SDL  2.0
SDL_wave.c File Reference
#include "../SDL_internal.h"
#include "SDL_audio.h"
#include "SDL_wave.h"
+ Include dependency graph for SDL_wave.c:

Go to the source code of this file.

Data Structures

struct  MS_ADPCM_decodestate
struct  MS_ADPCM_decoder
struct  IMA_ADPCM_decodestate
struct  IMA_ADPCM_decoder

Functions

static int ReadChunk (SDL_RWops *src, Chunk *chunk)
static int InitMS_ADPCM (WaveFMT *format)
static Sint32 MS_ADPCM_nibble (struct MS_ADPCM_decodestate *state, Uint8 nybble, Sint16 *coeff)
static int MS_ADPCM_decode (Uint8 **audio_buf, Uint32 *audio_len)
static int InitIMA_ADPCM (WaveFMT *format)
static Sint32 IMA_ADPCM_nibble (struct IMA_ADPCM_decodestate *state, Uint8 nybble)
static void Fill_IMA_ADPCM_block (Uint8 *decoded, Uint8 *encoded, int channel, int numchannels, struct IMA_ADPCM_decodestate *state)
static int IMA_ADPCM_decode (Uint8 **audio_buf, Uint32 *audio_len)
static int ConvertSint24ToSint32 (Uint8 **audio_buf, Uint32 *audio_len)
SDL_AudioSpecSDL_LoadWAV_RW (SDL_RWops *src, int freesrc, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
void SDL_FreeWAV (Uint8 *audio_buf)

Variables

static struct MS_ADPCM_decoder MS_ADPCM_state
static struct IMA_ADPCM_decoder IMA_ADPCM_state
static const Uint8 extensible_pcm_guid [16] = { 1, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 }
static const Uint8 extensible_ieee_guid [16] = { 3, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 }

Function Documentation

static int ConvertSint24ToSint32 ( Uint8 **  audio_buf,
Uint32 audio_len 
)
static

Definition at line 408 of file SDL_wave.c.

References i, SDL_OutOfMemory, and SDL_realloc.

Referenced by SDL_LoadWAV_RW().

{
const double DIVBY8388608 = 0.00000011920928955078125;
const Uint32 original_len = *audio_len;
const Uint32 samples = original_len / 3;
const Uint32 expanded_len = samples * sizeof (Uint32);
Uint8 *ptr = (Uint8 *) SDL_realloc(*audio_buf, expanded_len);
const Uint8 *src;
if (!ptr) {
return SDL_OutOfMemory();
}
*audio_buf = ptr;
*audio_len = expanded_len;
/* work from end to start, since we're expanding in-place. */
src = (ptr + original_len) - 3;
dst = ((Uint32 *) (ptr + expanded_len)) - 1;
for (i = 0; i < samples; i++) {
/* There's probably a faster way to do all this. */
const Sint32 converted = ((Sint32) ( (((Uint32) src[2]) << 24) |
(((Uint32) src[1]) << 16) |
(((Uint32) src[0]) << 8) )) >> 8;
const double scaled = (((double) converted) * DIVBY8388608);
src -= 3;
*(dst--) = (Sint32) (scaled * 2147483647.0);
}
return 0;
}
static void Fill_IMA_ADPCM_block ( Uint8 decoded,
Uint8 encoded,
int  channel,
int  numchannels,
struct IMA_ADPCM_decodestate state 
)
static

Definition at line 309 of file SDL_wave.c.

References i, and IMA_ADPCM_nibble().

Referenced by IMA_ADPCM_decode().

{
int i;
Sint8 nybble;
Sint32 new_sample;
decoded += (channel * 2);
for (i = 0; i < 4; ++i) {
nybble = (*encoded) & 0x0F;
new_sample = IMA_ADPCM_nibble(state, nybble);
decoded[0] = new_sample & 0xFF;
new_sample >>= 8;
decoded[1] = new_sample & 0xFF;
decoded += 2 * numchannels;
nybble = (*encoded) >> 4;
new_sample = IMA_ADPCM_nibble(state, nybble);
decoded[0] = new_sample & 0xFF;
new_sample >>= 8;
decoded[1] = new_sample & 0xFF;
decoded += 2 * numchannels;
++encoded;
}
}
static int IMA_ADPCM_decode ( Uint8 **  audio_buf,
Uint32 audio_len 
)
static

Definition at line 338 of file SDL_wave.c.

References WaveFMT::blockalign, WaveFMT::channels, Fill_IMA_ADPCM_block(), IMA_ADPCM_state, IMA_ADPCM_decodestate::index, NULL, IMA_ADPCM_decodestate::sample, SDL_arraysize, SDL_free, SDL_malloc, SDL_OutOfMemory, SDL_SetError, state, IMA_ADPCM_decoder::state, IMA_ADPCM_decoder::wavefmt, and IMA_ADPCM_decoder::wSamplesPerBlock.

Referenced by SDL_LoadWAV_RW().

{
Uint8 *freeable, *encoded, *decoded;
Sint32 encoded_len, samplesleft;
unsigned int c, channels;
/* Check to make sure we have enough variables in the state array */
if (channels > SDL_arraysize(IMA_ADPCM_state.state)) {
SDL_SetError("IMA ADPCM decoder can only handle %u channels",
return (-1);
}
/* Allocate the proper sized output buffer */
encoded_len = *audio_len;
encoded = *audio_buf;
freeable = *audio_buf;
*audio_len = (encoded_len / IMA_ADPCM_state.wavefmt.blockalign) *
*audio_buf = (Uint8 *) SDL_malloc(*audio_len);
if (*audio_buf == NULL) {
return SDL_OutOfMemory();
}
decoded = *audio_buf;
/* Get ready... Go! */
while (encoded_len >= IMA_ADPCM_state.wavefmt.blockalign) {
/* Grab the initial information for this block */
for (c = 0; c < channels; ++c) {
/* Fill the state information for this block */
state[c].sample = ((encoded[1] << 8) | encoded[0]);
encoded += 2;
if (state[c].sample & 0x8000) {
state[c].sample -= 0x10000;
}
state[c].index = *encoded++;
/* Reserved byte in buffer header, should be 0 */
if (*encoded++ != 0) {
/* Uh oh, corrupt data? Buggy code? */ ;
}
/* Store the initial sample we start with */
decoded[0] = (Uint8) (state[c].sample & 0xFF);
decoded[1] = (Uint8) (state[c].sample >> 8);
decoded += 2;
}
/* Decode and store the other samples in this block */
samplesleft = (IMA_ADPCM_state.wSamplesPerBlock - 1) * channels;
while (samplesleft > 0) {
for (c = 0; c < channels; ++c) {
Fill_IMA_ADPCM_block(decoded, encoded,
c, channels, &state[c]);
encoded += 4;
samplesleft -= 8;
}
decoded += (channels * 8 * 2);
}
}
SDL_free(freeable);
return (0);
}
static Sint32 IMA_ADPCM_nibble ( struct IMA_ADPCM_decodestate state,
Uint8  nybble 
)
static

Definition at line 254 of file SDL_wave.c.

References IMA_ADPCM_decodestate::index, and IMA_ADPCM_decodestate::sample.

Referenced by Fill_IMA_ADPCM_block().

{
const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
const Sint32 min_audioval = -(1 << (16 - 1));
const int index_table[16] = {
-1, -1, -1, -1,
2, 4, 6, 8,
-1, -1, -1, -1,
2, 4, 6, 8
};
const Sint32 step_table[89] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130,
143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408,
449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282,
1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350,
22385, 24623, 27086, 29794, 32767
};
Sint32 delta, step;
/* Compute difference and new sample value */
if (state->index > 88) {
state->index = 88;
} else if (state->index < 0) {
state->index = 0;
}
/* explicit cast to avoid gcc warning about using 'char' as array index */
step = step_table[(int)state->index];
delta = step >> 3;
if (nybble & 0x04)
delta += step;
if (nybble & 0x02)
delta += (step >> 1);
if (nybble & 0x01)
delta += (step >> 2);
if (nybble & 0x08)
delta = -delta;
state->sample += delta;
/* Update index value */
state->index += index_table[nybble];
/* Clamp output sample */
if (state->sample > max_audioval) {
state->sample = max_audioval;
} else if (state->sample < min_audioval) {
state->sample = min_audioval;
}
return (state->sample);
}
static int InitIMA_ADPCM ( WaveFMT format)
static

Definition at line 232 of file SDL_wave.c.

References WaveFMT::bitspersample, WaveFMT::blockalign, WaveFMT::byterate, WaveFMT::channels, WaveFMT::encoding, WaveFMT::frequency, IMA_ADPCM_state, SDL_SwapLE16, SDL_SwapLE32, IMA_ADPCM_decoder::wavefmt, and IMA_ADPCM_decoder::wSamplesPerBlock.

Referenced by SDL_LoadWAV_RW().

{
Uint8 *rogue_feel;
/* Set the rogue pointer to the IMA_ADPCM specific data */
rogue_feel = (Uint8 *) format + sizeof(*format);
if (sizeof(*format) == 16) {
/* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
rogue_feel += sizeof(Uint16);
}
IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
return (0);
}
static int InitMS_ADPCM ( WaveFMT format)
static

Definition at line 49 of file SDL_wave.c.

References MS_ADPCM_decoder::aCoeff, WaveFMT::bitspersample, WaveFMT::blockalign, WaveFMT::byterate, WaveFMT::channels, WaveFMT::encoding, WaveFMT::frequency, i, MS_ADPCM_state, SDL_SetError, SDL_SwapLE16, SDL_SwapLE32, MS_ADPCM_decoder::wavefmt, MS_ADPCM_decoder::wNumCoef, and MS_ADPCM_decoder::wSamplesPerBlock.

Referenced by SDL_LoadWAV_RW().

{
Uint8 *rogue_feel;
int i;
/* Set the rogue pointer to the MS_ADPCM specific data */
rogue_feel = (Uint8 *) format + sizeof(*format);
if (sizeof(*format) == 16) {
/* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
rogue_feel += sizeof(Uint16);
}
MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
rogue_feel += sizeof(Uint16);
MS_ADPCM_state.wNumCoef = ((rogue_feel[1] << 8) | rogue_feel[0]);
rogue_feel += sizeof(Uint16);
SDL_SetError("Unknown set of MS_ADPCM coefficients");
return (-1);
}
for (i = 0; i < MS_ADPCM_state.wNumCoef; ++i) {
MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1] << 8) | rogue_feel[0]);
rogue_feel += sizeof(Uint16);
MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1] << 8) | rogue_feel[0]);
rogue_feel += sizeof(Uint16);
}
return (0);
}
static int MS_ADPCM_decode ( Uint8 **  audio_buf,
Uint32 audio_len 
)
static

Definition at line 119 of file SDL_wave.c.

References MS_ADPCM_decoder::aCoeff, WaveFMT::blockalign, WaveFMT::channels, MS_ADPCM_decodestate::hPredictor, MS_ADPCM_decodestate::iDelta, MS_ADPCM_decodestate::iSamp1, MS_ADPCM_decodestate::iSamp2, MS_ADPCM_nibble(), MS_ADPCM_state, NULL, SDL_free, SDL_malloc, SDL_OutOfMemory, MS_ADPCM_decoder::state, state, MS_ADPCM_decoder::wavefmt, and MS_ADPCM_decoder::wSamplesPerBlock.

Referenced by SDL_LoadWAV_RW().

{
Uint8 *freeable, *encoded, *decoded;
Sint32 encoded_len, samplesleft;
Sint8 nybble;
Uint8 stereo;
Sint16 *coeff[2];
Sint32 new_sample;
/* Allocate the proper sized output buffer */
encoded_len = *audio_len;
encoded = *audio_buf;
freeable = *audio_buf;
*audio_len = (encoded_len / MS_ADPCM_state.wavefmt.blockalign) *
*audio_buf = (Uint8 *) SDL_malloc(*audio_len);
if (*audio_buf == NULL) {
return SDL_OutOfMemory();
}
decoded = *audio_buf;
/* Get ready... Go! */
stereo = (MS_ADPCM_state.wavefmt.channels == 2);
state[0] = &MS_ADPCM_state.state[0];
state[1] = &MS_ADPCM_state.state[stereo];
while (encoded_len >= MS_ADPCM_state.wavefmt.blockalign) {
/* Grab the initial information for this block */
state[0]->hPredictor = *encoded++;
if (stereo) {
state[1]->hPredictor = *encoded++;
}
state[0]->iDelta = ((encoded[1] << 8) | encoded[0]);
encoded += sizeof(Sint16);
if (stereo) {
state[1]->iDelta = ((encoded[1] << 8) | encoded[0]);
encoded += sizeof(Sint16);
}
state[0]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
encoded += sizeof(Sint16);
if (stereo) {
state[1]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
encoded += sizeof(Sint16);
}
state[0]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
encoded += sizeof(Sint16);
if (stereo) {
state[1]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
encoded += sizeof(Sint16);
}
coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor];
coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor];
/* Store the two initial samples we start with */
decoded[0] = state[0]->iSamp2 & 0xFF;
decoded[1] = state[0]->iSamp2 >> 8;
decoded += 2;
if (stereo) {
decoded[0] = state[1]->iSamp2 & 0xFF;
decoded[1] = state[1]->iSamp2 >> 8;
decoded += 2;
}
decoded[0] = state[0]->iSamp1 & 0xFF;
decoded[1] = state[0]->iSamp1 >> 8;
decoded += 2;
if (stereo) {
decoded[0] = state[1]->iSamp1 & 0xFF;
decoded[1] = state[1]->iSamp1 >> 8;
decoded += 2;
}
/* Decode and store the other samples in this block */
samplesleft = (MS_ADPCM_state.wSamplesPerBlock - 2) *
while (samplesleft > 0) {
nybble = (*encoded) >> 4;
new_sample = MS_ADPCM_nibble(state[0], nybble, coeff[0]);
decoded[0] = new_sample & 0xFF;
new_sample >>= 8;
decoded[1] = new_sample & 0xFF;
decoded += 2;
nybble = (*encoded) & 0x0F;
new_sample = MS_ADPCM_nibble(state[1], nybble, coeff[1]);
decoded[0] = new_sample & 0xFF;
new_sample >>= 8;
decoded[1] = new_sample & 0xFF;
decoded += 2;
++encoded;
samplesleft -= 2;
}
}
SDL_free(freeable);
return (0);
}
static Sint32 MS_ADPCM_nibble ( struct MS_ADPCM_decodestate state,
Uint8  nybble,
Sint16 coeff 
)
static

Definition at line 85 of file SDL_wave.c.

References MS_ADPCM_decodestate::iDelta, MS_ADPCM_decodestate::iSamp1, and MS_ADPCM_decodestate::iSamp2.

Referenced by MS_ADPCM_decode().

{
const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
const Sint32 min_audioval = -(1 << (16 - 1));
const Sint32 adaptive[] = {
230, 230, 230, 230, 307, 409, 512, 614,
768, 614, 512, 409, 307, 230, 230, 230
};
Sint32 new_sample, delta;
new_sample = ((state->iSamp1 * coeff[0]) +
(state->iSamp2 * coeff[1])) / 256;
if (nybble & 0x08) {
new_sample += state->iDelta * (nybble - 0x10);
} else {
new_sample += state->iDelta * nybble;
}
if (new_sample < min_audioval) {
new_sample = min_audioval;
} else if (new_sample > max_audioval) {
new_sample = max_audioval;
}
delta = ((Sint32) state->iDelta * adaptive[nybble]) / 256;
if (delta < 16) {
delta = 16;
}
state->iDelta = (Uint16) delta;
state->iSamp2 = state->iSamp1;
state->iSamp1 = (Sint16) new_sample;
return (new_sample);
}
static int ReadChunk ( SDL_RWops src,
Chunk chunk 
)
static

Definition at line 678 of file SDL_wave.c.

References Chunk::data, Chunk::length, Chunk::magic, NULL, SDL_EFREAD, SDL_Error, SDL_free, SDL_malloc, SDL_OutOfMemory, SDL_ReadLE32, and SDL_RWread.

Referenced by SDL_LoadWAV_RW().

{
chunk->magic = SDL_ReadLE32(src);
chunk->length = SDL_ReadLE32(src);
chunk->data = (Uint8 *) SDL_malloc(chunk->length);
if (chunk->data == NULL) {
return SDL_OutOfMemory();
}
if (SDL_RWread(src, chunk->data, chunk->length, 1) != 1) {
SDL_free(chunk->data);
chunk->data = NULL;
}
return (chunk->length);
}
void SDL_FreeWAV ( Uint8 audio_buf)

This function frees data previously allocated with SDL_LoadWAV_RW()

Definition at line 672 of file SDL_wave.c.

References SDL_free.

{
SDL_free(audio_buf);
}
SDL_AudioSpec* SDL_LoadWAV_RW ( SDL_RWops src,
int  freesrc,
SDL_AudioSpec spec,
Uint8 **  audio_buf,
Uint32 audio_len 
)

This function loads a WAVE from the data source, automatically freeing that source if freesrc is non-zero. For example, to load a WAVE file, you could do:

SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...);

