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