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_AudioSpec * | SDL_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

## ConvertSint24ToSint32()

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;
Uint32 *dst;
Uint32 i;
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;
}
dst
GLenum GLenum dst
Definition: SDL_opengl_glext.h:1737
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:181
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
src
GLenum src
Definition: SDL_opengl_glext.h:1737
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:175
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
samples
GLsizei samples
Definition: SDL_opengl_glext.h:1185

## Fill_IMA_ADPCM_block()

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;
}
}
Sint8
int8_t Sint8
Definition: SDL_stdinc.h:151
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:175
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
IMA_ADPCM_nibble
static Sint32 IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state, Uint8 nybble)
Definition: SDL_wave.c:254

## IMA_ADPCM_decode()

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().

{
struct IMA_ADPCM_decodestate *state;
Uint8 *freeable, *encoded, *decoded;
Sint32 encoded_len, samplesleft;
unsigned int c, channels;
/* Check to make sure we have enough variables in the state array */
channels = IMA_ADPCM_state.wavefmt.channels;
if (channels > SDL_arraysize(IMA_ADPCM_state.state)) {
SDL_SetError("IMA ADPCM decoder can only handle %u channels",
(unsigned int)SDL_arraysize(IMA_ADPCM_state.state));
return (-1);
}
state = IMA_ADPCM_state.state;
/* 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) *
IMA_ADPCM_state.wSamplesPerBlock *
IMA_ADPCM_state.wavefmt.channels * sizeof(Sint16);
*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);
}
encoded_len -= IMA_ADPCM_state.wavefmt.blockalign;
}
SDL_free(freeable);
return (0);
}
WaveFMT::blockalign
Uint16 blockalign
Definition: SDL_wave.h:56
IMA_ADPCM_decodestate
Definition: SDL_wave.c:218
Fill_IMA_ADPCM_block
static void Fill_IMA_ADPCM_block(Uint8 *decoded, Uint8 *encoded, int channel, int numchannels, struct IMA_ADPCM_decodestate *state)
Definition: SDL_wave.c:309
state
struct xkb_state * state
Definition: SDL_waylandsym.h:113
IMA_ADPCM_state
static struct IMA_ADPCM_decoder IMA_ADPCM_state
IMA_ADPCM_decoder::wavefmt
WaveFMT wavefmt
Definition: SDL_wave.c:225
WaveFMT::channels
Uint16 channels
Definition: SDL_wave.h:53
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
IMA_ADPCM_decoder::state
struct IMA_ADPCM_decodestate state[2]
Definition: SDL_wave.c:228
c
const GLubyte * c
Definition: SDL_opengl_glext.h:11093
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:175
IMA_ADPCM_decodestate::sample
Sint32 sample
Definition: SDL_wave.c:220
NULL
#define NULL
Definition: begin_code.h:164
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
IMA_ADPCM_decoder::wSamplesPerBlock
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:226
Sint16
int16_t Sint16
Definition: SDL_stdinc.h:163
IMA_ADPCM_decodestate::index
Sint8 index
Definition: SDL_wave.c:221

## IMA_ADPCM_nibble()

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);
}
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:175
IMA_ADPCM_decodestate::sample
Sint32 sample
Definition: SDL_wave.c:220
IMA_ADPCM_decodestate::index
Sint8 index
Definition: SDL_wave.c:221

## InitIMA_ADPCM()

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 */
IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
IMA_ADPCM_state.wavefmt.bitspersample =
SDL_SwapLE16(format->bitspersample);
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);
}
WaveFMT::blockalign
Uint16 blockalign
Definition: SDL_wave.h:56
IMA_ADPCM_state
static struct IMA_ADPCM_decoder IMA_ADPCM_state
WaveFMT::encoding
Uint16 encoding
Definition: SDL_wave.h:52
IMA_ADPCM_decoder::wavefmt
WaveFMT wavefmt
Definition: SDL_wave.c:225
WaveFMT::channels
Uint16 channels
Definition: SDL_wave.h:53
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_SwapLE32
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:233
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:169
IMA_ADPCM_decoder::wSamplesPerBlock
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:226
WaveFMT::frequency
Uint32 frequency
Definition: SDL_wave.h:54
WaveFMT::bitspersample
Uint16 bitspersample
Definition: SDL_wave.h:57
SDL_SwapLE16
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:232
WaveFMT::byterate
Uint32 byterate
Definition: SDL_wave.h:55

