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