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