gpu_neon: fix some missing ebuf updates
[pcsx_rearmed.git] / deps / libretro-common / formats / wav / rwav.c
1 /* Copyright  (C) 2010-2020 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (rwav.c).
5  * ---------------------------------------------------------------------------------------
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include <stdio.h>
24 #include <stdint.h>
25 #include <stdarg.h>
26 #include <stddef.h> /* ptrdiff_t on osx */
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <formats/rwav.h>
31
32 enum
33 {
34    ITER_BEGIN,
35    ITER_COPY_SAMPLES,
36    ITER_COPY_SAMPLES_8,
37    ITER_COPY_SAMPLES_16
38 };
39
40 struct rwav_iterator
41 {
42    rwav_t *out;
43    const uint8_t *data;
44    size_t size;
45    size_t i, j;
46    int step;
47 };
48
49 void rwav_init(rwav_iterator_t* iter, rwav_t* out, const void* buf, size_t size)
50 {
51    iter->out    = out;
52    iter->data   = (const uint8_t*)buf;
53    iter->size   = size;
54    iter->step   = ITER_BEGIN;
55
56    out->samples = NULL;
57 }
58
59 enum rwav_state rwav_iterate(rwav_iterator_t *iter)
60 {
61    size_t s;
62    uint16_t *u16       = NULL;
63    void *samples       = NULL;
64    rwav_t *rwav        = iter->out;
65    const uint8_t *data = iter->data;
66
67    switch (iter->step)
68    {
69       case ITER_BEGIN:
70          if (iter->size < 44)
71             return RWAV_ITERATE_ERROR; /* buffer is smaller than an empty wave file */
72
73          if (data[0] != 'R' || data[1] != 'I' || data[2] != 'F' || data[3] != 'F')
74             return RWAV_ITERATE_ERROR;
75
76          if (data[8] != 'W' || data[9] != 'A' || data[10] != 'V' || data[11] != 'E')
77             return RWAV_ITERATE_ERROR;
78
79          if (data[12] != 'f' || data[13] != 'm' || data[14] != 't' || data[15] != ' ')
80             return RWAV_ITERATE_ERROR; /* we don't support non-PCM or compressed data */
81
82          if (data[16] != 16 || data[17] != 0 || data[18] != 0 || data[19] != 0)
83             return RWAV_ITERATE_ERROR;
84
85          if (data[20] != 1 || data[21] != 0)
86             return RWAV_ITERATE_ERROR; /* we don't support non-PCM or compressed data */
87
88          if (data[36] != 'd' || data[37] != 'a' || data[38] != 't' || data[39] != 'a')
89             return RWAV_ITERATE_ERROR;
90
91          rwav->bitspersample = data[34] | data[35] << 8;
92
93          if (rwav->bitspersample != 8 && rwav->bitspersample != 16)
94             return RWAV_ITERATE_ERROR; /* we only support 8 and 16 bps */
95
96          rwav->subchunk2size = data[40] | data[41] << 8 | data[42] << 16 | data[43] << 24;
97
98          if ((rwav->subchunk2size < 1) ||
99              (rwav->subchunk2size > iter->size - 44))
100             return RWAV_ITERATE_ERROR; /* too few bytes in buffer */
101
102          samples = malloc(rwav->subchunk2size);
103
104          if (!samples)
105             return RWAV_ITERATE_ERROR;
106
107          rwav->numchannels = data[22] | data[23] << 8;
108          rwav->numsamples  = rwav->subchunk2size * 8 / rwav->bitspersample / rwav->numchannels;
109          rwav->samplerate  = data[24] | data[25] << 8 | data[26] << 16 | data[27] << 24;
110          rwav->samples     = samples;
111
112          iter->step = ITER_COPY_SAMPLES;
113          return RWAV_ITERATE_MORE;
114
115       case ITER_COPY_SAMPLES:
116          iter->i = 0;
117
118          if (rwav->bitspersample == 8)
119          {
120             iter->step = ITER_COPY_SAMPLES_8;
121
122             /* TODO/FIXME - what is going on here? */
123             case ITER_COPY_SAMPLES_8:
124             s = rwav->subchunk2size - iter->i;
125
126             if (s > RWAV_ITERATE_BUF_SIZE)
127                s = RWAV_ITERATE_BUF_SIZE;
128
129             memcpy((void*)((uint8_t*)rwav->samples + iter->i), (void *)(iter->data + 44 + iter->i), s);
130             iter->i += s;
131          }
132          else
133          {
134             iter->step = ITER_COPY_SAMPLES_16;
135             iter->j    = 0;
136
137             /* TODO/FIXME - what is going on here? */
138             case ITER_COPY_SAMPLES_16:
139             s = rwav->subchunk2size - iter->i;
140
141             if (s > RWAV_ITERATE_BUF_SIZE)
142                s = RWAV_ITERATE_BUF_SIZE;
143
144             u16 = (uint16_t *)rwav->samples;
145
146             while (s != 0)
147             {
148                u16[iter->j++] = iter->data[44 + iter->i] | iter->data[45 + iter->i] << 8;
149                iter->i += 2;
150                s -= 2;
151             }
152          }
153
154          if (iter->i < rwav->subchunk2size)
155             return RWAV_ITERATE_MORE;
156          return RWAV_ITERATE_DONE;
157    }
158
159    return RWAV_ITERATE_ERROR;
160 }
161
162 enum rwav_state rwav_load(rwav_t* out, const void* buf, size_t size)
163 {
164    enum rwav_state res;
165    rwav_iterator_t iter;
166
167    iter.out             = NULL;
168    iter.data            = NULL;
169    iter.size            = 0;
170    iter.i               = 0;
171    iter.j               = 0;
172    iter.step            = 0;
173
174    rwav_init(&iter, out, buf, size);
175
176    do
177    {
178       res = rwav_iterate(&iter);
179    }while (res == RWAV_ITERATE_MORE);
180
181    return res;
182 }
183
184 void rwav_free(rwav_t *rwav)
185 {
186    free((void*)rwav->samples);
187 }