## InitMS_ADPCM()

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 */
MS_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
MS_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
MS_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
MS_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
MS_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
MS_ADPCM_state.wavefmt.bitspersample =
SDL_SwapLE16(format->bitspersample);
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);
if (MS_ADPCM_state.wNumCoef != 7) {
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);
}
MS_ADPCM_decoder::wNumCoef
Uint16 wNumCoef
Definition: SDL_wave.c:42
MS_ADPCM_decoder::wSamplesPerBlock
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:41
WaveFMT::blockalign
Uint16 blockalign
Definition: SDL_wave.h:56
WaveFMT::encoding
Uint16 encoding
Definition: SDL_wave.h:52
WaveFMT::channels
Uint16 channels
Definition: SDL_wave.h:53
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_SwapLE32
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:233
MS_ADPCM_decoder::aCoeff
Sint16 aCoeff[7][2]
Definition: SDL_wave.c:43
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:169
WaveFMT::frequency
Uint32 frequency
Definition: SDL_wave.h:54
WaveFMT::bitspersample
Uint16 bitspersample
Definition: SDL_wave.h:57
SDL_SwapLE16
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:232
WaveFMT::byterate
Uint32 byterate
Definition: SDL_wave.h:55
MS_ADPCM_decoder::wavefmt
WaveFMT wavefmt
Definition: SDL_wave.c:40
MS_ADPCM_state
static struct MS_ADPCM_decoder MS_ADPCM_state

## MS_ADPCM_decode()

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().

{
struct MS_ADPCM_decodestate *state[2];
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) *
MS_ADPCM_state.wSamplesPerBlock *
MS_ADPCM_state.wavefmt.channels * sizeof(Sint16);
*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) *
MS_ADPCM_state.wavefmt.channels;
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;
}
encoded_len -= MS_ADPCM_state.wavefmt.blockalign;
}
SDL_free(freeable);
return (0);
}
MS_ADPCM_decodestate::iDelta
Uint16 iDelta
Definition: SDL_wave.c:34
MS_ADPCM_decoder::wSamplesPerBlock
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:41
WaveFMT::blockalign
Uint16 blockalign
Definition: SDL_wave.h:56
state
struct xkb_state * state
Definition: SDL_waylandsym.h:113
MS_ADPCM_decoder::state
struct MS_ADPCM_decodestate state[2]
Definition: SDL_wave.c:45
MS_ADPCM_nibble
static Sint32 MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state, Uint8 nybble, Sint16 *coeff)
Definition: SDL_wave.c:85
WaveFMT::channels
Uint16 channels
Definition: SDL_wave.h:53
MS_ADPCM_decodestate::hPredictor
Uint8 hPredictor
Definition: SDL_wave.c:33
Sint8
int8_t Sint8
Definition: SDL_stdinc.h:151
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
MS_ADPCM_decoder::aCoeff
Sint16 aCoeff[7][2]
Definition: SDL_wave.c:43
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:175
NULL
#define NULL
Definition: begin_code.h:164
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
MS_ADPCM_decodestate::iSamp2
Sint16 iSamp2
Definition: SDL_wave.c:36
MS_ADPCM_decodestate::iSamp1
Sint16 iSamp1
Definition: SDL_wave.c:35
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
MS_ADPCM_decoder::wavefmt
WaveFMT wavefmt
Definition: SDL_wave.c:40
Sint16
int16_t Sint16
Definition: SDL_stdinc.h:163
MS_ADPCM_state
static struct MS_ADPCM_decoder MS_ADPCM_state
MS_ADPCM_decodestate
Definition: SDL_wave.c:31

## MS_ADPCM_nibble()

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);
}
MS_ADPCM_decodestate::iDelta
Uint16 iDelta
Definition: SDL_wave.c:34
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:175
MS_ADPCM_decodestate::iSamp2
Sint16 iSamp2
Definition: SDL_wave.c:36
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:169
MS_ADPCM_decodestate::iSamp1
Sint16 iSamp1
Definition: SDL_wave.c:35
Sint16
int16_t Sint16
Definition: SDL_stdinc.h:163

## ReadChunk()

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 SDL_Error(SDL_EFREAD);
}
return (chunk->length);
}
SDL_ReadLE32
#define SDL_ReadLE32
Definition: SDL_dynapi_overrides.h:359
SDL_RWread
#define SDL_RWread(ctx, ptr, size, n)
Definition: SDL_rwops.h:187
Chunk::length
Uint32 length
Definition: SDL_wave.h:64
SDL_Error
#define SDL_Error
Definition: SDL_dynapi_overrides.h:115
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_EFREAD
Definition: SDL_error.h:58
Chunk::data
Uint8 * data
Definition: SDL_wave.h:65
NULL
#define NULL
Definition: begin_code.h:164
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
Chunk::magic
Uint32 magic
Definition: SDL_wave.h:63
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374

## SDL_FreeWAV()

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_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377

