1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | #define SG_BUILD_LIBRARY |
16 | #include <siege/audio/buffer.h> |
17 | |
18 | #include <stdlib.h> |
19 | #include <string.h> |
20 | |
21 | #include <al.h> |
22 | #include <alc.h> |
23 | |
24 | #include "../internal/stb/stb_vorbis.h" |
25 | |
26 | |
27 | #define ALBUF(x)(*(ALuint*)(x)->handle) (*(ALuint*)(x)->handle) |
28 | |
29 | |
30 | static void* toStereo(SGuint channels, void* data, size_t* datalen, ALuint* alformat) |
31 | { |
32 | void* odata = data; |
33 | if(channels == 2) |
| 6 | | Assuming 'channels' is not equal to 2 | |
|
| |
34 | { |
35 | if(*alformat == AL_FORMAT_MONO80x1100) |
36 | *alformat = AL_FORMAT_STEREO80x1102; |
37 | else |
38 | *alformat = AL_FORMAT_STEREO160x1103; |
39 | } |
40 | else if(channels > 2) |
| 8 | | Assuming 'channels' is > 2 | |
|
| |
41 | { |
42 | SGuint chan; |
43 | SGuint i; |
44 | long double sum1; |
45 | long double sum2; |
46 | int num1; |
47 | int num2; |
48 | if(*alformat == AL_FORMAT_MONO80x1100) |
| |
49 | { |
50 | odata = malloc(*datalen * sizeof(SGubyte)); |
51 | memcpy(odata, data, *datalen * sizeof(SGubyte)); |
52 | |
53 | *alformat = AL_FORMAT_STEREO80x1102; |
54 | SGubyte* bdata = (SGubyte*) odata; |
55 | |
56 | for(i = 0; i < *datalen; i += channels) |
57 | { |
58 | sum1 = 0; |
59 | num1 = 0; |
60 | sum2 = 0; |
61 | num2 = 0; |
62 | |
63 | if(channels % 2 != 0) |
64 | { |
65 | chan = 1; |
66 | sum1 += bdata[i / channels] * 0.5L; |
67 | num1++; |
68 | sum2 += bdata[i / channels] * 0.5L; |
69 | num2++; |
70 | } |
71 | else |
72 | chan = 0; |
73 | for(; chan < channels; chan++) |
74 | { |
75 | if(chan % 2 == 0) |
76 | { |
77 | sum1 += bdata[i + chan]; |
78 | num1++; |
79 | } |
80 | else |
81 | { |
82 | sum2 += bdata[i + chan]; |
83 | num2++; |
84 | } |
85 | } |
86 | bdata[i / channels ] = (SGubyte)(sum1 / num1); |
87 | bdata[i / channels + 1] = (SGubyte)(sum2 / num2); |
88 | } |
89 | } |
90 | else |
91 | { |
92 | odata = malloc(*datalen * sizeof(SGushort)); |
| 11 | | Call to 'malloc' has an allocation size of 0 bytes |
|
93 | memcpy(odata, data, *datalen * sizeof(SGushort)); |
94 | |
95 | *alformat = AL_FORMAT_STEREO160x1103; |
96 | SGshort* sdata = (SGshort*) odata; |
97 | |
98 | for(i = 0; i < *datalen / 2; i += channels) |
99 | { |
100 | sum1 = 0; |
101 | num1 = 0; |
102 | sum2 = 0; |
103 | num2 = 0; |
104 | |
105 | if(channels % 2 != 0) |
106 | { |
107 | chan = 1; |
108 | sum1 += sdata[i / channels] * 0.5L; |
109 | num1++; |
110 | sum2 += sdata[i / channels] * 0.5L; |
111 | num2++; |
112 | } |
113 | else |
114 | chan = 0; |
115 | for(; chan < channels; chan++) |
116 | { |
117 | if(chan % 2 == 0) |
118 | { |
119 | sum1 += sdata[i + chan]; |
120 | num1++; |
121 | } |
122 | else |
123 | { |
124 | sum2 += sdata[i + chan]; |
125 | num2++; |
126 | } |
127 | } |
128 | sdata[i / channels ] = (SGushort)(sum1 / num1); |
129 | sdata[i / channels + 1] = (SGushort)(sum2 / num2); |
130 | } |
131 | } |
132 | *datalen = *datalen / channels * 2; |
133 | } |
134 | return odata; |
135 | } |
136 | |
137 | SGAudioBuffer* SG_CALL__cdecl sgAudioBufferCreateStream(SGStream* stream, SGbool delstream) |
138 | { |
139 | if(!stream || !stream->read || !stream->seek || !stream->tell) return NULL((void*)0); |
140 | |
141 | SGAudioBuffer* buffer = malloc(sizeof(SGAudioBuffer)); |
142 | if(!buffer) goto error; |
143 | |
144 | buffer->stream = stream; |
145 | buffer->del = delstream; |
146 | |
147 | buffer->handle = malloc(sizeof(ALuint)); |
148 | if(!buffer->handle) goto error; |
149 | alGenBuffers(1, buffer->handle); |
150 | |
151 | SGuint channels; |
152 | SGuint format; |
153 | SGuint frequency; |
154 | void* data = NULL((void*)0); |
155 | SGuint datalen; |
156 | SGuint nsamples; |
157 | |
158 | void* buf = NULL((void*)0); |
159 | int error = 0; |
160 | stb_vorbis* stb = NULL((void*)0); |
161 | stb_vorbis_info info; |
162 | |
163 | SGlong pos = sgStreamTell(stream); |
164 | SGlong size = sgStreamTellSize(stream); |
165 | size -= pos; |
166 | if(pos < 0 || size < 0) |
167 | goto lderr; |
168 | |
169 | buf = malloc(size); |
170 | if(sgStreamRead(stream, buf, 1, size) != size) |
171 | goto lderr; |
172 | |
173 | stb = stb_vorbis_open_memory(buf, size, &error, NULL((void*)0)); |
174 | if(!stb) goto lderr; |
175 | |
176 | info = stb_vorbis_get_info(stb); |
177 | channels = info.channels; |
178 | frequency = info.sample_rate; |
179 | format = SG_AUDIO_FORMAT_S160x02; |
180 | |
181 | nsamples = stb_vorbis_stream_length_in_samples(stb); |
182 | datalen = 2 * nsamples * channels; |
183 | data = malloc(datalen); |
184 | |
185 | datalen = 2 * stb_vorbis_get_samples_short_interleaved(stb, info.channels, data, datalen / 2); |
186 | |
187 | sgAudioBufferSetData(buffer, channels, format, frequency, data, datalen); |
188 | free(data); |
189 | |
190 | lderr: |
191 | if(stb) |
192 | stb_vorbis_close(stb); |
193 | if(buf) |
194 | free(buf); |
195 | return buffer; |
196 | |
197 | error: |
198 | if(buffer) |
199 | free(buffer); |
200 | return NULL((void*)0); |
201 | } |
202 | SGAudioBuffer* SG_CALL__cdecl sgAudioBufferCreateFile(const char* fname) |
203 | { |
204 | return sgAudioBufferCreateStream(sgStreamCreateFile(fname, "r"), SG_TRUE1); |
205 | } |
206 | void SG_CALL__cdecl sgAudioBufferDestroy(SGAudioBuffer* buffer) |
207 | { |
208 | if(buffer == NULL((void*)0)) |
209 | return; |
210 | |
211 | alDeleteBuffers(1, buffer->handle); |
212 | free(buffer->handle); |
213 | if(buffer->del) |
214 | sgStreamDestroy(buffer->stream); |
215 | free(buffer); |
216 | } |
217 | |
218 | void SG_CALL__cdecl sgAudioBufferSetData(SGAudioBuffer* buffer, SGuint channels, SGuint format, SGuint frequency, void* data, size_t datalen) |
219 | { |
220 | |
221 | ALuint alformat; |
222 | |
223 | SGuint i; |
224 | SGubyte* bdata = (SGubyte*)data; |
225 | SGshort* scur; |
226 | SGint* icur; |
227 | SGfloat* fcur; |
228 | SGdouble* dcur; |
229 | switch(format) |
| 1 | Control jumps to 'case 11:' at line 302 | |
|
230 | { |
231 | case SG_AUDIO_FORMAT_S80x01: |
232 | alformat = AL_FORMAT_MONO80x1100; |
233 | for(i = 0; i < datalen; i++) |
234 | bdata[i] = bdata[i] + 0x80; |
235 | break; |
236 | case SG_AUDIO_FORMAT_S160x02: |
237 | alformat = AL_FORMAT_MONO160x1101; |
238 | break; |
239 | case SG_AUDIO_FORMAT_S240x03: |
240 | alformat = AL_FORMAT_MONO160x1101; |
241 | for(i = 0; i < datalen; i += 3) |
242 | { |
243 | icur = (SGint*)&bdata[i]; |
244 | scur = (SGshort*)&bdata[i / 3 * 2]; |
245 | *scur = (SGshort)((*icur >> 8) / 256.0L); |
246 | } |
247 | datalen = datalen / 3 * 2; |
248 | break; |
249 | case SG_AUDIO_FORMAT_S320x04: |
250 | alformat = AL_FORMAT_MONO160x1101; |
251 | for(i = 0; i < datalen; i += 4) |
252 | { |
253 | icur = (SGint*)&bdata[i]; |
254 | scur = (SGshort*)&bdata[i / 4 * 2]; |
255 | *scur = (SGshort)(*icur / 65536.0L); |
256 | } |
257 | datalen = datalen / 4 * 2; |
258 | break; |
259 | |
260 | case SG_AUDIO_FORMAT_U80x05: |
261 | alformat = AL_FORMAT_MONO80x1100; |
262 | break; |
263 | case SG_AUDIO_FORMAT_U160x06: |
264 | alformat = AL_FORMAT_MONO160x1101; |
265 | for(i = 0; i < datalen; i += 2) |
266 | { |
267 | scur = (SGshort*)&bdata[i]; |
268 | *scur = *scur - 0x7FFF; |
269 | } |
270 | break; |
271 | case SG_AUDIO_FORMAT_U240x07: |
272 | alformat = AL_FORMAT_MONO160x1101; |
273 | for(i = 0; i < datalen; i += 3) |
274 | { |
275 | icur = (SGint*)&bdata[i]; |
276 | scur = (SGshort*)&bdata[i / 3 * 2]; |
277 | *scur = (SGshort)((*icur >> 8) / 256.0L) - 0x7FFF; |
278 | } |
279 | datalen = datalen / 3 * 2; |
280 | break; |
281 | case SG_AUDIO_FORMAT_U320x08: |
282 | alformat = AL_FORMAT_MONO160x1101; |
283 | for(i = 0; i < datalen; i += 4) |
284 | { |
285 | icur = (SGint*)&bdata[i]; |
286 | scur = (SGshort*)&bdata[i / 4 * 2]; |
287 | *scur = (SGshort)(*icur / 65536.0L) - 0x7FFF; |
288 | } |
289 | datalen = datalen / 4 * 2; |
290 | break; |
291 | |
292 | case SG_AUDIO_FORMAT_F0x0A: |
293 | alformat = AL_FORMAT_MONO160x1101; |
294 | for(i = 0; i < datalen; i += 4) |
295 | { |
296 | fcur = (SGfloat*)&bdata[i]; |
297 | scur = (SGshort*)&bdata[i / 4 * 2]; |
298 | *scur = (SGshort)(*fcur * 0xFFFF); |
299 | } |
300 | datalen = datalen / 4 * 2; |
301 | break; |
302 | case SG_AUDIO_FORMAT_D0x0B: |
303 | alformat = AL_FORMAT_MONO160x1101; |
304 | for(i = 0; i < datalen; i += 8) |
| 2 | | Assuming 'i' is >= 'datalen' | |
|
| 3 | | Loop condition is false. Execution continues on line 310 | |
|
305 | { |
306 | dcur = (SGdouble*)&bdata[i]; |
307 | scur = (SGshort*)&bdata[i / 8 * 2]; |
308 | *scur = (SGshort)(*dcur * 0xFFFF); |
309 | } |
310 | datalen = datalen / 8 * 2; |
311 | break; |
| 4 | | Execution continues on line 315 | |
|
312 | default: |
313 | return; |
314 | } |
315 | void* odata = toStereo(channels, data, &datalen, &alformat); |
| |
316 | alBufferData(ALBUF(buffer)(*(ALuint*)(buffer)->handle), alformat, odata, datalen, frequency); |
317 | if(data != odata) |
318 | free(odata); |
319 | } |