If this function succeeds, it returns the given SDL_AudioSpec, filled with the audio data format of the wave data, and sets *audio_buf to a malloc()'d buffer containing the audio data, and sets *audio_len to the length of that audio buffer, in bytes. You need to free the audio buffer with SDL_FreeWAV() when you are done with it.

This function returns NULL and sets the SDL error message if the wave file cannot be opened, uses an unknown data format, or is corrupt. Currently raw and MS-ADPCM WAVE files are supported.

Definition at line 448 of file SDL_wave.c.

References AUDIO_F32, AUDIO_S16, AUDIO_S32, AUDIO_U8, BEXT, WaveFMT::bitspersample, WaveFMT::channels, SDL_AudioSpec::channels, ConvertSint24ToSint32(), DATA, Chunk::data, done, WaveFMT::encoding, EXTENSIBLE_CODE, extensible_ieee_guid, extensible_pcm_guid, FACT, FMT, SDL_AudioSpec::format, SDL_AudioSpec::freq, WaveFMT::frequency, IEEE_FLOAT_CODE, IMA_ADPCM_CODE, IMA_ADPCM_decode(), InitIMA_ADPCM(), InitMS_ADPCM(), JUNK, Chunk::length, LIST, Chunk::magic, MP3_CODE, MS_ADPCM_CODE, MS_ADPCM_decode(), NULL, PCM_CODE, ReadChunk(), RIFF, RW_SEEK_CUR, SDL_AudioSpec::samples, SDL_AUDIO_BITSIZE, SDL_free, SDL_memcmp, SDL_ReadLE32, SDL_RWclose, SDL_RWseek, SDL_SetError, SDL_SwapLE16, SDL_SwapLE32, SDL_zero, SDL_zerop, WaveExtensibleFMT::size, WaveExtensibleFMT::subformat, and WAVE.

