|
1 /* |
|
2 SDL - Simple DirectMedia Layer |
|
3 Copyright (C) 1997-2006 Sam Lantinga |
|
4 |
|
5 This library is free software; you can redistribute it and/or |
|
6 modify it under the terms of the GNU Lesser General Public |
|
7 License as published by the Free Software Foundation; either |
|
8 version 2.1 of the License, or (at your option) any later version. |
|
9 |
|
10 This library is distributed in the hope that it will be useful, |
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 Lesser General Public License for more details. |
|
14 |
|
15 You should have received a copy of the GNU Lesser General Public |
|
16 License along with this library; if not, write to the Free Software |
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
18 |
|
19 Sam Lantinga |
|
20 slouken@libsdl.org |
|
21 */ |
|
22 #include "SDL_config.h" |
|
23 |
|
24 /* Microsoft WAVE file loading routines */ |
|
25 |
|
26 #include "SDL_audio.h" |
|
27 #include "SDL_wave.h" |
|
28 |
|
29 |
|
30 static int ReadChunk(SDL_RWops *src, Chunk *chunk); |
|
31 |
|
32 struct MS_ADPCM_decodestate { |
|
33 Uint8 hPredictor; |
|
34 Uint16 iDelta; |
|
35 Sint16 iSamp1; |
|
36 Sint16 iSamp2; |
|
37 }; |
|
38 static struct MS_ADPCM_decoder { |
|
39 WaveFMT wavefmt; |
|
40 Uint16 wSamplesPerBlock; |
|
41 Uint16 wNumCoef; |
|
42 Sint16 aCoeff[7][2]; |
|
43 /* * * */ |
|
44 struct MS_ADPCM_decodestate state[2]; |
|
45 } MS_ADPCM_state; |
|
46 |
|
47 static int InitMS_ADPCM(WaveFMT *format) |
|
48 { |
|
49 Uint8 *rogue_feel; |
|
50 Uint16 extra_info; |
|
51 int i; |
|
52 |
|
53 /* Set the rogue pointer to the MS_ADPCM specific data */ |
|
54 MS_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding); |
|
55 MS_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels); |
|
56 MS_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency); |
|
57 MS_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate); |
|
58 MS_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign); |
|
59 MS_ADPCM_state.wavefmt.bitspersample = |
|
60 SDL_SwapLE16(format->bitspersample); |
|
61 rogue_feel = (Uint8 *)format+sizeof(*format); |
|
62 if ( sizeof(*format) == 16 ) { |
|
63 extra_info = ((rogue_feel[1]<<8)|rogue_feel[0]); |
|
64 rogue_feel += sizeof(Uint16); |
|
65 } |
|
66 MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1]<<8)|rogue_feel[0]); |
|
67 rogue_feel += sizeof(Uint16); |
|
68 MS_ADPCM_state.wNumCoef = ((rogue_feel[1]<<8)|rogue_feel[0]); |
|
69 rogue_feel += sizeof(Uint16); |
|
70 if ( MS_ADPCM_state.wNumCoef != 7 ) { |
|
71 SDL_SetError("Unknown set of MS_ADPCM coefficients"); |
|
72 return(-1); |
|
73 } |
|
74 for ( i=0; i<MS_ADPCM_state.wNumCoef; ++i ) { |
|
75 MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1]<<8)|rogue_feel[0]); |
|
76 rogue_feel += sizeof(Uint16); |
|
77 MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1]<<8)|rogue_feel[0]); |
|
78 rogue_feel += sizeof(Uint16); |
|
79 } |
|
80 return(0); |
|
81 } |
|
82 |
|
83 static Sint32 MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state, |
|
84 Uint8 nybble, Sint16 *coeff) |
|
85 { |
|
86 const Sint32 max_audioval = ((1<<(16-1))-1); |
|
87 const Sint32 min_audioval = -(1<<(16-1)); |
|
88 const Sint32 adaptive[] = { |
|
89 230, 230, 230, 230, 307, 409, 512, 614, |
|
90 768, 614, 512, 409, 307, 230, 230, 230 |
|
91 }; |
|
92 Sint32 new_sample, delta; |
|
93 |
|
94 new_sample = ((state->iSamp1 * coeff[0]) + |
|
95 (state->iSamp2 * coeff[1]))/256; |
|
96 if ( nybble & 0x08 ) { |
|
97 new_sample += state->iDelta * (nybble-0x10); |
|
98 } else { |
|
99 new_sample += state->iDelta * nybble; |
|
100 } |
|
101 if ( new_sample < min_audioval ) { |
|
102 new_sample = min_audioval; |
|
103 } else |
|
104 if ( new_sample > max_audioval ) { |
|
105 new_sample = max_audioval; |
|
106 } |
|
107 delta = ((Sint32)state->iDelta * adaptive[nybble])/256; |
|
108 if ( delta < 16 ) { |
|
109 delta = 16; |
|
110 } |
|
111 state->iDelta = (Uint16)delta; |
|
112 state->iSamp2 = state->iSamp1; |
|
113 state->iSamp1 = (Sint16)new_sample; |
|
114 return(new_sample); |
|
115 } |
|
116 |
|
117 static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len) |
|
118 { |
|
119 struct MS_ADPCM_decodestate *state[2]; |
|
120 Uint8 *freeable, *encoded, *decoded; |
|
121 Sint32 encoded_len, samplesleft; |
|
122 Sint8 nybble, stereo; |
|
123 Sint16 *coeff[2]; |
|
124 Sint32 new_sample; |
|
125 |
|
126 /* Allocate the proper sized output buffer */ |
|
127 encoded_len = *audio_len; |
|
128 encoded = *audio_buf; |
|
129 freeable = *audio_buf; |
|
130 *audio_len = (encoded_len/MS_ADPCM_state.wavefmt.blockalign) * |
|
131 MS_ADPCM_state.wSamplesPerBlock* |
|
132 MS_ADPCM_state.wavefmt.channels*sizeof(Sint16); |
|
133 *audio_buf = (Uint8 *)SDL_malloc(*audio_len); |
|
134 if ( *audio_buf == NULL ) { |
|
135 SDL_Error(SDL_ENOMEM); |
|
136 return(-1); |
|
137 } |
|
138 decoded = *audio_buf; |
|
139 |
|
140 /* Get ready... Go! */ |
|
141 stereo = (MS_ADPCM_state.wavefmt.channels == 2); |
|
142 state[0] = &MS_ADPCM_state.state[0]; |
|
143 state[1] = &MS_ADPCM_state.state[stereo]; |
|
144 while ( encoded_len >= MS_ADPCM_state.wavefmt.blockalign ) { |
|
145 /* Grab the initial information for this block */ |
|
146 state[0]->hPredictor = *encoded++; |
|
147 if ( stereo ) { |
|
148 state[1]->hPredictor = *encoded++; |
|
149 } |
|
150 state[0]->iDelta = ((encoded[1]<<8)|encoded[0]); |
|
151 encoded += sizeof(Sint16); |
|
152 if ( stereo ) { |
|
153 state[1]->iDelta = ((encoded[1]<<8)|encoded[0]); |
|
154 encoded += sizeof(Sint16); |
|
155 } |
|
156 state[0]->iSamp1 = ((encoded[1]<<8)|encoded[0]); |
|
157 encoded += sizeof(Sint16); |
|
158 if ( stereo ) { |
|
159 state[1]->iSamp1 = ((encoded[1]<<8)|encoded[0]); |
|
160 encoded += sizeof(Sint16); |
|
161 } |
|
162 state[0]->iSamp2 = ((encoded[1]<<8)|encoded[0]); |
|
163 encoded += sizeof(Sint16); |
|
164 if ( stereo ) { |
|
165 state[1]->iSamp2 = ((encoded[1]<<8)|encoded[0]); |
|
166 encoded += sizeof(Sint16); |
|
167 } |
|
168 coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor]; |
|
169 coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor]; |
|
170 |
|
171 /* Store the two initial samples we start with */ |
|
172 decoded[0] = state[0]->iSamp2&0xFF; |
|
173 decoded[1] = state[0]->iSamp2>>8; |
|
174 decoded += 2; |
|
175 if ( stereo ) { |
|
176 decoded[0] = state[1]->iSamp2&0xFF; |
|
177 decoded[1] = state[1]->iSamp2>>8; |
|
178 decoded += 2; |
|
179 } |
|
180 decoded[0] = state[0]->iSamp1&0xFF; |
|
181 decoded[1] = state[0]->iSamp1>>8; |
|
182 decoded += 2; |
|
183 if ( stereo ) { |
|
184 decoded[0] = state[1]->iSamp1&0xFF; |
|
185 decoded[1] = state[1]->iSamp1>>8; |
|
186 decoded += 2; |
|
187 } |
|
188 |
|
189 /* Decode and store the other samples in this block */ |
|
190 samplesleft = (MS_ADPCM_state.wSamplesPerBlock-2)* |
|
191 MS_ADPCM_state.wavefmt.channels; |
|
192 while ( samplesleft > 0 ) { |
|
193 nybble = (*encoded)>>4; |
|
194 new_sample = MS_ADPCM_nibble(state[0],nybble,coeff[0]); |
|
195 decoded[0] = new_sample&0xFF; |
|
196 new_sample >>= 8; |
|
197 decoded[1] = new_sample&0xFF; |
|
198 decoded += 2; |
|
199 |
|
200 nybble = (*encoded)&0x0F; |
|
201 new_sample = MS_ADPCM_nibble(state[1],nybble,coeff[1]); |
|
202 decoded[0] = new_sample&0xFF; |
|
203 new_sample >>= 8; |
|
204 decoded[1] = new_sample&0xFF; |
|
205 decoded += 2; |
|
206 |
|
207 ++encoded; |
|
208 samplesleft -= 2; |
|
209 } |
|
210 encoded_len -= MS_ADPCM_state.wavefmt.blockalign; |
|
211 } |
|
212 SDL_free(freeable); |
|
213 return(0); |
|
214 } |
|
215 |
|
216 struct IMA_ADPCM_decodestate { |
|
217 Sint32 sample; |
|
218 Sint8 index; |
|
219 }; |
|
220 static struct IMA_ADPCM_decoder { |
|
221 WaveFMT wavefmt; |
|
222 Uint16 wSamplesPerBlock; |
|
223 /* * * */ |
|
224 struct IMA_ADPCM_decodestate state[2]; |
|
225 } IMA_ADPCM_state; |
|
226 |
|
227 static int InitIMA_ADPCM(WaveFMT *format) |
|
228 { |
|
229 Uint8 *rogue_feel; |
|
230 Uint16 extra_info; |
|
231 |
|
232 /* Set the rogue pointer to the IMA_ADPCM specific data */ |
|
233 IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding); |
|
234 IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels); |
|
235 IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency); |
|
236 IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate); |
|
237 IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign); |
|
238 IMA_ADPCM_state.wavefmt.bitspersample = |
|
239 SDL_SwapLE16(format->bitspersample); |
|
240 rogue_feel = (Uint8 *)format+sizeof(*format); |
|
241 if ( sizeof(*format) == 16 ) { |
|
242 extra_info = ((rogue_feel[1]<<8)|rogue_feel[0]); |
|
243 rogue_feel += sizeof(Uint16); |
|
244 } |
|
245 IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1]<<8)|rogue_feel[0]); |
|
246 return(0); |
|
247 } |
|
248 |
|
249 static Sint32 IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state,Uint8 nybble) |
|
250 { |
|
251 const Sint32 max_audioval = ((1<<(16-1))-1); |
|
252 const Sint32 min_audioval = -(1<<(16-1)); |
|
253 const int index_table[16] = { |
|
254 -1, -1, -1, -1, |
|
255 2, 4, 6, 8, |
|
256 -1, -1, -1, -1, |
|
257 2, 4, 6, 8 |
|
258 }; |
|
259 const Sint32 step_table[89] = { |
|
260 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, |
|
261 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, |
|
262 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, |
|
263 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, |
|
264 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, |
|
265 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, |
|
266 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, |
|
267 22385, 24623, 27086, 29794, 32767 |
|
268 }; |
|
269 Sint32 delta, step; |
|
270 |
|
271 /* Compute difference and new sample value */ |
|
272 step = step_table[state->index]; |
|
273 delta = step >> 3; |
|
274 if ( nybble & 0x04 ) delta += step; |
|
275 if ( nybble & 0x02 ) delta += (step >> 1); |
|
276 if ( nybble & 0x01 ) delta += (step >> 2); |
|
277 if ( nybble & 0x08 ) delta = -delta; |
|
278 state->sample += delta; |
|
279 |
|
280 /* Update index value */ |
|
281 state->index += index_table[nybble]; |
|
282 if ( state->index > 88 ) { |
|
283 state->index = 88; |
|
284 } else |
|
285 if ( state->index < 0 ) { |
|
286 state->index = 0; |
|
287 } |
|
288 |
|
289 /* Clamp output sample */ |
|
290 if ( state->sample > max_audioval ) { |
|
291 state->sample = max_audioval; |
|
292 } else |
|
293 if ( state->sample < min_audioval ) { |
|
294 state->sample = min_audioval; |
|
295 } |
|
296 return(state->sample); |
|
297 } |
|
298 |
|
299 /* Fill the decode buffer with a channel block of data (8 samples) */ |
|
300 static void Fill_IMA_ADPCM_block(Uint8 *decoded, Uint8 *encoded, |
|
301 int channel, int numchannels, struct IMA_ADPCM_decodestate *state) |
|
302 { |
|
303 int i; |
|
304 Sint8 nybble; |
|
305 Sint32 new_sample; |
|
306 |
|
307 decoded += (channel * 2); |
|
308 for ( i=0; i<4; ++i ) { |
|
309 nybble = (*encoded)&0x0F; |
|
310 new_sample = IMA_ADPCM_nibble(state, nybble); |
|
311 decoded[0] = new_sample&0xFF; |
|
312 new_sample >>= 8; |
|
313 decoded[1] = new_sample&0xFF; |
|
314 decoded += 2 * numchannels; |
|
315 |
|
316 nybble = (*encoded)>>4; |
|
317 new_sample = IMA_ADPCM_nibble(state, nybble); |
|
318 decoded[0] = new_sample&0xFF; |
|
319 new_sample >>= 8; |
|
320 decoded[1] = new_sample&0xFF; |
|
321 decoded += 2 * numchannels; |
|
322 |
|
323 ++encoded; |
|
324 } |
|
325 } |
|
326 |
|
327 static int IMA_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len) |
|
328 { |
|
329 struct IMA_ADPCM_decodestate *state; |
|
330 Uint8 *freeable, *encoded, *decoded; |
|
331 Sint32 encoded_len, samplesleft; |
|
332 unsigned int c, channels; |
|
333 |
|
334 /* Check to make sure we have enough variables in the state array */ |
|
335 channels = IMA_ADPCM_state.wavefmt.channels; |
|
336 if ( channels > SDL_arraysize(IMA_ADPCM_state.state) ) { |
|
337 SDL_SetError("IMA ADPCM decoder can only handle %d channels", |
|
338 SDL_arraysize(IMA_ADPCM_state.state)); |
|
339 return(-1); |
|
340 } |
|
341 state = IMA_ADPCM_state.state; |
|
342 |
|
343 /* Allocate the proper sized output buffer */ |
|
344 encoded_len = *audio_len; |
|
345 encoded = *audio_buf; |
|
346 freeable = *audio_buf; |
|
347 *audio_len = (encoded_len/IMA_ADPCM_state.wavefmt.blockalign) * |
|
348 IMA_ADPCM_state.wSamplesPerBlock* |
|
349 IMA_ADPCM_state.wavefmt.channels*sizeof(Sint16); |
|
350 *audio_buf = (Uint8 *)SDL_malloc(*audio_len); |
|
351 if ( *audio_buf == NULL ) { |
|
352 SDL_Error(SDL_ENOMEM); |
|
353 return(-1); |
|
354 } |
|
355 decoded = *audio_buf; |
|
356 |
|
357 /* Get ready... Go! */ |
|
358 while ( encoded_len >= IMA_ADPCM_state.wavefmt.blockalign ) { |
|
359 /* Grab the initial information for this block */ |
|
360 for ( c=0; c<channels; ++c ) { |
|
361 /* Fill the state information for this block */ |
|
362 state[c].sample = ((encoded[1]<<8)|encoded[0]); |
|
363 encoded += 2; |
|
364 if ( state[c].sample & 0x8000 ) { |
|
365 state[c].sample -= 0x10000; |
|
366 } |
|
367 state[c].index = *encoded++; |
|
368 /* Reserved byte in buffer header, should be 0 */ |
|
369 if ( *encoded++ != 0 ) { |
|
370 /* Uh oh, corrupt data? Buggy code? */; |
|
371 } |
|
372 |
|
373 /* Store the initial sample we start with */ |
|
374 decoded[0] = (Uint8)(state[c].sample&0xFF); |
|
375 decoded[1] = (Uint8)(state[c].sample>>8); |
|
376 decoded += 2; |
|
377 } |
|
378 |
|
379 /* Decode and store the other samples in this block */ |
|
380 samplesleft = (IMA_ADPCM_state.wSamplesPerBlock-1)*channels; |
|
381 while ( samplesleft > 0 ) { |
|
382 for ( c=0; c<channels; ++c ) { |
|
383 Fill_IMA_ADPCM_block(decoded, encoded, |
|
384 c, channels, &state[c]); |
|
385 encoded += 4; |
|
386 samplesleft -= 8; |
|
387 } |
|
388 decoded += (channels * 8 * 2); |
|
389 } |
|
390 encoded_len -= IMA_ADPCM_state.wavefmt.blockalign; |
|
391 } |
|
392 SDL_free(freeable); |
|
393 return(0); |
|
394 } |
|
395 |
|
396 SDL_AudioSpec * SDL_LoadWAV_RW (SDL_RWops *src, int freesrc, |
|
397 SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) |
|
398 { |
|
399 int was_error; |
|
400 Chunk chunk; |
|
401 int lenread; |
|
402 int MS_ADPCM_encoded, IMA_ADPCM_encoded; |
|
403 int samplesize; |
|
404 |
|
405 /* WAV magic header */ |
|
406 Uint32 RIFFchunk; |
|
407 Uint32 wavelen = 0; |
|
408 Uint32 WAVEmagic; |
|
409 Uint32 headerDiff = 0; |
|
410 |
|
411 /* FMT chunk */ |
|
412 WaveFMT *format = NULL; |
|
413 |
|
414 /* Make sure we are passed a valid data source */ |
|
415 was_error = 0; |
|
416 if ( src == NULL ) { |
|
417 was_error = 1; |
|
418 goto done; |
|
419 } |
|
420 |
|
421 /* Check the magic header */ |
|
422 RIFFchunk = SDL_ReadLE32(src); |
|
423 wavelen = SDL_ReadLE32(src); |
|
424 if ( wavelen == WAVE ) { /* The RIFFchunk has already been read */ |
|
425 WAVEmagic = wavelen; |
|
426 wavelen = RIFFchunk; |
|
427 RIFFchunk = RIFF; |
|
428 } else { |
|
429 WAVEmagic = SDL_ReadLE32(src); |
|
430 } |
|
431 if ( (RIFFchunk != RIFF) || (WAVEmagic != WAVE) ) { |
|
432 SDL_SetError("Unrecognized file type (not WAVE)"); |
|
433 was_error = 1; |
|
434 goto done; |
|
435 } |
|
436 headerDiff += sizeof(Uint32); /* for WAVE */ |
|
437 |
|
438 /* Read the audio data format chunk */ |
|
439 chunk.data = NULL; |
|
440 do { |
|
441 if ( chunk.data != NULL ) { |
|
442 SDL_free(chunk.data); |
|
443 } |
|
444 lenread = ReadChunk(src, &chunk); |
|
445 if ( lenread < 0 ) { |
|
446 was_error = 1; |
|
447 goto done; |
|
448 } |
|
449 /* 2 Uint32's for chunk header+len, plus the lenread */ |
|
450 headerDiff += lenread + 2 * sizeof(Uint32); |
|
451 } while ( (chunk.magic == FACT) || (chunk.magic == LIST) ); |
|
452 |
|
453 /* Decode the audio data format */ |
|
454 format = (WaveFMT *)chunk.data; |
|
455 if ( chunk.magic != FMT ) { |
|
456 SDL_SetError("Complex WAVE files not supported"); |
|
457 was_error = 1; |
|
458 goto done; |
|
459 } |
|
460 MS_ADPCM_encoded = IMA_ADPCM_encoded = 0; |
|
461 switch (SDL_SwapLE16(format->encoding)) { |
|
462 case PCM_CODE: |
|
463 /* We can understand this */ |
|
464 break; |
|
465 case MS_ADPCM_CODE: |
|
466 /* Try to understand this */ |
|
467 if ( InitMS_ADPCM(format) < 0 ) { |
|
468 was_error = 1; |
|
469 goto done; |
|
470 } |
|
471 MS_ADPCM_encoded = 1; |
|
472 break; |
|
473 case IMA_ADPCM_CODE: |
|
474 /* Try to understand this */ |
|
475 if ( InitIMA_ADPCM(format) < 0 ) { |
|
476 was_error = 1; |
|
477 goto done; |
|
478 } |
|
479 IMA_ADPCM_encoded = 1; |
|
480 break; |
|
481 case MP3_CODE: |
|
482 SDL_SetError("MPEG Layer 3 data not supported", |
|
483 SDL_SwapLE16(format->encoding)); |
|
484 was_error = 1; |
|
485 goto done; |
|
486 default: |
|
487 SDL_SetError("Unknown WAVE data format: 0x%.4x", |
|
488 SDL_SwapLE16(format->encoding)); |
|
489 was_error = 1; |
|
490 goto done; |
|
491 } |
|
492 SDL_memset(spec, 0, (sizeof *spec)); |
|
493 spec->freq = SDL_SwapLE32(format->frequency); |
|
494 switch (SDL_SwapLE16(format->bitspersample)) { |
|
495 case 4: |
|
496 if ( MS_ADPCM_encoded || IMA_ADPCM_encoded ) { |
|
497 spec->format = AUDIO_S16; |
|
498 } else { |
|
499 was_error = 1; |
|
500 } |
|
501 break; |
|
502 case 8: |
|
503 spec->format = AUDIO_U8; |
|
504 break; |
|
505 case 16: |
|
506 spec->format = AUDIO_S16; |
|
507 break; |
|
508 default: |
|
509 was_error = 1; |
|
510 break; |
|
511 } |
|
512 if ( was_error ) { |
|
513 SDL_SetError("Unknown %d-bit PCM data format", |
|
514 SDL_SwapLE16(format->bitspersample)); |
|
515 goto done; |
|
516 } |
|
517 spec->channels = (Uint8)SDL_SwapLE16(format->channels); |
|
518 spec->samples = 4096; /* Good default buffer size */ |
|
519 |
|
520 /* Read the audio data chunk */ |
|
521 *audio_buf = NULL; |
|
522 do { |
|
523 if ( *audio_buf != NULL ) { |
|
524 SDL_free(*audio_buf); |
|
525 } |
|
526 lenread = ReadChunk(src, &chunk); |
|
527 if ( lenread < 0 ) { |
|
528 was_error = 1; |
|
529 goto done; |
|
530 } |
|
531 *audio_len = lenread; |
|
532 *audio_buf = chunk.data; |
|
533 if(chunk.magic != DATA) headerDiff += lenread + 2 * sizeof(Uint32); |
|
534 } while ( chunk.magic != DATA ); |
|
535 headerDiff += 2 * sizeof(Uint32); /* for the data chunk and len */ |
|
536 |
|
537 if ( MS_ADPCM_encoded ) { |
|
538 if ( MS_ADPCM_decode(audio_buf, audio_len) < 0 ) { |
|
539 was_error = 1; |
|
540 goto done; |
|
541 } |
|
542 } |
|
543 if ( IMA_ADPCM_encoded ) { |
|
544 if ( IMA_ADPCM_decode(audio_buf, audio_len) < 0 ) { |
|
545 was_error = 1; |
|
546 goto done; |
|
547 } |
|
548 } |
|
549 |
|
550 /* Don't return a buffer that isn't a multiple of samplesize */ |
|
551 samplesize = ((spec->format & 0xFF)/8)*spec->channels; |
|
552 *audio_len &= ~(samplesize-1); |
|
553 |
|
554 done: |
|
555 if ( format != NULL ) { |
|
556 SDL_free(format); |
|
557 } |
|
558 if ( src ) { |
|
559 if ( freesrc ) { |
|
560 SDL_RWclose(src); |
|
561 } else { |
|
562 /* seek to the end of the file (given by the RIFF chunk) */ |
|
563 SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR); |
|
564 } |
|
565 } |
|
566 if ( was_error ) { |
|
567 spec = NULL; |
|
568 } |
|
569 return(spec); |
|
570 } |
|
571 |
|
572 /* Since the WAV memory is allocated in the shared library, it must also |
|
573 be freed here. (Necessary under Win32, VC++) |
|
574 */ |
|
575 void SDL_FreeWAV(Uint8 *audio_buf) |
|
576 { |
|
577 if ( audio_buf != NULL ) { |
|
578 SDL_free(audio_buf); |
|
579 } |
|
580 } |
|
581 |
|
582 static int ReadChunk(SDL_RWops *src, Chunk *chunk) |
|
583 { |
|
584 chunk->magic = SDL_ReadLE32(src); |
|
585 chunk->length = SDL_ReadLE32(src); |
|
586 chunk->data = (Uint8 *)SDL_malloc(chunk->length); |
|
587 if ( chunk->data == NULL ) { |
|
588 SDL_Error(SDL_ENOMEM); |
|
589 return(-1); |
|
590 } |
|
591 if ( SDL_RWread(src, chunk->data, chunk->length, 1) != 1 ) { |
|
592 SDL_Error(SDL_EFREAD); |
|
593 SDL_free(chunk->data); |
|
594 return(-1); |
|
595 } |
|
596 return(chunk->length); |
|
597 } |