## SDL_LoadWAV_RW()

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 */
WaveFMT *format = NULL;
WaveExtensibleFMT *ext = NULL;
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;
case IEEE_FLOAT_CODE:
IEEE_float_encoded = 1;
/* We can understand this */
break;
case MS_ADPCM_CODE:
/* Try to understand this */
if (InitMS_ADPCM(format) < 0) {
was_error = 1;
goto done;
}
MS_ADPCM_encoded = 1;
break;
case IMA_ADPCM_CODE:
/* Try to understand this */
if (InitIMA_ADPCM(format) < 0) {
was_error = 1;
goto done;
}
IMA_ADPCM_encoded = 1;
break;
case EXTENSIBLE_CODE:
/* 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",
SDL_SwapLE16(format->encoding));
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",
SDL_SwapLE16(format->bitspersample));
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);
done:
SDL_free(format);
if (src) {
if (freesrc) {
SDL_RWclose(src);
} 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);
}
InitIMA_ADPCM
static int InitIMA_ADPCM(WaveFMT *format)
Definition: SDL_wave.c:232
PCM_CODE
#define PCM_CODE
Definition: SDL_wave.h:36
RIFF
#define RIFF
Definition: SDL_wave.h:28
LIST
#define LIST
Definition: SDL_wave.h:31
WaveFMT
Definition: SDL_wave.h:46
MP3_CODE
#define MP3_CODE
Definition: SDL_wave.h:40
Chunk
Definition: SDL_wave.h:61
SDL_ReadLE32
#define SDL_ReadLE32
Definition: SDL_dynapi_overrides.h:359
Chunk::length
Uint32 length
Definition: SDL_wave.h:64
SDL_AudioSpec::samples
Uint16 samples
Definition: SDL_audio.h:183
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:181
WaveFMT::encoding
Uint16 encoding
Definition: SDL_wave.h:52
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
WaveExtensibleFMT::size
Uint16 size
Definition: SDL_wave.h:71
MS_ADPCM_decode
static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:119
WaveFMT::channels
Uint16 channels
Definition: SDL_wave.h:53
FMT
#define FMT
Definition: SDL_wave.h:34
SDL_RWseek
#define SDL_RWseek(ctx, offset, whence)
Definition: SDL_rwops.h:185
extensible_ieee_guid
static const Uint8 extensible_ieee_guid[16]
Definition: SDL_wave.c:445
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
AUDIO_U8
#define AUDIO_U8
Definition: SDL_audio.h:89
SDL_AudioSpec::freq
int freq
Definition: SDL_audio.h:179
DATA
#define DATA
Definition: SDL_wave.h:35
FACT
#define FACT
Definition: SDL_wave.h:30
SDL_AudioSpec::channels
Uint8 channels
Definition: SDL_audio.h:181
IMA_ADPCM_decode
static int IMA_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:338
WaveExtensibleFMT
Definition: SDL_wave.h:68
EXTENSIBLE_CODE
#define EXTENSIBLE_CODE
Definition: SDL_wave.h:41
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_AUDIO_BITSIZE
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
SDL_SwapLE32
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:233
ConvertSint24ToSint32
static int ConvertSint24ToSint32(Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:408
done
int done
Definition: checkkeys.c:28
AUDIO_S32
#define AUDIO_S32
Definition: SDL_audio.h:105
extensible_pcm_guid
static const Uint8 extensible_pcm_guid[16]
Definition: SDL_wave.c:444
WAVE
#define WAVE
Definition: SDL_wave.h:29
SDL_memcmp
#define SDL_memcmp
Definition: SDL_dynapi_overrides.h:389
JUNK
#define JUNK
Definition: SDL_wave.h:33
WaveExtensibleFMT::subformat
Uint8 subformat[16]
Definition: SDL_wave.h:74
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
Chunk::data
Uint8 * data
Definition: SDL_wave.h:65
NULL
#define NULL
Definition: begin_code.h:164
IEEE_FLOAT_CODE
#define IEEE_FLOAT_CODE
Definition: SDL_wave.h:38
SDL_RWclose
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
IMA_ADPCM_CODE
#define IMA_ADPCM_CODE
Definition: SDL_wave.h:39
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_AudioSpec::format
SDL_AudioFormat format
Definition: SDL_audio.h:180
InitMS_ADPCM
static int InitMS_ADPCM(WaveFMT *format)
Definition: SDL_wave.c:49
Chunk::magic
Uint32 magic
Definition: SDL_wave.h:63
AUDIO_S16
#define AUDIO_S16
Definition: SDL_audio.h:96
WaveFMT::frequency
Uint32 frequency
Definition: SDL_wave.h:54
RW_SEEK_CUR
#define RW_SEEK_CUR
Definition: SDL_rwops.h:175
WaveFMT::bitspersample
Uint16 bitspersample
Definition: SDL_wave.h:57
AUDIO_F32
#define AUDIO_F32
Definition: SDL_audio.h:114
SDL_SwapLE16
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:232
BEXT
#define BEXT
Definition: SDL_wave.h:32
ReadChunk
static int ReadChunk(SDL_RWops *src, Chunk *chunk)
Definition: SDL_wave.c:678
MS_ADPCM_CODE
#define MS_ADPCM_CODE
Definition: SDL_wave.h:37

## Variable Documentation

## extensible_ieee_guid

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().

## extensible_pcm_guid

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().

## IMA_ADPCM_state

struct IMA_ADPCM_decoder IMA_ADPCM_state

static

Referenced by IMA_ADPCM_decode(), and InitIMA_ADPCM().

## MS_ADPCM_state

struct MS_ADPCM_decoder MS_ADPCM_state

static

Referenced by InitMS_ADPCM(), and MS_ADPCM_decode().