{
int was_error;
Chunk chunk;
int lenread;
int IEEE_float_encoded, MS_ADPCM_encoded, IMA_ADPCM_encoded;
int samplesize;
/* WAV magic header */
Uint32 RIFFchunk;
Uint32 wavelen = 0;
Uint32 WAVEmagic;
Uint32 headerDiff = 0;
/* FMT chunk */
SDL_zero(chunk);
/* Make sure we are passed a valid data source */
was_error = 0;
if (src == NULL) {
was_error = 1;
goto done;
}
/* Check the magic header */
RIFFchunk = SDL_ReadLE32(src);
wavelen = SDL_ReadLE32(src);
if (wavelen == WAVE) { /* The RIFFchunk has already been read */
WAVEmagic = wavelen;
wavelen = RIFFchunk;
RIFFchunk = RIFF;
} else {
WAVEmagic = SDL_ReadLE32(src);
}
if ((RIFFchunk != RIFF) || (WAVEmagic != WAVE)) {
SDL_SetError("Unrecognized file type (not WAVE)");
was_error = 1;
goto done;
}
headerDiff += sizeof(Uint32); /* for WAVE */
/* Read the audio data format chunk */
chunk.data = NULL;
do {
SDL_free(chunk.data);
chunk.data = NULL;
lenread = ReadChunk(src, &chunk);
if (lenread < 0) {
was_error = 1;
goto done;
}
/* 2 Uint32's for chunk header+len, plus the lenread */
headerDiff += lenread + 2 * sizeof(Uint32);
} while ((chunk.magic == FACT) || (chunk.magic == LIST) || (chunk.magic == BEXT) || (chunk.magic == JUNK));
/* Decode the audio data format */
format = (WaveFMT *) chunk.data;
if (chunk.magic != FMT) {
SDL_SetError("Complex WAVE files not supported");
was_error = 1;
goto done;
}
IEEE_float_encoded = MS_ADPCM_encoded = IMA_ADPCM_encoded = 0;
switch (SDL_SwapLE16(format->encoding)) {
case PCM_CODE:
/* We can understand this */
break;
IEEE_float_encoded = 1;
/* We can understand this */
break;
/* Try to understand this */
if (InitMS_ADPCM(format) < 0) {
was_error = 1;
goto done;
}
MS_ADPCM_encoded = 1;
break;
/* Try to understand this */
if (InitIMA_ADPCM(format) < 0) {
was_error = 1;
goto done;
}
IMA_ADPCM_encoded = 1;
break;
/* note that this ignores channel masks, smaller valid bit counts
inside a larger container, and most subtypes. This is just enough
to get things that didn't really _need_ WAVE_FORMAT_EXTENSIBLE
to be useful working when they use this format flag. */
ext = (WaveExtensibleFMT *) format;
if (SDL_SwapLE16(ext->size) < 22) {
SDL_SetError("bogus extended .wav header");
was_error = 1;
goto done;
}
if (SDL_memcmp(ext->subformat, extensible_pcm_guid, 16) == 0) {
break; /* cool. */
} else if (SDL_memcmp(ext->subformat, extensible_ieee_guid, 16) == 0) {
IEEE_float_encoded = 1;
break;
}
break;
case MP3_CODE:
SDL_SetError("MPEG Layer 3 data not supported");
was_error = 1;
goto done;
default:
SDL_SetError("Unknown WAVE data format: 0x%.4x",
was_error = 1;
goto done;
}
SDL_zerop(spec);
spec->freq = SDL_SwapLE32(format->frequency);
if (IEEE_float_encoded) {
if ((SDL_SwapLE16(format->bitspersample)) != 32) {
was_error = 1;
} else {
spec->format = AUDIO_F32;
}
} else {
switch (SDL_SwapLE16(format->bitspersample)) {
case 4:
if (MS_ADPCM_encoded || IMA_ADPCM_encoded) {
spec->format = AUDIO_S16;
} else {
was_error = 1;
}
break;
case 8:
spec->format = AUDIO_U8;
break;
case 16:
spec->format = AUDIO_S16;
break;
case 24: /* convert this. */
spec->format = AUDIO_S32;
break;
case 32:
spec->format = AUDIO_S32;
break;
default:
was_error = 1;
break;
}
}
if (was_error) {
SDL_SetError("Unknown %d-bit PCM data format",
goto done;
}
spec->channels = (Uint8) SDL_SwapLE16(format->channels);
spec->samples = 4096; /* Good default buffer size */
/* Read the audio data chunk */
*audio_buf = NULL;
do {
SDL_free(*audio_buf);
*audio_buf = NULL;
lenread = ReadChunk(src, &chunk);
if (lenread < 0) {
was_error = 1;
goto done;
}
*audio_len = lenread;
*audio_buf = chunk.data;
if (chunk.magic != DATA)
headerDiff += lenread + 2 * sizeof(Uint32);
} while (chunk.magic != DATA);
headerDiff += 2 * sizeof(Uint32); /* for the data chunk and len */
if (MS_ADPCM_encoded) {
if (MS_ADPCM_decode(audio_buf, audio_len) < 0) {
was_error = 1;
goto done;
}
}
if (IMA_ADPCM_encoded) {
if (IMA_ADPCM_decode(audio_buf, audio_len) < 0) {
was_error = 1;
goto done;
}
}
if (SDL_SwapLE16(format->bitspersample) == 24) {
if (ConvertSint24ToSint32(audio_buf, audio_len) < 0) {
was_error = 1;
goto done;
}
}
/* Don't return a buffer that isn't a multiple of samplesize */
samplesize = ((SDL_AUDIO_BITSIZE(spec->format)) / 8) * spec->channels;
*audio_len &= ~(samplesize - 1);
SDL_free(format);
if (src) {
if (freesrc) {
} else {
/* seek to the end of the file (given by the RIFF chunk) */
SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR);
}
}
if (was_error) {
spec = NULL;
}
return (spec);
}

Variable Documentation

const Uint8 extensible_ieee_guid[16] = { 3, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 }
static

Definition at line 445 of file SDL_wave.c.

Referenced by SDL_LoadWAV_RW().

const Uint8 extensible_pcm_guid[16] = { 1, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 }
static

Definition at line 444 of file SDL_wave.c.

Referenced by SDL_LoadWAV_RW().

struct IMA_ADPCM_decoder IMA_ADPCM_state
static

Referenced by IMA_ADPCM_decode(), and InitIMA_ADPCM().

struct MS_ADPCM_decoder MS_ADPCM_state
static

Referenced by InitMS_ADPCM(), and MS_ADPCM_decode().