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) |
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) |
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)); |
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 | SGAudioBuffer* buffer = malloc(sizeof(SGAudioBuffer)); |
| |
140 | |
141 | buffer->stream = stream; |
142 | buffer->del = delstream; |
143 | |
144 | buffer->handle = malloc(sizeof(ALuint)); |
145 | alGenBuffers(1, buffer->handle); |
146 | |
147 | SGuint channels; |
148 | SGuint format; |
149 | SGuint frequency; |
150 | void* data = NULL((void*)0); |
151 | SGuint datalen; |
152 | SGuint nsamples; |
153 | |
154 | void* buf = NULL((void*)0); |
155 | int error = 0; |
156 | stb_vorbis* stb = NULL((void*)0); |
157 | stb_vorbis_info info; |
158 | |
159 | if(!stream || !stream->read || !stream->seek || !stream->tell) |
| 3 | | Assuming 'stream' is null | |
|
160 | return NULL((void*)0); |
| 4 | | Within the expansion of the macro 'NULL':
|
a | Potential leak of memory pointed to by 'buffer' |
|
161 | |
162 | SGlong pos = sgStreamTell(stream); |
163 | SGlong size = sgStreamTellSize(stream); |
164 | size -= pos; |
165 | if(pos < 0 || size < 0) |
166 | goto lderr; |
167 | |
168 | buf = malloc(size); |
169 | if(sgStreamRead(stream, buf, 1, size) != size) |
170 | goto lderr; |
171 | |
172 | stb = stb_vorbis_open_memory(buf, size, &error, NULL((void*)0)); |
173 | if(!stb) goto lderr; |
174 | |
175 | info = stb_vorbis_get_info(stb); |
176 | channels = info.channels; |
177 | frequency = info.sample_rate; |
178 | format = SG_AUDIO_FORMAT_S160x02; |
179 | |
180 | nsamples = stb_vorbis_stream_length_in_samples(stb); |
181 | datalen = 2 * nsamples * channels; |
182 | data = malloc(datalen); |
183 | |
184 | datalen = 2 * stb_vorbis_get_samples_short_interleaved(stb, info.channels, data, datalen / 2); |
185 | |
186 | sgAudioBufferSetData(buffer, channels, format, frequency, data, datalen); |
187 | free(data); |
188 | |
189 | lderr: |
190 | if(stb) |
191 | stb_vorbis_close(stb); |
192 | if(buf) |
193 | free(buf); |
194 | |
195 | return buffer; |
196 | } |
197 | SGAudioBuffer* SG_CALL__cdecl sgAudioBufferCreateFile(const char* fname) |
198 | { |
199 | return sgAudioBufferCreateStream(sgStreamCreateFile(fname, "r"), SG_TRUE1); |
| 1 | Calling 'sgAudioBufferCreateStream' | |
|
200 | } |
201 | void SG_CALL__cdecl sgAudioBufferDestroy(SGAudioBuffer* buffer) |
202 | { |
203 | if(buffer == NULL((void*)0)) |
204 | return; |
205 | |
206 | alDeleteBuffers(1, buffer->handle); |
207 | free(buffer->handle); |
208 | if(buffer->del) |
209 | sgStreamDestroy(buffer->stream); |
210 | free(buffer); |
211 | } |
212 | |
213 | void SG_CALL__cdecl sgAudioBufferSetData(SGAudioBuffer* buffer, SGuint channels, SGuint format, SGuint frequency, void* data, size_t datalen) |
214 | { |
215 | |
216 | ALuint alformat; |
217 | |
218 | SGuint i; |
219 | SGubyte* bdata = (SGubyte*)data; |
220 | SGshort* scur; |
221 | SGint* icur; |
222 | SGfloat* fcur; |
223 | SGdouble* dcur; |
224 | switch(format) |
225 | { |
226 | case SG_AUDIO_FORMAT_S80x01: |
227 | alformat = AL_FORMAT_MONO80x1100; |
228 | for(i = 0; i < datalen; i++) |
229 | bdata[i] = bdata[i] + 0x80; |
230 | break; |
231 | case SG_AUDIO_FORMAT_S160x02: |
232 | alformat = AL_FORMAT_MONO160x1101; |
233 | break; |
234 | case SG_AUDIO_FORMAT_S240x03: |
235 | alformat = AL_FORMAT_MONO160x1101; |
236 | for(i = 0; i < datalen; i += 3) |
237 | { |
238 | icur = (SGint*)&bdata[i]; |
239 | scur = (SGshort*)&bdata[i / 3 * 2]; |
240 | *scur = (SGshort)((*icur >> 8) / 256.0L); |
241 | } |
242 | datalen = datalen / 3 * 2; |
243 | break; |
244 | case SG_AUDIO_FORMAT_S320x04: |
245 | alformat = AL_FORMAT_MONO160x1101; |
246 | for(i = 0; i < datalen; i += 4) |
247 | { |
248 | icur = (SGint*)&bdata[i]; |
249 | scur = (SGshort*)&bdata[i / 4 * 2]; |
250 | *scur = (SGshort)(*icur / 65536.0L); |
251 | } |
252 | datalen = datalen / 4 * 2; |
253 | break; |
254 | |
255 | case SG_AUDIO_FORMAT_U80x05: |
256 | alformat = AL_FORMAT_MONO80x1100; |
257 | break; |
258 | case SG_AUDIO_FORMAT_U160x06: |
259 | alformat = AL_FORMAT_MONO160x1101; |
260 | for(i = 0; i < datalen; i += 2) |
261 | { |
262 | scur = (SGshort*)&bdata[i]; |
263 | *scur = *scur - 0x7FFF; |
264 | } |
265 | break; |
266 | case SG_AUDIO_FORMAT_U240x07: |
267 | alformat = AL_FORMAT_MONO160x1101; |
268 | for(i = 0; i < datalen; i += 3) |
269 | { |
270 | icur = (SGint*)&bdata[i]; |
271 | scur = (SGshort*)&bdata[i / 3 * 2]; |
272 | *scur = (SGshort)((*icur >> 8) / 256.0L) - 0x7FFF; |
273 | } |
274 | datalen = datalen / 3 * 2; |
275 | break; |
276 | case SG_AUDIO_FORMAT_U320x08: |
277 | alformat = AL_FORMAT_MONO160x1101; |
278 | for(i = 0; i < datalen; i += 4) |
279 | { |
280 | icur = (SGint*)&bdata[i]; |
281 | scur = (SGshort*)&bdata[i / 4 * 2]; |
282 | *scur = (SGshort)(*icur / 65536.0L) - 0x7FFF; |
283 | } |
284 | datalen = datalen / 4 * 2; |
285 | break; |
286 | |
287 | case SG_AUDIO_FORMAT_F0x0A: |
288 | alformat = AL_FORMAT_MONO160x1101; |
289 | for(i = 0; i < datalen; i += 4) |
290 | { |
291 | fcur = (SGfloat*)&bdata[i]; |
292 | scur = (SGshort*)&bdata[i / 4 * 2]; |
293 | *scur = (SGshort)(*fcur * 0xFFFF); |
294 | } |
295 | datalen = datalen / 4 * 2; |
296 | break; |
297 | case SG_AUDIO_FORMAT_D0x0B: |
298 | alformat = AL_FORMAT_MONO160x1101; |
299 | for(i = 0; i < datalen; i += 8) |
300 | { |
301 | dcur = (SGdouble*)&bdata[i]; |
302 | scur = (SGshort*)&bdata[i / 8 * 2]; |
303 | *scur = (SGshort)(*dcur * 0xFFFF); |
304 | } |
305 | datalen = datalen / 8 * 2; |
306 | break; |
307 | default: |
308 | return; |
309 | } |
310 | void* odata = toStereo(channels, data, &datalen, &alformat); |
311 | alBufferData(ALBUF(buffer)(*(ALuint*)(buffer)->handle), alformat, odata, datalen, frequency); |
312 | if(data != odata) |
313 | free(odata); |
314 | } |