SDL_wave.c File Reference
`#include "../SDL_internal.h"`
`#include "SDL_log.h"`
`#include "SDL_hints.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 | ADPCM_DecoderState
struct | MS_ADPCM_CoeffData
struct | MS_ADPCM_ChannelState
struct | WaveExtensibleGUID

## Macros

#define | SIZE_MAX ((size_t)-1)
#define | INT_MAX SDL_MAX_SINT32
#define | WAVE_FORMATTAG_GUID(tag) {(tag) & 0xff, (tag) >> 8, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113}

## Functions

static int | SafeMult (size_t *f1, size_t f2)
static Sint64 | WaveAdjustToFactValue (WaveFile *file, Sint64 sampleframes)
static int | MS_ADPCM_CalculateSampleFrames (WaveFile *file, size_t datalength)
static int | MS_ADPCM_Init (WaveFile *file, size_t datalength)
static Sint16 | MS_ADPCM_ProcessNibble (MS_ADPCM_ChannelState *cstate, Sint32 sample1, Sint32 sample2, Uint8 nybble)
static int | MS_ADPCM_DecodeBlockHeader (ADPCM_DecoderState *state)
static int | MS_ADPCM_DecodeBlockData (ADPCM_DecoderState *state)
static int | MS_ADPCM_Decode (WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
static int | IMA_ADPCM_CalculateSampleFrames (WaveFile *file, size_t datalength)
static int | IMA_ADPCM_Init (WaveFile *file, size_t datalength)
static Sint16 | IMA_ADPCM_ProcessNibble (Sint8 *cindex, Sint16 lastsample, Uint8 nybble)
static int | IMA_ADPCM_DecodeBlockHeader (ADPCM_DecoderState *state)
static int | IMA_ADPCM_DecodeBlockData (ADPCM_DecoderState *state)
static int | IMA_ADPCM_Decode (WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
static int | LAW_Init (WaveFile *file, size_t datalength)
static int | LAW_Decode (WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
static int | PCM_Init (WaveFile *file, size_t datalength)
static int | PCM_ConvertSint24ToSint32 (WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
static int | PCM_Decode (WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
static WaveRiffSizeHint | WaveGetRiffSizeHint ()
static WaveTruncationHint | WaveGetTruncationHint ()
static WaveFactChunkHint | WaveGetFactChunkHint ()
static void | WaveFreeChunkData (WaveChunk *chunk)
static int | WaveNextChunk (SDL_RWops *src, WaveChunk *chunk)
static int | WaveReadPartialChunkData (SDL_RWops *src, WaveChunk *chunk, size_t length)
static int | WaveReadChunkData (SDL_RWops *src, WaveChunk *chunk)
static Uint16 | WaveGetFormatGUIDEncoding (WaveFormat *format)
static int | WaveReadFormat (WaveFile *file)
static int | WaveCheckFormat (WaveFile *file, size_t datalength)
static int | WaveLoad (SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, 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)
| Load the audio data of a WAVE file into memory. More...
void | SDL_FreeWAV (Uint8 *audio_buf)

## Variables

static WaveExtensibleGUID | extensible_guids []

## Macro Definition Documentation

## INT_MAX

#define INT_MAX SDL_MAX_SINT32

Definition at line 31 of file SDL_wave.c.

## SIZE_MAX

#define SIZE_MAX ((size_t)-1)

Definition at line 27 of file SDL_wave.c.

## WAVE_FORMATTAG_GUID

#define WAVE_FORMATTAG_GUID | ( |  | tag | ) | {(tag) & 0xff, (tag) >> 8, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113}

Definition at line 1594 of file SDL_wave.c.

## Function Documentation

## IMA_ADPCM_CalculateSampleFrames()

static int IMA_ADPCM_CalculateSampleFrames | ( | WaveFile * | file,
|  | size_t | datalength
| ) |  |

static

Definition at line 741 of file SDL_wave.c.

{
WaveFormat *format = &file->format;
const size_t blockheadersize = (size_t)format->channels * 4;
const size_t subblockframesize = (size_t)format->channels * 4;
const size_t availableblocks = datalength / format->blockalign;
const size_t trailingdata = datalength % format->blockalign;
if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
/* The size of the data chunk must be a multiple of the block size. */
if (datalength < blockheadersize || trailingdata > 0) {
return SDL_SetError("Truncated IMA ADPCM block");
}
}
/* Calculate number of sample frames that will be decoded. */
file->sampleframes = (Uint64)availableblocks * format->samplesperblock;
if (trailingdata > 0) {
/* The last block is truncated. Check if we can get any samples out of it. */
if (file->trunchint == TruncDropFrame && trailingdata > blockheadersize - 2) {
/* The sample frame in the header of the truncated block is present.
* Drop incomplete sample frames.
*/
size_t trailingsamples = 1;
if (trailingdata > blockheadersize) {
/* More data following after the header. */
const size_t trailingblockdata = trailingdata - blockheadersize;
const size_t trailingsubblockdata = trailingblockdata % subblockframesize;
trailingsamples += (trailingblockdata / subblockframesize) * 8;
/* Due to the interleaved sub-blocks, the last 4 bytes determine
* how many samples of the truncated sub-block are lost.
*/
if (trailingsubblockdata > subblockframesize - 4) {
trailingsamples += (trailingsubblockdata % 4) * 2;
}
}
if (trailingsamples > format->samplesperblock) {
trailingsamples = format->samplesperblock;
}
file->sampleframes += trailingsamples;
}
}
file->sampleframes = WaveAdjustToFactValue(file, file->sampleframes);
if (file->sampleframes < 0) {
return -1;
}
return 0;
}

References WaveFormat::channels, WaveFile::format, WaveFile::sampleframes, SDL_SetError, TruncDropFrame, WaveFile::trunchint, TruncStrict, TruncVeryStrict, and WaveAdjustToFactValue().

Referenced by IMA_ADPCM_Decode(), and IMA_ADPCM_Init().

## IMA_ADPCM_Decode()

static int IMA_ADPCM_Decode | ( | WaveFile * | file,
|  | Uint8 ** | audio_buf,
|  | Uint32 * | audio_len
| ) |  |

static

Definition at line 1037 of file SDL_wave.c.

{
int result;
size_t bytesleft, outputsize;
WaveChunk *chunk = &file->chunk;
ADPCM_DecoderState state;
Sint8 *cstate;
if (chunk->size != chunk->length) {
/* Could not read everything. Recalculate number of sample frames. */
if (IMA_ADPCM_CalculateSampleFrames(file, chunk->size) < 0) {
return -1;
}
}
/* Nothing to decode, nothing to return. */
if (file->sampleframes == 0) {
*audio_buf = NULL;
*audio_len = 0;
return 0;
}
SDL_zero(state);
state.channels = file->format.channels;
state.blocksize = file->format.blockalign;
state.blockheadersize = (size_t)state.channels * 4;
state.samplesperblock = file->format.samplesperblock;
state.framesize = state.channels * sizeof(Sint16);
state.framestotal = file->sampleframes;
state.framesleft = state.framestotal;
state.input.data = chunk->data;
state.input.size = chunk->size;
state.input.pos = 0;
/* The output size in bytes. May get modified if data is truncated. */
outputsize = (size_t)state.framestotal;
if (SafeMult(&outputsize, state.framesize)) {
return SDL_OutOfMemory();
} else if (outputsize > SDL_MAX_UINT32 || state.framestotal > SIZE_MAX) {
return SDL_SetError("WAVE file too big");
}
state.output.pos = 0;
state.output.size = outputsize / sizeof(Sint16);
state.output.data = (Sint16 *)SDL_malloc(outputsize);
if (state.output.data == NULL) {
return SDL_OutOfMemory();
}
cstate = (Sint8 *)SDL_calloc(state.channels, sizeof(Sint8));
if (cstate == NULL) {
SDL_free(state.output.data);
return SDL_OutOfMemory();
}
state.cstate = cstate;
/* Decode block by block. A truncated block will stop the decoding. */
bytesleft = state.input.size - state.input.pos;
while (state.framesleft > 0 && bytesleft >= state.blockheadersize) {
state.block.data = state.input.data + state.input.pos;
state.block.size = bytesleft < state.blocksize ? bytesleft : state.blocksize;
state.block.pos = 0;
if (state.output.size - state.output.pos < (Uint64)state.framesleft * state.channels) {
/* Somehow didn't allocate enough space for the output. */
SDL_free(state.output.data);
SDL_free(cstate);
return SDL_SetError("Unexpected overflow in IMA ADPCM decoder");
}
/* Initialize decoder with the values from the block header. */
result = IMA_ADPCM_DecodeBlockHeader(&state);
if (result == 0) {
/* Decode the block data. It stores the samples directly in the output. */
result = IMA_ADPCM_DecodeBlockData(&state);
}
if (result == -1) {
/* Unexpected end. Stop decoding and return partial data if necessary. */
if (file->trunchint == TruncVeryStrict || file->trunchint == TruncVeryStrict) {
SDL_free(state.output.data);
SDL_free(cstate);
return SDL_SetError("Truncated data chunk");
} else if (file->trunchint != TruncDropFrame) {
state.output.pos -= state.output.pos % (state.samplesperblock * state.channels);
}
outputsize = state.output.pos * sizeof(Sint16); /* Can't overflow, is always smaller. */
break;
}
state.input.pos += state.block.size;
bytesleft = state.input.size - state.input.pos;
}
*audio_buf = (Uint8 *)state.output.data;
*audio_len = (Uint32)outputsize;
SDL_free(cstate);
return 0;
}

References WaveFormat::blockalign, WaveFormat::channels, WaveFile::chunk, WaveChunk::data, WaveFile::format, IMA_ADPCM_CalculateSampleFrames(), IMA_ADPCM_DecodeBlockData(), IMA_ADPCM_DecodeBlockHeader(), WaveChunk::length, NULL, SafeMult(), WaveFile::sampleframes, WaveFormat::samplesperblock, SDL_calloc, SDL_free, SDL_malloc, SDL_MAX_UINT32, SDL_OutOfMemory, SDL_SetError, SDL_zero, WaveChunk::size, SIZE_MAX, state, TruncDropFrame, WaveFile::trunchint, and TruncVeryStrict.

Referenced by WaveLoad().

## IMA_ADPCM_DecodeBlockData()

static int IMA_ADPCM_DecodeBlockData | ( | ADPCM_DecoderState * | state | ) |

static

Definition at line 967 of file SDL_wave.c.

{
size_t i;
int retval = 0;
const Uint32 channels = state->channels;
const size_t subblockframesize = channels * 4;
Uint64 bytesrequired;
Uint32 c;
size_t blockpos = state->block.pos;
size_t blocksize = state->block.size;
size_t blockleft = blocksize - blockpos;
size_t outpos = state->output.pos;
Sint64 blockframesleft = state->samplesperblock - 1;
if (blockframesleft > state->framesleft) {
blockframesleft = state->framesleft;
}
bytesrequired = (blockframesleft + 7) / 8 * subblockframesize;
if (blockleft < bytesrequired) {
/* Data truncated. Calculate how many samples we can get out if it. */
const size_t guaranteedframes = blockleft / subblockframesize;
const size_t remainingbytes = blockleft % subblockframesize;
blockframesleft = guaranteedframes;
if (remainingbytes > subblockframesize - 4) {
blockframesleft += (remainingbytes % 4) * 2;
}
/* Signal the truncation. */
retval = -1;
}
/* Each channel has their nibbles packed into 32-bit blocks. These blocks
* are interleaved and make up the data part of the ADPCM block. This loop
* decodes the samples as they come from the input data and puts them at
* the appropriate places in the output data.
*/
while (blockframesleft > 0) {
const size_t subblocksamples = blockframesleft < 8 ? (size_t)blockframesleft : 8;
for (c = 0; c < channels; c++) {
Uint8 nybble = 0;
/* Load previous sample which may come from the block header. */
Sint16 sample = state->output.data[outpos + c - channels];
for (i = 0; i < subblocksamples; i++) {
if (i & 1) {
nybble >>= 4;
} else {
nybble = state->block.data[blockpos++];
}
sample = IMA_ADPCM_ProcessNibble((Sint8 *)state->cstate + c, sample, nybble & 0x0f);
state->output.data[outpos + c + i * channels] = sample;
}
}
outpos += channels * subblocksamples;
state->framesleft -= subblocksamples;
blockframesleft -= subblocksamples;
}
state->block.pos = blockpos;
state->output.pos = outpos;
return retval;
}

References i, IMA_ADPCM_ProcessNibble(), retval, and state.

Referenced by IMA_ADPCM_Decode().

## IMA_ADPCM_DecodeBlockHeader()

static int IMA_ADPCM_DecodeBlockHeader | ( | ADPCM_DecoderState * | state | ) |

static

Definition at line 927 of file SDL_wave.c.

{
Sint16 step;
Uint32 c;
Uint8 *cstate = state->cstate;
for (c = 0; c < state->channels; c++) {
size_t o = state->block.pos + c * 4;
/* Extract the sample from the header. */
Sint32 sample = state->block.data[o] | ((Sint32)state->block.data[o + 1] << 8);
if (sample >= 0x8000) {
sample -= 0x10000;
}
state->output.data[state->output.pos++] = (Sint16)sample;
/* Channel step index. */
step = (Sint16)state->block.data[o + 2];
cstate[c] = (Sint8)(step > 0x80 ? step - 0x100 : step);
/* Reserved byte in block header, should be 0. */
if (state->block.data[o + 3] != 0) {
/* Uh oh, corrupt data? Buggy code? */ ;
}
}
state->block.pos += state->blockheadersize;
/* Header provided one sample frame. */
state->framesleft--;
return 0;
}

References state.

Referenced by IMA_ADPCM_Decode().

## IMA_ADPCM_Init()

static int IMA_ADPCM_Init | ( | WaveFile * | file,
|  | size_t | datalength
| ) |  |

static

Definition at line 795 of file SDL_wave.c.

{
WaveFormat *format = &file->format;
WaveChunk *chunk = &file->chunk;
const size_t blockheadersize = (size_t)format->channels * 4;
const size_t blockdatasize = (size_t)format->blockalign - blockheadersize;
const size_t blockframebitsize = (size_t)format->bitspersample * format->channels;
const size_t blockdatasamples = (blockdatasize * 8) / blockframebitsize;
/* Sanity checks. */
/* IMA ADPCM can also have 3-bit samples, but it's not supported by SDL at this time. */
if (format->bitspersample == 3) {
return SDL_SetError("3-bit IMA ADPCM currently not supported");
} else if (format->bitspersample != 4) {
return SDL_SetError("Invalid IMA ADPCM bits per sample of %u", (unsigned int)format->bitspersample);
}
/* The block size is required to be a multiple of 4 and it must be able to
* hold a block header.
*/
if (format->blockalign < blockheadersize || format->blockalign % 4) {
return SDL_SetError("Invalid IMA ADPCM block size (nBlockAlign)");
}
if (format->formattag == EXTENSIBLE_CODE) {
/* There's no specification for this, but it's basically the same
* format because the extensible header has wSampePerBlocks too.
*/
} else {
/* The Standards Update says there 'should' be 2 bytes for wSamplesPerBlock. */
if (chunk->size >= 20 && format->extsize >= 2) {
format->samplesperblock = chunk->data[18] | ((Uint16)chunk->data[19] << 8);
}
}
if (format->samplesperblock == 0) {
/* Field zero? No problem. We just assume the encoder packed the block.
* The specification calculates it this way:
*
* x = Block size (in bits) minus header size (in bits)
* y = Bit depth multiplied by channel count
* z = Number of samples per channel in header
* wSamplesPerBlock = x / y + z
*/
format->samplesperblock = (Uint32)blockdatasamples + 1;
}
/* nBlockAlign can be in conflict with wSamplesPerBlock. For example, if
* the number of samples doesn't fit into the block. The Standards Update
* also describes wSamplesPerBlock with a formula that makes it necessary
* to always fill the block with the maximum amount of samples, but this is
* not enforced here as there are no compatibility issues.
*/
if (blockdatasamples < format->samplesperblock - 1) {
return SDL_SetError("Invalid number of samples per IMA ADPCM block (wSamplesPerBlock)");
}
if (IMA_ADPCM_CalculateSampleFrames(file, datalength) < 0) {
return -1;
}
return 0;
}

References WaveFile::chunk, WaveChunk::data, EXTENSIBLE_CODE, WaveFile::format, IMA_ADPCM_CalculateSampleFrames(), SDL_SetError, and WaveChunk::size.

Referenced by WaveCheckFormat().

## IMA_ADPCM_ProcessNibble()

static Sint16 IMA_ADPCM_ProcessNibble | ( | Sint8 * | cindex,
|  | Sint16 | lastsample,
|  | Uint8 | nybble
| ) |  |

static

Definition at line 861 of file SDL_wave.c.

{
const Sint32 max_audioval = 32767;
const Sint32 min_audioval = -32768;
const Sint8 index_table_4b[16] = {
-1, -1, -1, -1,
2, 4, 6, 8,
-1, -1, -1, -1,
2, 4, 6, 8
};
const Uint16 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
};
Uint32 step;
Sint32 sample, delta;
Sint8 index = *cindex;
/* Clamp index into valid range. */
if (index > 88) {
index = 88;
} else if (index < 0) {
index = 0;
}
/* explicit cast to avoid gcc warning about using 'char' as array index */
step = step_table[(size_t)index];
/* Update index value */
*cindex = index + index_table_4b[nybble];
/* This calculation uses shifts and additions because multiplications were
* much slower back then. Sadly, this can't just be replaced with an actual
* multiplication now as the old algorithm drops some bits. The closest
* approximation I could find is something like this:
* (nybble & 0x8 ? -1 : 1) * ((nybble & 0x7) * step / 4 + step / 8)
*/
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;
sample = lastsample + delta;
/* Clamp output sample */
if (sample > max_audioval) {
sample = max_audioval;
} else if (sample < min_audioval) {
sample = min_audioval;
}
return (Sint16)sample;
}

Referenced by IMA_ADPCM_DecodeBlockData().

## LAW_Decode()

static int LAW_Decode | ( | WaveFile * | file,
|  | Uint8 ** | audio_buf,
|  | Uint32 * | audio_len
| ) |  |

static

Definition at line 1170 of file SDL_wave.c.

{
#ifdef SDL_WAVE_LAW_LUT
const Sint16 alaw_lut[256] = {
-5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, -2752,
-2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, -22016,
-20992, -24064, -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, -11008,
-10496, -12032, -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, -344,
-328, -376, -360, -280, -264, -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88,
-72, -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, -184, -168, -1376,
-1312, -1504, -1440, -1120, -1056, -1248, -1184, -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688,
-656, -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, -784, -880, -848, 5504,
5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752,
2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016,
20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008,
10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344,
328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88,
72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376,
1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688,
656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848
};
const Sint16 mulaw_lut[256] = {
-32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, -15996,
-15484, -14972, -14460, -13948, -13436, -12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, -7932,
-7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900,
-3772, -3644, -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, -1884,
-1820, -1756, -1692, -1628, -1564, -1500, -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876,
-844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, -492, -460, -428, -396, -372,
-356, -340, -324, -308, -292, -276, -260, -244, -228, -212, -196, -180, -164, -148, -132, -120,
-112, -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, 32124,
31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 15996,
15484, 14972, 14460, 13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, 7932,
7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900,
3772, 3644, 3516, 3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, 1884,
1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, 876,
844, 812, 780, 748, 716, 684, 652, 620, 588, 556, 524, 492, 460, 428, 396, 372,
356, 340, 324, 308, 292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120,
112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0
};
#endif
WaveFormat *format = &file->format;
WaveChunk *chunk = &file->chunk;
size_t i, sample_count, expanded_len;
Uint8 *src;
Sint16 *dst;
if (chunk->length != chunk->size) {
file->sampleframes = WaveAdjustToFactValue(file, chunk->size / format->blockalign);
if (file->sampleframes < 0) {
return -1;
}
}
/* Nothing to decode, nothing to return. */
if (file->sampleframes == 0) {
*audio_buf = NULL;
*audio_len = 0;
return 0;
}
sample_count = (size_t)file->sampleframes;
if (SafeMult(&sample_count, format->channels)) {
return SDL_OutOfMemory();
}
expanded_len = sample_count;
if (SafeMult(&expanded_len, sizeof(Sint16))) {
return SDL_OutOfMemory();
} else if (expanded_len > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
return SDL_SetError("WAVE file too big");
}
/* 1 to avoid allocating zero bytes, to keep static analysis happy. */
src = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1);
if (src == NULL) {
return SDL_OutOfMemory();
}
chunk->data = NULL;
chunk->size = 0;
dst = (Sint16 *)src;
/* Work backwards, since we're expanding in-place. SDL_AudioSpec.format will
* inform the caller about the byte order.
*/
i = sample_count;
switch (file->format.encoding) {
#ifdef SDL_WAVE_LAW_LUT
case ALAW_CODE:
while (i--) {
dst[i] = alaw_lut[src[i]];
}
break;
case MULAW_CODE:
while (i--) {
dst[i] = mulaw_lut[src[i]];
}
break;
#else
case ALAW_CODE:
while (i--) {
Uint8 nibble = src[i];
Uint8 exponent = (nibble & 0x7f) ^ 0x55;
Sint16 mantissa = exponent & 0xf;
exponent >>= 4;
if (exponent > 0) {
mantissa |= 0x10;
}
mantissa = (mantissa << 4) | 0x8;
if (exponent > 1) {
mantissa <<= exponent - 1;
}
dst[i] = nibble & 0x80 ? mantissa : -mantissa;
}
break;
case MULAW_CODE:
while (i--) {
Uint8 nibble = ~src[i];
Sint16 mantissa = nibble & 0xf;
Uint8 exponent = (nibble >> 4) & 0x7;
Sint16 step = 4 << (exponent + 1);
mantissa = (0x80 << exponent) + step * mantissa + step / 2 - 132;
dst[i] = nibble & 0x80 ? -mantissa : mantissa;
}
break;
#endif
default:
SDL_free(src);
return SDL_SetError("Unknown companded encoding");
}
*audio_buf = src;
*audio_len = (Uint32)expanded_len;
return 0;
}

References ALAW_CODE, WaveFile::chunk, WaveChunk::data, WaveFormat::encoding, WaveFile::format, i, WaveChunk::length, MULAW_CODE, nibble(), NULL, SafeMult(), WaveFile::sampleframes, SDL_free, SDL_MAX_UINT32, SDL_OutOfMemory, SDL_realloc, SDL_SetError, WaveChunk::size, SIZE_MAX, and WaveAdjustToFactValue().

Referenced by WaveLoad().

## LAW_Init()

static int LAW_Init | ( | WaveFile * | file,
|  | size_t | datalength
| ) |  |

static

Definition at line 1141 of file SDL_wave.c.

{
WaveFormat *format = &file->format;
/* Standards Update requires this to be 8. */
if (format->bitspersample != 8) {
return SDL_SetError("Invalid companded bits per sample of %u", (unsigned int)format->bitspersample);
}
/* Not going to bother with weird padding. */
if (format->blockalign != format->channels) {
return SDL_SetError("Unsupported block alignment");
}
if ((file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict)) {
if (format->blockalign > 1 && datalength % format->blockalign) {
return SDL_SetError("Truncated data chunk in WAVE file");
}
}
file->sampleframes = WaveAdjustToFactValue(file, datalength / format->blockalign);
if (file->sampleframes < 0) {
return -1;
}
return 0;
}

References WaveFile::format, WaveFile::sampleframes, SDL_SetError, WaveFile::trunchint, TruncStrict, TruncVeryStrict, and WaveAdjustToFactValue().

Referenced by WaveCheckFormat().

## MS_ADPCM_CalculateSampleFrames()

static int MS_ADPCM_CalculateSampleFrames | ( | WaveFile * | file,
|  | size_t | datalength
| ) |  |

static

Definition at line 336 of file SDL_wave.c.

{
WaveFormat *format = &file->format;
const size_t blockheadersize = (size_t)file->format.channels * 7;
const size_t availableblocks = datalength / file->format.blockalign;
const size_t blockframebitsize = (size_t)file->format.bitspersample * file->format.channels;
const size_t trailingdata = datalength % file->format.blockalign;
if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
/* The size of the data chunk must be a multiple of the block size. */
if (datalength < blockheadersize || trailingdata > 0) {
return SDL_SetError("Truncated MS ADPCM block");
}
}
/* Calculate number of sample frames that will be decoded. */
file->sampleframes = (Sint64)availableblocks * format->samplesperblock;
if (trailingdata > 0) {
/* The last block is truncated. Check if we can get any samples out of it. */
if (file->trunchint == TruncDropFrame) {
/* Drop incomplete sample frame. */
if (trailingdata >= blockheadersize) {
size_t trailingsamples = 2 + (trailingdata - blockheadersize) * 8 / blockframebitsize;
if (trailingsamples > format->samplesperblock) {
trailingsamples = format->samplesperblock;
}
file->sampleframes += trailingsamples;
}
}
}
file->sampleframes = WaveAdjustToFactValue(file, file->sampleframes);
if (file->sampleframes < 0) {
return -1;
}
return 0;
}

References WaveFormat::bitspersample, WaveFormat::blockalign, WaveFormat::channels, WaveFile::format, WaveFile::sampleframes, SDL_SetError, TruncDropFrame, WaveFile::trunchint, TruncStrict, TruncVeryStrict, and WaveAdjustToFactValue().

Referenced by MS_ADPCM_Decode(), and MS_ADPCM_Init().

## MS_ADPCM_Decode()

static int MS_ADPCM_Decode | ( | WaveFile * | file,
|  | Uint8 ** | audio_buf,
|  | Uint32 * | audio_len
| ) |  |

static

Definition at line 641 of file SDL_wave.c.

{
int result;
size_t bytesleft, outputsize;
WaveChunk *chunk = &file->chunk;
ADPCM_DecoderState state;
MS_ADPCM_ChannelState cstate[2];
SDL_zero(state);
SDL_zero(cstate);
if (chunk->size != chunk->length) {
/* Could not read everything. Recalculate number of sample frames. */
if (MS_ADPCM_CalculateSampleFrames(file, chunk->size) < 0) {
return -1;
}
}
/* Nothing to decode, nothing to return. */
if (file->sampleframes == 0) {
*audio_buf = NULL;
*audio_len = 0;
return 0;
}
state.blocksize = file->format.blockalign;
state.channels = file->format.channels;
state.blockheadersize = (size_t)state.channels * 7;
state.samplesperblock = file->format.samplesperblock;
state.framesize = state.channels * sizeof(Sint16);
state.ddata = file->decoderdata;
state.framestotal = file->sampleframes;
state.framesleft = state.framestotal;
state.input.data = chunk->data;
state.input.size = chunk->size;
state.input.pos = 0;
/* The output size in bytes. May get modified if data is truncated. */
outputsize = (size_t)state.framestotal;
if (SafeMult(&outputsize, state.framesize)) {
return SDL_OutOfMemory();
} else if (outputsize > SDL_MAX_UINT32 || state.framestotal > SIZE_MAX) {
return SDL_SetError("WAVE file too big");
}
state.output.pos = 0;
state.output.size = outputsize / sizeof(Sint16);
state.output.data = (Sint16 *)SDL_malloc(outputsize);
if (state.output.data == NULL) {
return SDL_OutOfMemory();
}
state.cstate = &cstate;
/* Decode block by block. A truncated block will stop the decoding. */
bytesleft = state.input.size - state.input.pos;
while (state.framesleft > 0 && bytesleft >= state.blockheadersize) {
state.block.data = state.input.data + state.input.pos;
state.block.size = bytesleft < state.blocksize ? bytesleft : state.blocksize;
state.block.pos = 0;
if (state.output.size - state.output.pos < (Uint64)state.framesleft * state.channels) {
/* Somehow didn't allocate enough space for the output. */
SDL_free(state.output.data);
return SDL_SetError("Unexpected overflow in MS ADPCM decoder");
}
/* Initialize decoder with the values from the block header. */
result = MS_ADPCM_DecodeBlockHeader(&state);
if (result == -1) {
SDL_free(state.output.data);
return -1;
}
/* Decode the block data. It stores the samples directly in the output. */
result = MS_ADPCM_DecodeBlockData(&state);
if (result == -1) {
/* Unexpected end. Stop decoding and return partial data if necessary. */
if (file->trunchint == TruncVeryStrict || file->trunchint == TruncVeryStrict) {
SDL_free(state.output.data);
return SDL_SetError("Truncated data chunk");
} else if (file->trunchint != TruncDropFrame) {
state.output.pos -= state.output.pos % (state.samplesperblock * state.channels);
}
outputsize = state.output.pos * sizeof(Sint16); /* Can't overflow, is always smaller. */
break;
}
state.input.pos += state.block.size;
bytesleft = state.input.size - state.input.pos;
}
*audio_buf = (Uint8 *)state.output.data;
*audio_len = (Uint32)outputsize;
return 0;
}

References WaveFormat::blockalign, WaveFormat::channels, WaveFile::chunk, WaveChunk::data, WaveFile::decoderdata, WaveFile::format, WaveChunk::length, MS_ADPCM_CalculateSampleFrames(), MS_ADPCM_DecodeBlockData(), MS_ADPCM_DecodeBlockHeader(), NULL, SafeMult(), WaveFile::sampleframes, WaveFormat::samplesperblock, SDL_free, SDL_malloc, SDL_MAX_UINT32, SDL_OutOfMemory, SDL_SetError, SDL_zero, WaveChunk::size, SIZE_MAX, state, TruncDropFrame, WaveFile::trunchint, and TruncVeryStrict.

Referenced by WaveLoad().

## MS_ADPCM_DecodeBlockData()

static int MS_ADPCM_DecodeBlockData | ( | ADPCM_DecoderState * | state | ) |

static

Definition at line 593 of file SDL_wave.c.

{
Uint16 nybble = 0;
Sint16 sample1, sample2;
const Uint32 channels = state->channels;
Uint32 c;
MS_ADPCM_ChannelState *cstate = (MS_ADPCM_ChannelState *)state->cstate;
size_t blockpos = state->block.pos;
size_t blocksize = state->block.size;
size_t outpos = state->output.pos;
Sint64 blockframesleft = state->samplesperblock - 2;
if (blockframesleft > state->framesleft) {
blockframesleft = state->framesleft;
}
while (blockframesleft > 0) {
for (c = 0; c < channels; c++) {
if (nybble & 0x4000) {
nybble <<= 4;
} else if (blockpos < blocksize) {
nybble = state->block.data[blockpos++] | 0x4000;
} else {
/* Out of input data. Drop the incomplete frame and return. */
state->output.pos = outpos - c;
return -1;
}
/* Load previous samples which may come from the block header. */
sample1 = state->output.data[outpos - channels];
sample2 = state->output.data[outpos - channels * 2];
sample1 = MS_ADPCM_ProcessNibble(cstate + c, sample1, sample2, (nybble >> 4) & 0x0f);
state->output.data[outpos++] = sample1;
}
state->framesleft--;
blockframesleft--;
}
state->output.pos = outpos;
return 0;
}

References MS_ADPCM_ProcessNibble(), and state.

Referenced by MS_ADPCM_Decode().

## MS_ADPCM_DecodeBlockHeader()

static int MS_ADPCM_DecodeBlockHeader | ( | ADPCM_DecoderState * | state | ) |

static

Definition at line 532 of file SDL_wave.c.

{
Uint8 coeffindex;
const Uint32 channels = state->channels;
Sint32 sample;
Uint32 c;
MS_ADPCM_ChannelState *cstate = (MS_ADPCM_ChannelState *)state->cstate;
MS_ADPCM_CoeffData *ddata = (MS_ADPCM_CoeffData *)state->ddata;
for (c = 0; c < channels; c++) {
size_t o = c;
/* Load the coefficient pair into the channel state. */
coeffindex = state->block.data[o];
if (coeffindex > ddata->coeffcount) {
return SDL_SetError("Invalid MS ADPCM coefficient index in block header");
}
cstate[c].coeff1 = ddata->coeff[coeffindex * 2];
cstate[c].coeff2 = ddata->coeff[coeffindex * 2 + 1];
/* Initial delta value. */
o = channels + c * 2;
cstate[c].delta = state->block.data[o] | ((Uint16)state->block.data[o + 1] << 8);
/* Load the samples from the header. Interestingly, the sample later in
* the output stream comes first.
*/
o = channels * 3 + c * 2;
sample = state->block.data[o] | ((Sint32)state->block.data[o + 1] << 8);
if (sample >= 0x8000) {
sample -= 0x10000;
}
state->output.data[state->output.pos + channels] = (Sint16)sample;
o = channels * 5 + c * 2;
sample = state->block.data[o] | ((Sint32)state->block.data[o + 1] << 8);
if (sample >= 0x8000) {
sample -= 0x10000;
}
state->output.data[state->output.pos] = (Sint16)sample;
state->output.pos++;
}
state->block.pos += state->blockheadersize;
/* Skip second sample frame that came from the header. */
state->output.pos += state->channels;
/* Header provided two sample frames. */
state->framesleft -= 2;
return 0;
}

References MS_ADPCM_ChannelState::coeff1, MS_ADPCM_ChannelState::coeff2, MS_ADPCM_ChannelState::delta, SDL_SetError, and state.

Referenced by MS_ADPCM_Decode().

## MS_ADPCM_Init()

static int MS_ADPCM_Init | ( | WaveFile * | file,
|  | size_t | datalength
| ) |  |

static

Definition at line 376 of file SDL_wave.c.

{
WaveFormat *format = &file->format;
WaveChunk *chunk = &file->chunk;
const size_t blockheadersize = (size_t)format->channels * 7;
const size_t blockdatasize = (size_t)format->blockalign - blockheadersize;
const size_t blockframebitsize = (size_t)format->bitspersample * format->channels;
const size_t blockdatasamples = (blockdatasize * 8) / blockframebitsize;
const Sint16 presetcoeffs[14] = {256, 0, 512, -256, 0, 0, 192, 64, 240, 0, 460, -208, 392, -232};
size_t i, coeffcount;
MS_ADPCM_CoeffData *coeffdata;
/* Sanity checks. */
/* While it's clear how IMA ADPCM handles more than two channels, the nibble
* order of MS ADPCM makes it awkward. The Standards Update does not talk
* about supporting more than stereo anyway.
*/
if (format->channels > 2) {
return SDL_SetError("Invalid number of channels");
}
if (format->bitspersample != 4) {
return SDL_SetError("Invalid MS ADPCM bits per sample of %u", (unsigned int)format->bitspersample);
}
/* The block size must be big enough to contain the block header. */
if (format->blockalign < blockheadersize) {
return SDL_SetError("Invalid MS ADPCM block size (nBlockAlign)");
}
if (format->formattag == EXTENSIBLE_CODE) {
/* Does have a GUID (like all format tags), but there's no specification
* for how the data is packed into the extensible header. Making
* assumptions here could lead to new formats nobody wants to support.
*/
return SDL_SetError("MS ADPCM with the extensible header is not supported");
}
/* There are wSamplesPerBlock, wNumCoef, and at least 7 coefficient pairs in
* the extended part of the header.
*/
if (chunk->size < 22) {
return SDL_SetError("Could not read MS ADPCM format header");
}
format->samplesperblock = chunk->data[18] | ((Uint16)chunk->data[19] << 8);
/* Number of coefficient pairs. A pair has two 16-bit integers. */
coeffcount = chunk->data[20] | ((size_t)chunk->data[21] << 8);
/* bPredictor, the integer offset into the coefficients array, is only
* 8 bits. It can only address the first 256 coefficients. Let's limit
* the count number here.
*/
if (coeffcount > 256) {
coeffcount = 256;
}
if (chunk->size < 22 + coeffcount * 4) {
return SDL_SetError("Could not read custom coefficients in MS ADPCM format header");
} else if (format->extsize < 4 + coeffcount * 4) {
return SDL_SetError("Invalid MS ADPCM format header (too small)");
} else if (coeffcount < 7) {
return SDL_SetError("Missing required coefficients in MS ADPCM format header");
}
coeffdata = (MS_ADPCM_CoeffData *)SDL_malloc(sizeof(MS_ADPCM_CoeffData) + coeffcount * 4);
file->decoderdata = coeffdata; /* Freed in cleanup. */
if (coeffdata == NULL) {
return SDL_OutOfMemory();
}
coeffdata->coeff = &coeffdata->aligndummy;
coeffdata->coeffcount = (Uint16)coeffcount;
/* Copy the 16-bit pairs. */
for (i = 0; i < coeffcount * 2; i++) {
Sint32 c = chunk->data[22 + i * 2] | ((Sint32)chunk->data[23 + i * 2] << 8);
if (c >= 0x8000) {
c -= 0x10000;
}
if (i < 14 && c != presetcoeffs[i]) {
return SDL_SetError("Wrong preset coefficients in MS ADPCM format header");
}
coeffdata->coeff[i] = (Sint16)c;
}
/* Technically, wSamplesPerBlock is required, but we have all the
* information in the other fields to calculate it, if it's zero.
*/
if (format->samplesperblock == 0) {
/* Let's be nice to the encoders that didn't know how to fill this.
* The Standards Update calculates it this way:
*
* x = Block size (in bits) minus header size (in bits)
* y = Bit depth multiplied by channel count
* z = Number of samples per channel in block header
* wSamplesPerBlock = x / y + z
*/
format->samplesperblock = (Uint32)blockdatasamples + 2;
}
/* nBlockAlign can be in conflict with wSamplesPerBlock. For example, if
* the number of samples doesn't fit into the block. The Standards Update
* also describes wSamplesPerBlock with a formula that makes it necessary to
* always fill the block with the maximum amount of samples, but this is not
* enforced here as there are no compatibility issues.
* A truncated block header with just one sample is not supported.
*/
if (format->samplesperblock == 1 || blockdatasamples < format->samplesperblock - 2) {
return SDL_SetError("Invalid number of samples per MS ADPCM block (wSamplesPerBlock)");
}
if (MS_ADPCM_CalculateSampleFrames(file, datalength) < 0) {
return -1;
}
return 0;
}

References MS_ADPCM_CoeffData::aligndummy, WaveFile::chunk, MS_ADPCM_CoeffData::coeff, MS_ADPCM_CoeffData::coeffcount, WaveChunk::data, WaveFile::decoderdata, EXTENSIBLE_CODE, WaveFile::format, i, MS_ADPCM_CalculateSampleFrames(), NULL, SDL_malloc, SDL_OutOfMemory, SDL_SetError, and WaveChunk::size.

Referenced by WaveCheckFormat().

## MS_ADPCM_ProcessNibble()

static Sint16 MS_ADPCM_ProcessNibble | ( | MS_ADPCM_ChannelState * | cstate,
|  | Sint32 | sample1,
|  | Sint32 | sample2,
|  | Uint8 | nybble
| ) |  |

static

Definition at line 495 of file SDL_wave.c.

{
const Sint32 max_audioval = 32767;
const Sint32 min_audioval = -32768;
const Uint16 max_deltaval = 65535;
const Uint16 adaptive[] = {
230, 230, 230, 230, 307, 409, 512, 614,
768, 614, 512, 409, 307, 230, 230, 230
};
Sint32 new_sample;
Sint32 errordelta;
Uint32 delta = cstate->delta;
new_sample = (sample1 * cstate->coeff1 + sample2 * cstate->coeff2) / 256;
/* The nibble is a signed 4-bit error delta. */
errordelta = (Sint32)nybble - (nybble >= 0x08 ? 0x10 : 0);
new_sample += (Sint32)delta * errordelta;
if (new_sample < min_audioval) {
new_sample = min_audioval;
} else if (new_sample > max_audioval) {
new_sample = max_audioval;
}
delta = (delta * adaptive[nybble]) / 256;
if (delta < 16) {
delta = 16;
} else if (delta > max_deltaval) {
/* This issue is not described in the Standards Update and therefore
* undefined. It seems sensible to prevent overflows with a limit.
*/
delta = max_deltaval;
}
cstate->delta = (Uint16)delta;
return (Sint16)new_sample;
}

References MS_ADPCM_ChannelState::coeff1, MS_ADPCM_ChannelState::coeff2, and MS_ADPCM_ChannelState::delta.

Referenced by MS_ADPCM_DecodeBlockData().

## PCM_ConvertSint24ToSint32()

static int PCM_ConvertSint24ToSint32 | ( | WaveFile * | file,
|  | Uint8 ** | audio_buf,
|  | Uint32 * | audio_len
| ) |  |

static

Definition at line 1356 of file SDL_wave.c.

{
WaveFormat *format = &file->format;
WaveChunk *chunk = &file->chunk;
size_t i, expanded_len, sample_count;
Uint8 *ptr;
sample_count = (size_t)file->sampleframes;
if (SafeMult(&sample_count, format->channels)) {
return SDL_OutOfMemory();
}
expanded_len = sample_count;
if (SafeMult(&expanded_len, sizeof(Sint32))) {
return SDL_OutOfMemory();
} else if (expanded_len > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
return SDL_SetError("WAVE file too big");
}
/* 1 to avoid allocating zero bytes, to keep static analysis happy. */
ptr = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1);
if (ptr == NULL) {
return SDL_OutOfMemory();
}
/* This pointer is now invalid. */
chunk->data = NULL;
chunk->size = 0;
*audio_buf = ptr;
*audio_len = (Uint32)expanded_len;
/* work from end to start, since we're expanding in-place. */
for (i = sample_count; i > 0; i--) {
const size_t o = i - 1;
uint8_t b[4];
b[0] = 0;
b[1] = ptr[o * 3];
b[2] = ptr[o * 3 + 1];
b[3] = ptr[o * 3 + 2];
ptr[o * 4 + 0] = b[0];
ptr[o * 4 + 1] = b[1];
ptr[o * 4 + 2] = b[2];
ptr[o * 4 + 3] = b[3];
}
return 0;
}

References WaveFile::chunk, WaveChunk::data, WaveFile::format, i, NULL, SafeMult(), WaveFile::sampleframes, SDL_MAX_UINT32, SDL_OutOfMemory, SDL_realloc, SDL_SetError, WaveChunk::size, and SIZE_MAX.

Referenced by PCM_Decode().

## PCM_Decode()

static int PCM_Decode | ( | WaveFile * | file,
|  | Uint8 ** | audio_buf,
|  | Uint32 * | audio_len
| ) |  |

static

Definition at line 1408 of file SDL_wave.c.

{
WaveFormat *format = &file->format;
WaveChunk *chunk = &file->chunk;
size_t outputsize;
if (chunk->length != chunk->size) {
file->sampleframes = WaveAdjustToFactValue(file, chunk->size / format->blockalign);
if (file->sampleframes < 0) {
return -1;
}
}
/* Nothing to decode, nothing to return. */
if (file->sampleframes == 0) {
*audio_buf = NULL;
*audio_len = 0;
return 0;
}
/* 24-bit samples get shifted to 32 bits. */
if (format->encoding == PCM_CODE && format->bitspersample == 24) {
return PCM_ConvertSint24ToSint32(file, audio_buf, audio_len);
}
outputsize = (size_t)file->sampleframes;
if (SafeMult(&outputsize, format->blockalign)) {
return SDL_OutOfMemory();
} else if (outputsize > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
return SDL_SetError("WAVE file too big");
}
*audio_buf = chunk->data;
*audio_len = (Uint32)outputsize;
/* This pointer is going to be returned to the caller. Prevent free in cleanup. */
chunk->data = NULL;
chunk->size = 0;
return 0;
}

References WaveFile::chunk, WaveChunk::data, WaveFile::format, WaveChunk::length, NULL, PCM_CODE, PCM_ConvertSint24ToSint32(), SafeMult(), WaveFile::sampleframes, SDL_MAX_UINT32, SDL_OutOfMemory, SDL_SetError, WaveChunk::size, SIZE_MAX, and WaveAdjustToFactValue().

Referenced by WaveLoad().

## PCM_Init()

static int PCM_Init | ( | WaveFile * | file,
|  | size_t | datalength
| ) |  |

static

Definition at line 1313 of file SDL_wave.c.

{
WaveFormat *format = &file->format;
if (format->encoding == PCM_CODE) {
switch (format->bitspersample) {
case 8:
case 16:
case 24:
case 32:
/* These are supported. */
break;
default:
return SDL_SetError("%u-bit PCM format not supported", (unsigned int)format->bitspersample);
}
} else if (format->encoding == IEEE_FLOAT_CODE) {
if (format->bitspersample != 32) {
return SDL_SetError("%u-bit IEEE floating-point format not supported", (unsigned int)format->bitspersample);
}
}
/* It wouldn't be that hard to support more exotic block sizes, but
* the most common formats should do for now.
*/
if (format->blockalign * 8 != format->channels * format->bitspersample) {
return SDL_SetError("Unsupported block alignment");
}
if ((file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict)) {
if (format->blockalign > 1 && datalength % format->blockalign) {
return SDL_SetError("Truncated data chunk in WAVE file");
}
}
file->sampleframes = WaveAdjustToFactValue(file, datalength / format->blockalign);
if (file->sampleframes < 0) {
return -1;
}
return 0;
}

References WaveFile::format, IEEE_FLOAT_CODE, PCM_CODE, WaveFile::sampleframes, SDL_SetError, WaveFile::trunchint, TruncStrict, TruncVeryStrict, and WaveAdjustToFactValue().

Referenced by WaveCheckFormat().

## SafeMult()

static int SafeMult | ( | size_t * | f1,
|  | size_t | f2
| ) |  |

static

Definition at line 48 of file SDL_wave.c.

{
if (*f1 > 0 && SIZE_MAX / *f1 <= f2) {
return -1;
}
*f1 *= f2;
return 0;
}

References SIZE_MAX.

Referenced by IMA_ADPCM_Decode(), LAW_Decode(), MS_ADPCM_Decode(), PCM_ConvertSint24ToSint32(), and PCM_Decode().

## SDL_FreeWAV()

void SDL_FreeWAV | ( | Uint8 * | audio_buf | ) |

This function frees data previously allocated with SDL_LoadWAV_RW()

Definition at line 2148 of file SDL_wave.c.

{
SDL_free(audio_buf);
}

References SDL_free.

## SDL_LoadWAV_RW()

SDL_AudioSpec* SDL_LoadWAV_RW | ( | SDL_RWops * | src,
|  | int | freesrc,
|  | SDL_AudioSpec * | spec,
|  | Uint8 ** | audio_buf,
|  | Uint32 * | audio_len
| ) |  |

Load the audio data of a WAVE file into memory.

Loading a WAVE file requires `src`, `spec`, `audio_buf` and `audio_len` to be valid pointers. The entire data portion of the file is then loaded into memory and decoded if necessary.

If `freesrc` is non-zero, the data source gets automatically closed and freed before the function returns.

Supported are RIFF WAVE files with the formats PCM (8, 16, 24, and 32 bits), IEEE Float (32 bits), Microsoft ADPCM and IMA ADPCM (4 bits), and A-law and µ-law (8 bits). Other formats are currently unsupported and cause an error.

If this function succeeds, the pointer returned by it is equal to `spec` and the pointer to the audio data allocated by the function is written to `audio_buf` and its length in bytes to `audio_len`. The SDL_AudioSpec members `freq`, `channels`, and `format` are set to the values of the audio data in the buffer. The `samples` member is set to a sane default and all others are set to zero.

It's necessary to use SDL_FreeWAV() to free the audio data returned in `audio_buf` when it is no longer used.

Because of the underspecification of the Waveform format, there are many problematic files in the wild that cause issues with strict decoders. To provide compatibility with these files, this decoder is lenient in regards to the truncation of the file, the fact chunk, and the size of the RIFF chunk. The hints SDL_HINT_WAVE_RIFF_CHUNK_SIZE, SDL_HINT_WAVE_TRUNCATION, and SDL_HINT_WAVE_FACT_CHUNK can be used to tune the behavior of the loading process.

Any file that is invalid (due to truncation, corruption, or wrong values in the headers), too big, or unsupported causes an error. Additionally, any critical I/O error from the data source will terminate the loading process with an error. The function returns NULL on error and in all cases (with the exception of `src` being NULL), an appropriate error message will be set.

It is required that the data source supports seeking.

Example:

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

Parameters

  src | The data source with the WAVE data
  freesrc | A integer value that makes the function close the data source if non-zero
  spec | A pointer filled with the audio format of the audio data
  audio_buf | A pointer filled with the audio data allocated by the function
  audio_len | A pointer filled with the length of the audio data buffer in bytes

Returns
  NULL on error, or non-NULL on success.

Definition at line 2095 of file SDL_wave.c.

{
int result;
WaveFile file;
SDL_zero(file);
/* Make sure we are passed a valid data source */
if (src == NULL) {
/* Error may come from RWops. */
return NULL;
} else if (spec == NULL) {
SDL_InvalidParamError("spec");
return NULL;
} else if (audio_buf == NULL) {
SDL_InvalidParamError("audio_buf");
return NULL;
} else if (audio_len == NULL) {
SDL_InvalidParamError("audio_len");
return NULL;
}
*audio_buf = NULL;
*audio_len = 0;
file.riffhint = WaveGetRiffSizeHint();
file.trunchint = WaveGetTruncationHint();
file.facthint = WaveGetFactChunkHint();
result = WaveLoad(src, &file, spec, audio_buf, audio_len);
if (result < 0) {
SDL_free(*audio_buf);
spec = NULL;
audio_buf = NULL;
audio_len = 0;
}
/* Cleanup */
if (freesrc) {
SDL_RWclose(src);
} else {
SDL_RWseek(src, file.chunk.position, RW_SEEK_SET);
}
WaveFreeChunkData(&file.chunk);
SDL_free(file.decoderdata);
return spec;
}

References WaveFile::chunk, WaveFile::decoderdata, WaveFile::facthint, NULL, WaveChunk::position, WaveFile::riffhint, RW_SEEK_SET, SDL_free, SDL_InvalidParamError, SDL_RWclose, SDL_RWseek, SDL_zero, spec, WaveFile::trunchint, WaveFreeChunkData(), WaveGetFactChunkHint(), WaveGetRiffSizeHint(), WaveGetTruncationHint(), and WaveLoad().

## WaveAdjustToFactValue()

static Sint64 WaveAdjustToFactValue | ( | WaveFile * | file,
|  | Sint64 | sampleframes
| ) |  |

static

Definition at line 322 of file SDL_wave.c.

{
if (file->fact.status == 2) {
if (file->facthint == FactStrict && sampleframes < file->fact.samplelength) {
return SDL_SetError("Invalid number of sample frames in WAVE fact chunk (too many)");
} else if (sampleframes > file->fact.samplelength) {
return file->fact.samplelength;
}
}
return sampleframes;
}

References WaveFile::fact, WaveFile::facthint, FactStrict, WaveFact::samplelength, SDL_SetError, and WaveFact::status.

Referenced by IMA_ADPCM_CalculateSampleFrames(), LAW_Decode(), LAW_Init(), MS_ADPCM_CalculateSampleFrames(), PCM_Decode(), and PCM_Init().

## WaveCheckFormat()

static int WaveCheckFormat | ( | WaveFile * | file,
|  | size_t | datalength
| ) |  |

static

Definition at line 1679 of file SDL_wave.c.

{
WaveFormat *format = &file->format;
/* Check for some obvious issues. */
if (format->channels == 0) {
return SDL_SetError("Invalid number of channels");
} else if (format->channels > 255) {
/* Limit given by SDL_AudioSpec.channels. */
return SDL_SetError("Number of channels exceeds limit of 255");
}
if (format->frequency == 0) {
return SDL_SetError("Invalid sample rate");
} else if (format->frequency > INT_MAX) {
/* Limit given by SDL_AudioSpec.freq. */
return SDL_SetError("Sample rate exceeds limit of %d", INT_MAX);
}
/* Reject invalid fact chunks in strict mode. */
if (file->facthint == FactStrict && file->fact.status == -1) {
return SDL_SetError("Invalid fact chunk in WAVE file");
}
/* Check for issues common to all encodings. Some unsupported formats set
* the bits per sample to zero. These fall through to the 'unsupported
* format' error.
*/
switch (format->encoding) {
case IEEE_FLOAT_CODE:
case ALAW_CODE:
case MULAW_CODE:
case MS_ADPCM_CODE:
case IMA_ADPCM_CODE:
/* These formats require a fact chunk. */
if (file->facthint == FactStrict && file->fact.status <= 0) {
return SDL_SetError("Missing fact chunk in WAVE file");
}
/* fallthrough */
case PCM_CODE:
/* All supported formats require a non-zero bit depth. */
if (file->chunk.size < 16) {
return SDL_SetError("Missing wBitsPerSample field in WAVE fmt chunk");
} else if (format->bitspersample == 0) {
return SDL_SetError("Invalid bits per sample");
}
/* All supported formats must have a proper block size. */
if (format->blockalign == 0) {
return SDL_SetError("Invalid block alignment");
}
/* If the fact chunk is valid and the appropriate hint is set, the
* decoders will use the number of sample frames from the fact chunk.
*/
if (file->fact.status == 1) {
WaveFactChunkHint hint = file->facthint;
Uint32 samples = file->fact.samplelength;
if (hint == FactTruncate || hint == FactStrict || (hint == FactIgnoreZero && samples > 0)) {
file->fact.status = 2;
}
}
}
/* Check the format for encoding specific issues and initialize decoders. */
switch (format->encoding) {
case PCM_CODE:
case IEEE_FLOAT_CODE:
if (PCM_Init(file, datalength) < 0) {
return -1;
}
break;
case ALAW_CODE:
case MULAW_CODE:
if (LAW_Init(file, datalength) < 0) {
return -1;
}
break;
case MS_ADPCM_CODE:
if (MS_ADPCM_Init(file, datalength) < 0) {
return -1;
}
break;
case IMA_ADPCM_CODE:
if (IMA_ADPCM_Init(file, datalength) < 0) {
return -1;
}
break;
case MPEG_CODE:
case MPEGLAYER3_CODE:
return SDL_SetError("MPEG formats not supported");
default:
if (format->formattag == EXTENSIBLE_CODE) {
const char *errstr = "Unknown WAVE format GUID: %08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x";
const Uint8 *g = format->subformat;
const Uint32 g1 = g[0] | ((Uint32)g[1] << 8) | ((Uint32)g[2] << 16) | ((Uint32)g[3] << 24);
const Uint32 g2 = g[4] | ((Uint32)g[5] << 8);
const Uint32 g3 = g[6] | ((Uint32)g[7] << 8);
return SDL_SetError(errstr, g1, g2, g3, g[8], g[9], g[10], g[11], g[12], g[13], g[14], g[15]);
}
return SDL_SetError("Unknown WAVE format tag: 0x%04x", (unsigned int)format->encoding);
}
return 0;
}

References ALAW_CODE, WaveFile::chunk, EXTENSIBLE_CODE, WaveFile::fact, WaveFile::facthint, FactIgnoreZero, FactStrict, FactTruncate, WaveFile::format, IEEE_FLOAT_CODE, IMA_ADPCM_CODE, IMA_ADPCM_Init(), INT_MAX, LAW_Init(), MPEG_CODE, MPEGLAYER3_CODE, MS_ADPCM_CODE, MS_ADPCM_Init(), MULAW_CODE, PCM_CODE, PCM_Init(), WaveFact::samplelength, SDL_SetError, WaveChunk::size, and WaveFact::status.

Referenced by WaveLoad().

## WaveFreeChunkData()

static void WaveFreeChunkData | ( | WaveChunk * | chunk | ) |

static

Definition at line 1511 of file SDL_wave.c.

{
if (chunk->data != NULL) {
SDL_free(chunk->data);
chunk->data = NULL;
}
chunk->size = 0;
}

References WaveChunk::data, NULL, SDL_free, and WaveChunk::size.

Referenced by SDL_LoadWAV_RW(), WaveLoad(), WaveNextChunk(), and WaveReadPartialChunkData().

## WaveGetFactChunkHint()

static WaveFactChunkHint WaveGetFactChunkHint | ( |  | ) |

static

Definition at line 1491 of file SDL_wave.c.

{
const char *hint = SDL_GetHint(SDL_HINT_WAVE_FACT_CHUNK);
if (hint != NULL) {
if (SDL_strcmp(hint, "truncate") == 0) {
return FactTruncate;
} else if (SDL_strcmp(hint, "strict") == 0) {
return FactStrict;
} else if (SDL_strcmp(hint, "ignorezero") == 0) {
return FactIgnoreZero;
} else if (SDL_strcmp(hint, "ignore") == 0) {
return FactIgnore;
}
}
return FactNoHint;
}

References FactIgnore, FactIgnoreZero, FactNoHint, FactStrict, FactTruncate, NULL, SDL_GetHint, SDL_HINT_WAVE_FACT_CHUNK, and SDL_strcmp.

Referenced by SDL_LoadWAV_RW().

## WaveGetFormatGUIDEncoding()

static Uint16 WaveGetFormatGUIDEncoding | ( | WaveFormat * | format | ) |

static

Definition at line 1605 of file SDL_wave.c.

{
size_t i;
for (i = 0; i < SDL_arraysize(extensible_guids); i++) {
if (SDL_memcmp(format->subformat, extensible_guids[i].guid, 16) == 0) {
return extensible_guids[i].encoding;
}
}
return UNKNOWN_CODE;
}

References WaveExtensibleGUID::encoding, extensible_guids, WaveExtensibleGUID::guid, i, SDL_arraysize, SDL_memcmp, and UNKNOWN_CODE.

Referenced by WaveReadFormat().

## WaveGetRiffSizeHint()

static WaveRiffSizeHint WaveGetRiffSizeHint | ( |  | ) |

static

Definition at line 1451 of file SDL_wave.c.

{
const char *hint = SDL_GetHint(SDL_HINT_WAVE_RIFF_CHUNK_SIZE);
if (hint != NULL) {
if (SDL_strcmp(hint, "force") == 0) {
return RiffSizeForce;
} else if (SDL_strcmp(hint, "ignore") == 0) {
return RiffSizeIgnore;
} else if (SDL_strcmp(hint, "ignorezero") == 0) {
return RiffSizeIgnoreZero;
} else if (SDL_strcmp(hint, "maximum") == 0) {
return RiffSizeMaximum;
}
}
return RiffSizeNoHint;
}

References NULL, RiffSizeForce, RiffSizeIgnore, RiffSizeIgnoreZero, RiffSizeMaximum, RiffSizeNoHint, SDL_GetHint, SDL_HINT_WAVE_RIFF_CHUNK_SIZE, and SDL_strcmp.

Referenced by SDL_LoadWAV_RW().

## WaveGetTruncationHint()

static WaveTruncationHint WaveGetTruncationHint | ( |  | ) |

static

Definition at line 1471 of file SDL_wave.c.

{
const char *hint = SDL_GetHint(SDL_HINT_WAVE_TRUNCATION);
if (hint != NULL) {
if (SDL_strcmp(hint, "verystrict") == 0) {
return TruncVeryStrict;
} else if (SDL_strcmp(hint, "strict") == 0) {
return TruncStrict;
} else if (SDL_strcmp(hint, "dropframe") == 0) {
return TruncDropFrame;
} else if (SDL_strcmp(hint, "dropblock") == 0) {
return TruncDropBlock;
}
}
return TruncNoHint;
}

References NULL, SDL_GetHint, SDL_HINT_WAVE_TRUNCATION, SDL_strcmp, TruncDropBlock, TruncDropFrame, TruncNoHint, TruncStrict, and TruncVeryStrict.

Referenced by SDL_LoadWAV_RW().

## WaveLoad()

static int WaveLoad | ( | SDL_RWops * | src,
|  | WaveFile * | file,
|  | SDL_AudioSpec * | spec,
|  | Uint8 ** | audio_buf,
|  | Uint32 * | audio_len
| ) |  |

static

Definition at line 1787 of file SDL_wave.c.

{
int result;
Uint32 chunkcount = 0;
Uint32 chunkcountlimit = 10000;
char *envchunkcountlimit;
Sint64 RIFFstart, RIFFend, lastchunkpos;
SDL_bool RIFFlengthknown = SDL_FALSE;
WaveFormat *format = &file->format;
WaveChunk *chunk = &file->chunk;
WaveChunk RIFFchunk;
WaveChunk fmtchunk;
WaveChunk datachunk;
SDL_zero(RIFFchunk);
SDL_zero(fmtchunk);
SDL_zero(datachunk);
envchunkcountlimit = SDL_getenv("SDL_WAVE_CHUNK_LIMIT");
if (envchunkcountlimit != NULL) {
unsigned int count;
if (SDL_sscanf(envchunkcountlimit, "%u", &count) == 1) {
chunkcountlimit = count <= SDL_MAX_UINT32 ? count : SDL_MAX_UINT32;
}
}
RIFFstart = SDL_RWtell(src);
if (RIFFstart < 0) {
return SDL_SetError("Could not seek in file");
}
RIFFchunk.position = RIFFstart;
if (WaveNextChunk(src, &RIFFchunk) < 0) {
return SDL_SetError("Could not read RIFF header");
}
/* Check main WAVE file identifiers. */
if (RIFFchunk.fourcc == RIFF) {
Uint32 formtype;
/* Read the form type. "WAVE" expected. */
if (SDL_RWread(src, &formtype, sizeof(Uint32), 1) != 1) {
return SDL_SetError("Could not read RIFF form type");
} else if (SDL_SwapLE32(formtype) != WAVE) {
return SDL_SetError("RIFF form type is not WAVE (not a Waveform file)");
}
} else if (RIFFchunk.fourcc == WAVE) {
/* RIFF chunk missing or skipped. Length unknown. */
RIFFchunk.position = 0;
RIFFchunk.length = 0;
} else {
return SDL_SetError("Could not find RIFF or WAVE identifiers (not a Waveform file)");
}
/* The 4-byte form type is immediately followed by the first chunk.*/
chunk->position = RIFFchunk.position + 4;
/* Use the RIFF chunk size to limit the search for the chunks. This is not
* always reliable and the hint can be used to tune the behavior. By
* default, it will never search past 4 GiB.
*/
switch (file->riffhint) {
case RiffSizeIgnore:
RIFFend = RIFFchunk.position + SDL_MAX_UINT32;
break;
default:
case RiffSizeIgnoreZero:
if (RIFFchunk.length == 0) {
RIFFend = RIFFchunk.position + SDL_MAX_UINT32;
break;
}
/* fallthrough */
case RiffSizeForce:
RIFFend = RIFFchunk.position + RIFFchunk.length;
RIFFlengthknown = SDL_TRUE;
break;
case RiffSizeMaximum:
RIFFend = SDL_MAX_SINT64;
break;
}
/* Step through all chunks and save information on the fmt, data, and fact
* chunks. Ignore the chunks we don't know as per specification. This
* currently also ignores cue, list, and slnt chunks.
*/
while ((Uint64)RIFFend > (Uint64)chunk->position + chunk->length + (chunk->length & 1)) {
/* Abort after too many chunks or else corrupt files may waste time. */
if (chunkcount++ >= chunkcountlimit) {
return SDL_SetError("Chunk count in WAVE file exceeds limit of %u", chunkcountlimit);
}
result = WaveNextChunk(src, chunk);
if (result == -1) {
/* Unexpected EOF. Corrupt file or I/O issues. */
if (file->trunchint == TruncVeryStrict) {
return SDL_SetError("Unexpected end of WAVE file");
}
/* Let the checks after this loop sort this issue out. */
break;
} else if (result == -2) {
return SDL_SetError("Could not seek to WAVE chunk header");
}
if (chunk->fourcc == FMT) {
if (fmtchunk.fourcc == FMT) {
/* Multiple fmt chunks. Ignore or error? */
} else {
/* The fmt chunk must occur before the data chunk. */
if (datachunk.fourcc == DATA) {
return SDL_SetError("fmt chunk after data chunk in WAVE file");
}
fmtchunk = *chunk;
}
} else if (chunk->fourcc == DATA) {
/* Only use the first data chunk. Handling the wavl list madness
* may require a different approach.
*/
if (datachunk.fourcc != DATA) {
datachunk = *chunk;
}
} else if (chunk->fourcc == FACT) {
/* The fact chunk data must be at least 4 bytes for the
* dwSampleLength field. Ignore all fact chunks after the first one.
*/
if (file->fact.status == 0) {
if (chunk->length < 4) {
file->fact.status = -1;
} else {
/* Let's use src directly, it's just too convenient. */
Sint64 position = SDL_RWseek(src, chunk->position, RW_SEEK_SET);
Uint32 samplelength;
if (position == chunk->position && SDL_RWread(src, &samplelength, sizeof(Uint32), 1) == 1) {
file->fact.status = 1;
file->fact.samplelength = SDL_SwapLE32(samplelength);
} else {
file->fact.status = -1;
}
}
}
}
/* Go through all chunks in verystrict mode or stop the search early if
* all required chunks were found.
*/
if (file->trunchint == TruncVeryStrict) {
if ((Uint64)RIFFend < (Uint64)chunk->position + chunk->length) {
return SDL_SetError("RIFF size truncates chunk");
}
} else if (fmtchunk.fourcc == FMT && datachunk.fourcc == DATA) {
if (file->fact.status == 1 || file->facthint == FactIgnore || file->facthint == FactNoHint) {
break;
}
}
}
/* Save the position after the last chunk. This position will be used if the
* RIFF length is unknown.
*/
lastchunkpos = chunk->position + chunk->length;
/* The fmt chunk is mandatory. */
if (fmtchunk.fourcc != FMT) {
return SDL_SetError("Missing fmt chunk in WAVE file");
}
/* A data chunk must be present. */
if (datachunk.fourcc != DATA) {
return SDL_SetError("Missing data chunk in WAVE file");
}
/* Check if the last chunk has all of its data in verystrict mode. */
if (file->trunchint == TruncVeryStrict) {
/* data chunk is handled later. */
if (chunk->fourcc != DATA && chunk->length > 0) {
Uint8 tmp;
Uint64 position = (Uint64)chunk->position + chunk->length - 1;
if (position > SDL_MAX_SINT64 || SDL_RWseek(src, (Sint64)position, RW_SEEK_SET) != (Sint64)position) {
return SDL_SetError("Could not seek to WAVE chunk data");
} else if (SDL_RWread(src, &tmp, 1, 1) != 1) {
return SDL_SetError("RIFF size truncates chunk");
}
}
}
/* Process fmt chunk. */
*chunk = fmtchunk;
/* No need to read more than 1046 bytes of the fmt chunk data with the
* formats that are currently supported. (1046 because of MS ADPCM coefficients)
*/
if (WaveReadPartialChunkData(src, chunk, 1046) < 0) {
return SDL_SetError("Could not read data of WAVE fmt chunk");
}
/* The fmt chunk data must be at least 14 bytes to include all common fields.
* It usually is 16 and larger depending on the header and encoding.
*/
if (chunk->length < 14) {
return SDL_SetError("Invalid WAVE fmt chunk length (too small)");
} else if (chunk->size < 14) {
return SDL_SetError("Could not read data of WAVE fmt chunk");
} else if (WaveReadFormat(file) < 0) {
return -1;
} else if (WaveCheckFormat(file, (size_t)datachunk.length) < 0) {
return -1;
}
#ifdef SDL_WAVE_DEBUG_LOG_FORMAT
WaveDebugLogFormat(file);
#endif
#ifdef SDL_WAVE_DEBUG_DUMP_FORMAT
WaveDebugDumpFormat(file, RIFFchunk.length, fmtchunk.length, datachunk.length);
#endif
WaveFreeChunkData(chunk);
/* Process data chunk. */
*chunk = datachunk;
if (chunk->length > 0) {
result = WaveReadChunkData(src, chunk);
if (result == -1) {
return -1;
} else if (result == -2) {
return SDL_SetError("Could not seek data of WAVE data chunk");
}
}
if (chunk->length != chunk->size) {
/* I/O issues or corrupt file. */
if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
return SDL_SetError("Could not read data of WAVE data chunk");
}
/* The decoders handle this truncation. */
}
/* Decode or convert the data if necessary. */
switch (format->encoding) {
case PCM_CODE:
case IEEE_FLOAT_CODE:
if (PCM_Decode(file, audio_buf, audio_len) < 0) {
return -1;
}
break;
case ALAW_CODE:
case MULAW_CODE:
if (LAW_Decode(file, audio_buf, audio_len) < 0) {
return -1;
}
break;
case MS_ADPCM_CODE:
if (MS_ADPCM_Decode(file, audio_buf, audio_len) < 0) {
return -1;
}
break;
case IMA_ADPCM_CODE:
if (IMA_ADPCM_Decode(file, audio_buf, audio_len) < 0) {
return -1;
}
break;
}
/* Setting up the SDL_AudioSpec. All unsupported formats were filtered out
* by checks earlier in this function.
*/
SDL_zerop(spec);
spec->freq = format->frequency;
spec->channels = (Uint8)format->channels;
spec->samples = 4096; /* Good default buffer size */
switch (format->encoding) {
case MS_ADPCM_CODE:
case IMA_ADPCM_CODE:
case ALAW_CODE:
case MULAW_CODE:
/* These can be easily stored in the byte order of the system. */
spec->format = AUDIO_S16SYS;
break;
case IEEE_FLOAT_CODE:
spec->format = AUDIO_F32LSB;
break;
case PCM_CODE:
switch (format->bitspersample) {
case 8:
spec->format = AUDIO_U8;
break;
case 16:
spec->format = AUDIO_S16LSB;
break;
case 24: /* Has been shifted to 32 bits. */
case 32:
spec->format = AUDIO_S32LSB;
break;
default:
/* Just in case something unexpected happened in the checks. */
return SDL_SetError("Unexpected %u-bit PCM data format", (unsigned int)format->bitspersample);
}
break;
}
/* Report the end position back to the cleanup code. */
if (RIFFlengthknown) {
chunk->position = RIFFend;
} else {
chunk->position = lastchunkpos;
}
return 0;
}

References ALAW_CODE, AUDIO_F32LSB, AUDIO_S16LSB, AUDIO_S16SYS, AUDIO_S32LSB, AUDIO_U8, SDL_AudioSpec::channels, WaveFile::chunk, DATA, FACT, WaveFile::fact, WaveFile::facthint, FactIgnore, FactNoHint, FMT, WaveFile::format, SDL_AudioSpec::format, WaveChunk::fourcc, SDL_AudioSpec::freq, IEEE_FLOAT_CODE, IMA_ADPCM_CODE, IMA_ADPCM_Decode(), LAW_Decode(), WaveChunk::length, MS_ADPCM_CODE, MS_ADPCM_Decode(), MULAW_CODE, NULL, PCM_CODE, PCM_Decode(), WaveChunk::position, RIFF, WaveFile::riffhint, RiffSizeForce, RiffSizeIgnore, RiffSizeIgnoreZero, RiffSizeMaximum, RW_SEEK_SET, WaveFact::samplelength, SDL_AudioSpec::samples, SDL_FALSE, SDL_getenv, SDL_MAX_SINT64, SDL_MAX_UINT32, SDL_RWread, SDL_RWseek, SDL_RWtell, SDL_SetError, SDL_sscanf, SDL_SwapLE32, SDL_TRUE, SDL_zero, SDL_zerop, WaveChunk::size, spec, WaveFact::status, WaveFile::trunchint, TruncStrict, TruncVeryStrict, WAVE, WaveCheckFormat(), WaveFreeChunkData(), WaveNextChunk(), WaveReadChunkData(), WaveReadFormat(), and WaveReadPartialChunkData().

Referenced by SDL_LoadWAV_RW().

## WaveNextChunk()

static int WaveNextChunk | ( | SDL_RWops * | src,
|  | WaveChunk * | chunk
| ) |  |

static

Definition at line 1521 of file SDL_wave.c.

{
Uint32 chunkheader[2];
Sint64 nextposition = chunk->position + chunk->length;
/* Data is no longer valid after this function returns. */
WaveFreeChunkData(chunk);
/* Error on overflows. */
if (SDL_MAX_SINT64 - chunk->length < chunk->position || SDL_MAX_SINT64 - 8 < nextposition) {
return -1;
}
/* RIFF chunks have a 2-byte alignment. Skip padding byte. */
if (chunk->length & 1) {
nextposition++;
}
if (SDL_RWseek(src, nextposition, RW_SEEK_SET) != nextposition) {
/* Not sure how we ended up here. Just abort. */
return -2;
} else if (SDL_RWread(src, chunkheader, 4, 2) != 2) {
return -1;
}
chunk->fourcc = SDL_SwapLE32(chunkheader[0]);
chunk->length = SDL_SwapLE32(chunkheader[1]);
chunk->position = nextposition + 8;
return 0;
}

References WaveChunk::fourcc, WaveChunk::length, WaveChunk::position, RW_SEEK_SET, SDL_MAX_SINT64, SDL_RWread, SDL_RWseek, SDL_SwapLE32, and WaveFreeChunkData().

Referenced by WaveLoad().

## WaveReadChunkData()

static int WaveReadChunkData | ( | SDL_RWops * | src,
|  | WaveChunk * | chunk
| ) |  |

static

Definition at line 1583 of file SDL_wave.c.

{
return WaveReadPartialChunkData(src, chunk, chunk->length);
}

References WaveChunk::length, and WaveReadPartialChunkData().

Referenced by WaveLoad().

## WaveReadFormat()

static int WaveReadFormat | ( | WaveFile * | file | ) |

static

Definition at line 1617 of file SDL_wave.c.

{
WaveChunk *chunk = &file->chunk;
WaveFormat *format = &file->format;
SDL_RWops *fmtsrc;
size_t fmtlen = chunk->size;
if (fmtlen > SDL_MAX_SINT32) {
/* Limit given by SDL_RWFromConstMem. */
return SDL_SetError("Data of WAVE fmt chunk too big");
}
fmtsrc = SDL_RWFromConstMem(chunk->data, (int)chunk->size);
if (fmtsrc == NULL) {
return SDL_OutOfMemory();
}
format->formattag = SDL_ReadLE16(fmtsrc);
format->encoding = format->formattag;
format->channels = SDL_ReadLE16(fmtsrc);
format->frequency = SDL_ReadLE32(fmtsrc);
format->byterate = SDL_ReadLE32(fmtsrc);
format->blockalign = SDL_ReadLE16(fmtsrc);
/* This is PCM specific in the first version of the specification. */
if (fmtlen >= 16) {
format->bitspersample = SDL_ReadLE16(fmtsrc);
} else if (format->encoding == PCM_CODE) {
SDL_RWclose(fmtsrc);
return SDL_SetError("Missing wBitsPerSample field in WAVE fmt chunk");
}
/* The earlier versions also don't have this field. */
if (fmtlen >= 18) {
format->extsize = SDL_ReadLE16(fmtsrc);
}
if (format->formattag == 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.
*/
/* Extensible header must be at least 22 bytes. */
if (fmtlen < 40 || format->extsize < 22) {
SDL_RWclose(fmtsrc);
return SDL_SetError("Extensible WAVE header too small");
}
format->validsamplebits = SDL_ReadLE16(fmtsrc);
format->samplesperblock = format->validsamplebits;
format->channelmask = SDL_ReadLE32(fmtsrc);
SDL_RWread(fmtsrc, format->subformat, 1, 16);
format->encoding = WaveGetFormatGUIDEncoding(format);
}
SDL_RWclose(fmtsrc);
return 0;
}

References WaveFile::chunk, WaveChunk::data, EXTENSIBLE_CODE, WaveFile::format, NULL, PCM_CODE, SDL_MAX_SINT32, SDL_OutOfMemory, SDL_ReadLE16, SDL_ReadLE32, SDL_RWclose, SDL_RWFromConstMem, SDL_RWread, SDL_SetError, WaveChunk::size, and WaveGetFormatGUIDEncoding().

Referenced by WaveLoad().

## WaveReadPartialChunkData()

static int WaveReadPartialChunkData | ( | SDL_RWops * | src,
|  | WaveChunk * | chunk,
|  | size_t | length
| ) |  |

static

Definition at line 1554 of file SDL_wave.c.

{
WaveFreeChunkData(chunk);
if (length > chunk->length) {
length = chunk->length;
}
if (length > 0) {
chunk->data = SDL_malloc(length);
if (chunk->data == NULL) {
return SDL_OutOfMemory();
}
if (SDL_RWseek(src, chunk->position, RW_SEEK_SET) != chunk->position) {
/* Not sure how we ended up here. Just abort. */
return -2;
}
chunk->size = SDL_RWread(src, chunk->data, 1, length);
if (chunk->size != length) {
/* Expected to be handled by the caller. */
}
}
return 0;
}

References WaveChunk::data, WaveChunk::length, NULL, WaveChunk::position, RW_SEEK_SET, SDL_malloc, SDL_OutOfMemory, SDL_RWread, SDL_RWseek, WaveChunk::size, and WaveFreeChunkData().

Referenced by WaveLoad(), and WaveReadChunkData().

## Variable Documentation

## extensible_guids

WaveExtensibleGUID extensible_guids[]

static

Initial value:
= {
{PCM_CODE, WAVE_FORMATTAG_GUID(PCM_CODE)},
{MS_ADPCM_CODE, WAVE_FORMATTAG_GUID(MS_ADPCM_CODE)},
{IEEE_FLOAT_CODE, WAVE_FORMATTAG_GUID(IEEE_FLOAT_CODE)},
{ALAW_CODE, WAVE_FORMATTAG_GUID(ALAW_CODE)},
{MULAW_CODE, WAVE_FORMATTAG_GUID(MULAW_CODE)},
{IMA_ADPCM_CODE, WAVE_FORMATTAG_GUID(IMA_ADPCM_CODE)}
}

Definition at line 1595 of file SDL_wave.c.

Referenced by WaveGetFormatGUIDEncoding().

SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
WaveGetFactChunkHint
static WaveFactChunkHint WaveGetFactChunkHint()
Definition: SDL_wave.c:1491
c
const GLubyte * c
Definition: SDL_opengl_glext.h:11093
MS_ADPCM_CoeffData::coeff
Sint16 * coeff
Definition: SDL_wave.c:94
SDL_AudioSpec::channels
Uint8 channels
Definition: SDL_audio.h:182
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
TruncVeryStrict
@ TruncVeryStrict
Definition: SDL_wave.h:115
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:197
WaveGetRiffSizeHint
static WaveRiffSizeHint WaveGetRiffSizeHint()
Definition: SDL_wave.c:1451
SIZE_MAX
#define SIZE_MAX
Definition: SDL_wave.c:27
WaveFile::format
WaveFormat format
Definition: SDL_wave.h:133
Sint64
int64_t Sint64
Definition: SDL_stdinc.h:210
TruncNoHint
@ TruncNoHint
Definition: SDL_wave.h:114
WaveChunk::data
Uint8 * data
Definition: SDL_wave.h:99
PCM_Decode
static int PCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:1408
MS_ADPCM_ChannelState::delta
Uint16 delta
Definition: SDL_wave.c:100
NULL
#define NULL
Definition: begin_code.h:167
b
GLboolean GLboolean GLboolean b
Definition: SDL_opengl_glext.h:1109
MS_ADPCM_CoeffData::aligndummy
Sint16 aligndummy
Definition: SDL_wave.c:95
SDL_AudioSpec::samples
Uint16 samples
Definition: SDL_audio.h:184
WaveFile::riffhint
WaveRiffSizeHint riffhint
Definition: SDL_wave.h:144
g
GLboolean GLboolean g
Definition: SDL_opengl_glext.h:1109
exponent
GLint * exponent
Definition: SDL_opengl_glext.h:4711
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
samples
GLsizei samples
Definition: SDL_opengl_glext.h:1185
SDL_LoadWAV_RW
#define SDL_LoadWAV_RW
Definition: SDL_dynapi_overrides.h:86
SDL_AudioSpec::format
SDL_AudioFormat format
Definition: SDL_audio.h:181
count
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
MS_ADPCM_Decode
static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:641
SafeMult
static int SafeMult(size_t *f1, size_t f2)
Definition: SDL_wave.c:48
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
SDL_InvalidParamError
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
MS_ADPCM_ChannelState::coeff1
Sint16 coeff1
Definition: SDL_wave.c:101
IMA_ADPCM_CalculateSampleFrames
static int IMA_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:741
IMA_ADPCM_DecodeBlockHeader
static int IMA_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state)
Definition: SDL_wave.c:927
RiffSizeForce
@ RiffSizeForce
Definition: SDL_wave.h:106
RIFF
#define RIFF
Definition: SDL_wave.h:29
MS_ADPCM_ChannelState
Definition: SDL_wave.c:98
SDL_RWread
#define SDL_RWread
Definition: SDL_dynapi_overrides.h:723
WaveFormat::bitspersample
Uint16 bitspersample
Definition: SDL_wave.h:58
index
GLuint index
Definition: SDL_opengl_glext.h:660
SDL_GetHint
#define SDL_GetHint
Definition: SDL_dynapi_overrides.h:191
WaveFile
Definition: SDL_wave.h:130
SDL_ReadLE32
#define SDL_ReadLE32
Definition: SDL_dynapi_overrides.h:359
RiffSizeNoHint
@ RiffSizeNoHint
Definition: SDL_wave.h:105
MS_ADPCM_DecodeBlockHeader
static int MS_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state)
Definition: SDL_wave.c:532
length
GLuint GLsizei GLsizei * length
Definition: SDL_opengl_glext.h:669
WaveLoad
static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:1787
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9432
WaveReadPartialChunkData
static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t length)
Definition: SDL_wave.c:1554
WaveFile::facthint
WaveFactChunkHint facthint
Definition: SDL_wave.h:146
ALAW_CODE
#define ALAW_CODE
Definition: SDL_wave.h:42
IMA_ADPCM_DecodeBlockData
static int IMA_ADPCM_DecodeBlockData(ADPCM_DecoderState *state)
Definition: SDL_wave.c:967
RiffSizeIgnore
@ RiffSizeIgnore
Definition: SDL_wave.h:108
DATA
#define DATA
Definition: SDL_wave.h:36
AUDIO_S16SYS
#define AUDIO_S16SYS
Definition: SDL_audio.h:128
WaveFormat
Definition: SDL_wave.h:50
dst
GLenum GLenum dst
Definition: SDL_opengl_glext.h:1737
WaveFormat::encoding
Uint16 encoding
Definition: SDL_wave.h:53
FactTruncate
@ FactTruncate
Definition: SDL_wave.h:124
AUDIO_U8
#define AUDIO_U8
Definition: SDL_audio.h:89
WaveChunk::size
size_t size
Definition: SDL_wave.h:100
MPEGLAYER3_CODE
#define MPEGLAYER3_CODE
Definition: SDL_wave.h:46
PCM_CODE
#define PCM_CODE
Definition: SDL_wave.h:39
TruncDropFrame
@ TruncDropFrame
Definition: SDL_wave.h:117
Sint16
int16_t Sint16
Definition: SDL_stdinc.h:185
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_ReadLE16
#define SDL_ReadLE16
Definition: SDL_dynapi_overrides.h:357
WaveReadFormat
static int WaveReadFormat(WaveFile *file)
Definition: SDL_wave.c:1617
WaveFact::samplelength
Uint32 samplelength
Definition: SDL_wave.h:90
WaveReadChunkData
static int WaveReadChunkData(SDL_RWops *src, WaveChunk *chunk)
Definition: SDL_wave.c:1583
FactStrict
@ FactStrict
Definition: SDL_wave.h:125
retval
SDL_bool retval
Definition: testgamecontroller.c:65
WaveChunk::fourcc
Uint32 fourcc
Definition: SDL_wave.h:96
WaveNextChunk
static int WaveNextChunk(SDL_RWops *src, WaveChunk *chunk)
Definition: SDL_wave.c:1521
WaveGetTruncationHint
static WaveTruncationHint WaveGetTruncationHint()
Definition: SDL_wave.c:1471
IMA_ADPCM_Decode
static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:1037
SDL_memcmp
#define SDL_memcmp
Definition: SDL_dynapi_overrides.h:389
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_RWFromFile
#define SDL_RWFromFile
Definition: SDL_dynapi_overrides.h:351
WaveFactChunkHint
WaveFactChunkHint
Definition: SDL_wave.h:122
FMT
#define FMT
Definition: SDL_wave.h:35
WaveExtensibleGUID::guid
Uint8 guid[16]
Definition: SDL_wave.c:1590
FACT
#define FACT
Definition: SDL_wave.h:31
WaveFile::trunchint
WaveTruncationHint trunchint
Definition: SDL_wave.h:145
SDL_RWseek
#define SDL_RWseek
Definition: SDL_dynapi_overrides.h:721
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
nibble
static unsigned char nibble(char c)
Definition: SDL_joystick.c:1654
WaveFile::sampleframes
Sint64 sampleframes
Definition: SDL_wave.h:140
WaveGetFormatGUIDEncoding
static Uint16 WaveGetFormatGUIDEncoding(WaveFormat *format)
Definition: SDL_wave.c:1605
WAVE
#define WAVE
Definition: SDL_wave.h:30
IEEE_FLOAT_CODE
#define IEEE_FLOAT_CODE
Definition: SDL_wave.h:41
AUDIO_F32LSB
#define AUDIO_F32LSB
Definition: SDL_audio.h:112
WaveFact::status
Sint32 status
Definition: SDL_wave.h:80
ADPCM_DecoderState
Definition: SDL_wave.c:57
SDL_AudioSpec::freq
int freq
Definition: SDL_audio.h:180
WaveFormat::samplesperblock
Uint32 samplesperblock
Definition: SDL_wave.h:67
MS_ADPCM_CoeffData::coeffcount
Uint16 coeffcount
Definition: SDL_wave.c:93
WaveFile::chunk
WaveChunk chunk
Definition: SDL_wave.h:132
WaveCheckFormat
static int WaveCheckFormat(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:1679
AUDIO_S32LSB
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
FactIgnoreZero
@ FactIgnoreZero
Definition: SDL_wave.h:126
SDL_sscanf
#define SDL_sscanf
Definition: SDL_dynapi_overrides.h:39
MS_ADPCM_ProcessNibble
static Sint16 MS_ADPCM_ProcessNibble(MS_ADPCM_ChannelState *cstate, Sint32 sample1, Sint32 sample2, Uint8 nybble)
Definition: SDL_wave.c:495
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
LAW_Init
static int LAW_Init(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:1141
MPEG_CODE
#define MPEG_CODE
Definition: SDL_wave.h:45
spec
SDL_AudioSpec spec
Definition: loopwave.c:31
WaveFile::fact
WaveFact fact
Definition: SDL_wave.h:134
UNKNOWN_CODE
#define UNKNOWN_CODE
Definition: SDL_wave.h:38
FactIgnore
@ FactIgnore
Definition: SDL_wave.h:127
SDL_RWtell
#define SDL_RWtell
Definition: SDL_dynapi_overrides.h:722
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
SDL_HINT_WAVE_FACT_CHUNK
#define SDL_HINT_WAVE_FACT_CHUNK
Controls how the fact chunk affects the loading of a WAVE file.
Definition: SDL_hints.h:1175
MS_ADPCM_DecodeBlockData
static int MS_ADPCM_DecodeBlockData(ADPCM_DecoderState *state)
Definition: SDL_wave.c:593
WaveChunk::length
Uint32 length
Definition: SDL_wave.h:97
src
GLenum src
Definition: SDL_opengl_glext.h:1737
SDL_getenv
#define SDL_getenv
Definition: SDL_dynapi_overrides.h:378
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
extensible_guids
static WaveExtensibleGUID extensible_guids[]
Definition: SDL_wave.c:1595
MS_ADPCM_ChannelState::coeff2
Sint16 coeff2
Definition: SDL_wave.c:102
RW_SEEK_SET
#define RW_SEEK_SET
Definition: SDL_rwops.h:174
INT_MAX
#define INT_MAX
Definition: SDL_wave.c:31
uint8_t
unsigned char uint8_t
Definition: SDL_config_windows.h:59
MS_ADPCM_Init
static int MS_ADPCM_Init(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:376
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
RiffSizeIgnoreZero
@ RiffSizeIgnoreZero
Definition: SDL_wave.h:107
Uint64
uint64_t Uint64
Definition: SDL_stdinc.h:216
SDL_MAX_SINT32
#define SDL_MAX_SINT32
A signed 32-bit integer type.
Definition: SDL_stdinc.h:195
WaveChunk
Definition: SDL_wave.h:94
SDL_RWclose
#define SDL_RWclose
Definition: SDL_dynapi_overrides.h:725
MS_ADPCM_CalculateSampleFrames
static int MS_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:336
WaveExtensibleGUID::encoding
Uint16 encoding
Definition: SDL_wave.c:1589
TruncDropBlock
@ TruncDropBlock
Definition: SDL_wave.h:118
IMA_ADPCM_Init
static int IMA_ADPCM_Init(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:795
SDL_MAX_SINT64
#define SDL_MAX_SINT64
A signed 64-bit integer type.
Definition: SDL_stdinc.h:208
WaveFreeChunkData
static void WaveFreeChunkData(WaveChunk *chunk)
Definition: SDL_wave.c:1511
SDL_HINT_WAVE_TRUNCATION
#define SDL_HINT_WAVE_TRUNCATION
Controls how a truncated WAVE file is handled.
Definition: SDL_hints.h:1148
MS_ADPCM_CoeffData
Definition: SDL_wave.c:91
FactNoHint
@ FactNoHint
Definition: SDL_wave.h:123
AUDIO_S16LSB
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
size_t
unsigned int size_t
Definition: SDL_config_windows.h:68
LAW_Decode
static int LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:1170
WaveFormat::channels
Uint16 channels
Definition: SDL_wave.h:54
TruncStrict
@ TruncStrict
Definition: SDL_wave.h:116
RiffSizeMaximum
@ RiffSizeMaximum
Definition: SDL_wave.h:109
MULAW_CODE
#define MULAW_CODE
Definition: SDL_wave.h:43
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
WaveFormat::blockalign
Uint16 blockalign
Definition: SDL_wave.h:57
SDL_strcmp
#define SDL_strcmp
Definition: SDL_dynapi_overrides.h:417
SDL_RWFromConstMem
#define SDL_RWFromConstMem
Definition: SDL_dynapi_overrides.h:353
SDL_HINT_WAVE_RIFF_CHUNK_SIZE
#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE
Controls how the size of the RIFF chunk affects the loading of a WAVE file.
Definition: SDL_hints.h:1132
SDL_RWops
Definition: SDL_rwops.h:52
PCM_Init
static int PCM_Init(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:1313
Sint8
int8_t Sint8
Definition: SDL_stdinc.h:173
WaveChunk::position
Sint64 position
Definition: SDL_wave.h:98
state
struct xkb_state * state
Definition: SDL_waylandsym.h:113
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
PCM_ConvertSint24ToSint32
static int PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:1356
WaveFile::decoderdata
void * decoderdata
Definition: SDL_wave.h:142
EXTENSIBLE_CODE
#define EXTENSIBLE_CODE
Definition: SDL_wave.h:47
WAVE_FORMATTAG_GUID
#define WAVE_FORMATTAG_GUID(tag)
Definition: SDL_wave.c:1594
SDL_SwapLE32
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:242
IMA_ADPCM_CODE
#define IMA_ADPCM_CODE
Definition: SDL_wave.h:44
WaveAdjustToFactValue
static Sint64 WaveAdjustToFactValue(WaveFile *file, Sint64 sampleframes)
Definition: SDL_wave.c:322
MS_ADPCM_CODE
#define MS_ADPCM_CODE
Definition: SDL_wave.h:40
SDL_MAX_UINT32
#define SDL_MAX_UINT32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:201
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
IMA_ADPCM_ProcessNibble
static Sint16 IMA_ADPCM_ProcessNibble(Sint8 *cindex, Sint16 lastsample, Uint8 nybble)
Definition: SDL_wave.c:861
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179