SDL  2.0
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_AudioSpecSDL_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.

742 {
743  WaveFormat *format = &file->format;
744  const size_t blockheadersize = (size_t)format->channels * 4;
745  const size_t subblockframesize = (size_t)format->channels * 4;
746  const size_t availableblocks = datalength / format->blockalign;
747  const size_t trailingdata = datalength % format->blockalign;
748 
749  if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
750  /* The size of the data chunk must be a multiple of the block size. */
751  if (datalength < blockheadersize || trailingdata > 0) {
752  return SDL_SetError("Truncated IMA ADPCM block");
753  }
754  }
755 
756  /* Calculate number of sample frames that will be decoded. */
757  file->sampleframes = (Uint64)availableblocks * format->samplesperblock;
758  if (trailingdata > 0) {
759  /* The last block is truncated. Check if we can get any samples out of it. */
760  if (file->trunchint == TruncDropFrame && trailingdata > blockheadersize - 2) {
761  /* The sample frame in the header of the truncated block is present.
762  * Drop incomplete sample frames.
763  */
764  size_t trailingsamples = 1;
765 
766  if (trailingdata > blockheadersize) {
767  /* More data following after the header. */
768  const size_t trailingblockdata = trailingdata - blockheadersize;
769  const size_t trailingsubblockdata = trailingblockdata % subblockframesize;
770  trailingsamples += (trailingblockdata / subblockframesize) * 8;
771  /* Due to the interleaved sub-blocks, the last 4 bytes determine
772  * how many samples of the truncated sub-block are lost.
773  */
774  if (trailingsubblockdata > subblockframesize - 4) {
775  trailingsamples += (trailingsubblockdata % 4) * 2;
776  }
777  }
778 
779  if (trailingsamples > format->samplesperblock) {
780  trailingsamples = format->samplesperblock;
781  }
782  file->sampleframes += trailingsamples;
783  }
784  }
785 
786  file->sampleframes = WaveAdjustToFactValue(file, file->sampleframes);
787  if (file->sampleframes < 0) {
788  return -1;
789  }
790 
791  return 0;
792 }

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.

1038 {
1039  int result;
1040  size_t bytesleft, outputsize;
1041  WaveChunk *chunk = &file->chunk;
1043  Sint8 *cstate;
1044 
1045  if (chunk->size != chunk->length) {
1046  /* Could not read everything. Recalculate number of sample frames. */
1047  if (IMA_ADPCM_CalculateSampleFrames(file, chunk->size) < 0) {
1048  return -1;
1049  }
1050  }
1051 
1052  /* Nothing to decode, nothing to return. */
1053  if (file->sampleframes == 0) {
1054  *audio_buf = NULL;
1055  *audio_len = 0;
1056  return 0;
1057  }
1058 
1059  SDL_zero(state);
1060  state.channels = file->format.channels;
1061  state.blocksize = file->format.blockalign;
1062  state.blockheadersize = (size_t)state.channels * 4;
1063  state.samplesperblock = file->format.samplesperblock;
1064  state.framesize = state.channels * sizeof(Sint16);
1065  state.framestotal = file->sampleframes;
1066  state.framesleft = state.framestotal;
1067 
1068  state.input.data = chunk->data;
1069  state.input.size = chunk->size;
1070  state.input.pos = 0;
1071 
1072  /* The output size in bytes. May get modified if data is truncated. */
1073  outputsize = (size_t)state.framestotal;
1074  if (SafeMult(&outputsize, state.framesize)) {
1075  return SDL_OutOfMemory();
1076  } else if (outputsize > SDL_MAX_UINT32 || state.framestotal > SIZE_MAX) {
1077  return SDL_SetError("WAVE file too big");
1078  }
1079 
1080  state.output.pos = 0;
1081  state.output.size = outputsize / sizeof(Sint16);
1082  state.output.data = (Sint16 *)SDL_malloc(outputsize);
1083  if (state.output.data == NULL) {
1084  return SDL_OutOfMemory();
1085  }
1086 
1087  cstate = (Sint8 *)SDL_calloc(state.channels, sizeof(Sint8));
1088  if (cstate == NULL) {
1089  SDL_free(state.output.data);
1090  return SDL_OutOfMemory();
1091  }
1092  state.cstate = cstate;
1093 
1094  /* Decode block by block. A truncated block will stop the decoding. */
1095  bytesleft = state.input.size - state.input.pos;
1096  while (state.framesleft > 0 && bytesleft >= state.blockheadersize) {
1097  state.block.data = state.input.data + state.input.pos;
1098  state.block.size = bytesleft < state.blocksize ? bytesleft : state.blocksize;
1099  state.block.pos = 0;
1100 
1101  if (state.output.size - state.output.pos < (Uint64)state.framesleft * state.channels) {
1102  /* Somehow didn't allocate enough space for the output. */
1103  SDL_free(state.output.data);
1104  SDL_free(cstate);
1105  return SDL_SetError("Unexpected overflow in IMA ADPCM decoder");
1106  }
1107 
1108  /* Initialize decoder with the values from the block header. */
1110  if (result == 0) {
1111  /* Decode the block data. It stores the samples directly in the output. */
1113  }
1114 
1115  if (result == -1) {
1116  /* Unexpected end. Stop decoding and return partial data if necessary. */
1117  if (file->trunchint == TruncVeryStrict || file->trunchint == TruncVeryStrict) {
1118  SDL_free(state.output.data);
1119  SDL_free(cstate);
1120  return SDL_SetError("Truncated data chunk");
1121  } else if (file->trunchint != TruncDropFrame) {
1122  state.output.pos -= state.output.pos % (state.samplesperblock * state.channels);
1123  }
1124  outputsize = state.output.pos * sizeof(Sint16); /* Can't overflow, is always smaller. */
1125  break;
1126  }
1127 
1128  state.input.pos += state.block.size;
1129  bytesleft = state.input.size - state.input.pos;
1130  }
1131 
1132  *audio_buf = (Uint8 *)state.output.data;
1133  *audio_len = (Uint32)outputsize;
1134 
1135  SDL_free(cstate);
1136 
1137  return 0;
1138 }

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.

968 {
969  size_t i;
970  int retval = 0;
971  const Uint32 channels = state->channels;
972  const size_t subblockframesize = channels * 4;
973  Uint64 bytesrequired;
974  Uint32 c;
975 
976  size_t blockpos = state->block.pos;
977  size_t blocksize = state->block.size;
978  size_t blockleft = blocksize - blockpos;
979 
980  size_t outpos = state->output.pos;
981 
982  Sint64 blockframesleft = state->samplesperblock - 1;
983  if (blockframesleft > state->framesleft) {
984  blockframesleft = state->framesleft;
985  }
986 
987  bytesrequired = (blockframesleft + 7) / 8 * subblockframesize;
988  if (blockleft < bytesrequired) {
989  /* Data truncated. Calculate how many samples we can get out if it. */
990  const size_t guaranteedframes = blockleft / subblockframesize;
991  const size_t remainingbytes = blockleft % subblockframesize;
992  blockframesleft = guaranteedframes;
993  if (remainingbytes > subblockframesize - 4) {
994  blockframesleft += (remainingbytes % 4) * 2;
995  }
996  /* Signal the truncation. */
997  retval = -1;
998  }
999 
1000  /* Each channel has their nibbles packed into 32-bit blocks. These blocks
1001  * are interleaved and make up the data part of the ADPCM block. This loop
1002  * decodes the samples as they come from the input data and puts them at
1003  * the appropriate places in the output data.
1004  */
1005  while (blockframesleft > 0) {
1006  const size_t subblocksamples = blockframesleft < 8 ? (size_t)blockframesleft : 8;
1007 
1008  for (c = 0; c < channels; c++) {
1009  Uint8 nybble = 0;
1010  /* Load previous sample which may come from the block header. */
1011  Sint16 sample = state->output.data[outpos + c - channels];
1012 
1013  for (i = 0; i < subblocksamples; i++) {
1014  if (i & 1) {
1015  nybble >>= 4;
1016  } else {
1017  nybble = state->block.data[blockpos++];
1018  }
1019 
1020  sample = IMA_ADPCM_ProcessNibble((Sint8 *)state->cstate + c, sample, nybble & 0x0f);
1021  state->output.data[outpos + c + i * channels] = sample;
1022  }
1023  }
1024 
1025  outpos += channels * subblocksamples;
1026  state->framesleft -= subblocksamples;
1027  blockframesleft -= subblocksamples;
1028  }
1029 
1030  state->block.pos = blockpos;
1031  state->output.pos = outpos;
1032 
1033  return retval;
1034 }

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.

928 {
929  Sint16 step;
930  Uint32 c;
931  Uint8 *cstate = state->cstate;
932 
933  for (c = 0; c < state->channels; c++) {
934  size_t o = state->block.pos + c * 4;
935 
936  /* Extract the sample from the header. */
937  Sint32 sample = state->block.data[o] | ((Sint32)state->block.data[o + 1] << 8);
938  if (sample >= 0x8000) {
939  sample -= 0x10000;
940  }
941  state->output.data[state->output.pos++] = (Sint16)sample;
942 
943  /* Channel step index. */
944  step = (Sint16)state->block.data[o + 2];
945  cstate[c] = (Sint8)(step > 0x80 ? step - 0x100 : step);
946 
947  /* Reserved byte in block header, should be 0. */
948  if (state->block.data[o + 3] != 0) {
949  /* Uh oh, corrupt data? Buggy code? */ ;
950  }
951  }
952 
953  state->block.pos += state->blockheadersize;
954 
955  /* Header provided one sample frame. */
956  state->framesleft--;
957 
958  return 0;
959 }

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.

796 {
797  WaveFormat *format = &file->format;
798  WaveChunk *chunk = &file->chunk;
799  const size_t blockheadersize = (size_t)format->channels * 4;
800  const size_t blockdatasize = (size_t)format->blockalign - blockheadersize;
801  const size_t blockframebitsize = (size_t)format->bitspersample * format->channels;
802  const size_t blockdatasamples = (blockdatasize * 8) / blockframebitsize;
803 
804  /* Sanity checks. */
805 
806  /* IMA ADPCM can also have 3-bit samples, but it's not supported by SDL at this time. */
807  if (format->bitspersample == 3) {
808  return SDL_SetError("3-bit IMA ADPCM currently not supported");
809  } else if (format->bitspersample != 4) {
810  return SDL_SetError("Invalid IMA ADPCM bits per sample of %u", (unsigned int)format->bitspersample);
811  }
812 
813  /* The block size is required to be a multiple of 4 and it must be able to
814  * hold a block header.
815  */
816  if (format->blockalign < blockheadersize || format->blockalign % 4) {
817  return SDL_SetError("Invalid IMA ADPCM block size (nBlockAlign)");
818  }
819 
820  if (format->formattag == EXTENSIBLE_CODE) {
821  /* There's no specification for this, but it's basically the same
822  * format because the extensible header has wSampePerBlocks too.
823  */
824  } else {
825  /* The Standards Update says there 'should' be 2 bytes for wSamplesPerBlock. */
826  if (chunk->size >= 20 && format->extsize >= 2) {
827  format->samplesperblock = chunk->data[18] | ((Uint16)chunk->data[19] << 8);
828  }
829  }
830 
831  if (format->samplesperblock == 0) {
832  /* Field zero? No problem. We just assume the encoder packed the block.
833  * The specification calculates it this way:
834  *
835  * x = Block size (in bits) minus header size (in bits)
836  * y = Bit depth multiplied by channel count
837  * z = Number of samples per channel in header
838  * wSamplesPerBlock = x / y + z
839  */
840  format->samplesperblock = (Uint32)blockdatasamples + 1;
841  }
842 
843  /* nBlockAlign can be in conflict with wSamplesPerBlock. For example, if
844  * the number of samples doesn't fit into the block. The Standards Update
845  * also describes wSamplesPerBlock with a formula that makes it necessary
846  * to always fill the block with the maximum amount of samples, but this is
847  * not enforced here as there are no compatibility issues.
848  */
849  if (blockdatasamples < format->samplesperblock - 1) {
850  return SDL_SetError("Invalid number of samples per IMA ADPCM block (wSamplesPerBlock)");
851  }
852 
853  if (IMA_ADPCM_CalculateSampleFrames(file, datalength) < 0) {
854  return -1;
855  }
856 
857  return 0;
858 }

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.

862 {
863  const Sint32 max_audioval = 32767;
864  const Sint32 min_audioval = -32768;
865  const Sint8 index_table_4b[16] = {
866  -1, -1, -1, -1,
867  2, 4, 6, 8,
868  -1, -1, -1, -1,
869  2, 4, 6, 8
870  };
871  const Uint16 step_table[89] = {
872  7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
873  34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130,
874  143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408,
875  449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282,
876  1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
877  3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
878  9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350,
879  22385, 24623, 27086, 29794, 32767
880  };
881  Uint32 step;
882  Sint32 sample, delta;
883  Sint8 index = *cindex;
884 
885  /* Clamp index into valid range. */
886  if (index > 88) {
887  index = 88;
888  } else if (index < 0) {
889  index = 0;
890  }
891 
892  /* explicit cast to avoid gcc warning about using 'char' as array index */
893  step = step_table[(size_t)index];
894 
895  /* Update index value */
896  *cindex = index + index_table_4b[nybble];
897 
898  /* This calculation uses shifts and additions because multiplications were
899  * much slower back then. Sadly, this can't just be replaced with an actual
900  * multiplication now as the old algorithm drops some bits. The closest
901  * approximation I could find is something like this:
902  * (nybble & 0x8 ? -1 : 1) * ((nybble & 0x7) * step / 4 + step / 8)
903  */
904  delta = step >> 3;
905  if (nybble & 0x04)
906  delta += step;
907  if (nybble & 0x02)
908  delta += step >> 1;
909  if (nybble & 0x01)
910  delta += step >> 2;
911  if (nybble & 0x08)
912  delta = -delta;
913 
914  sample = lastsample + delta;
915 
916  /* Clamp output sample */
917  if (sample > max_audioval) {
918  sample = max_audioval;
919  } else if (sample < min_audioval) {
920  sample = min_audioval;
921  }
922 
923  return (Sint16)sample;
924 }

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.

1171 {
1172 #ifdef SDL_WAVE_LAW_LUT
1173  const Sint16 alaw_lut[256] = {
1174  -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, -2752,
1175  -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, -22016,
1176  -20992, -24064, -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, -11008,
1177  -10496, -12032, -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, -344,
1178  -328, -376, -360, -280, -264, -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88,
1179  -72, -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, -184, -168, -1376,
1180  -1312, -1504, -1440, -1120, -1056, -1248, -1184, -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688,
1181  -656, -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, -784, -880, -848, 5504,
1182  5248, 6016, 5760, 4480, 4224, 4992, 4736, 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, 2752,
1183  2624, 3008, 2880, 2240, 2112, 2496, 2368, 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, 22016,
1184  20992, 24064, 23040, 17920, 16896, 19968, 18944, 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, 11008,
1185  10496, 12032, 11520, 8960, 8448, 9984, 9472, 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, 344,
1186  328, 376, 360, 280, 264, 312, 296, 472, 456, 504, 488, 408, 392, 440, 424, 88,
1187  72, 120, 104, 24, 8, 56, 40, 216, 200, 248, 232, 152, 136, 184, 168, 1376,
1188  1312, 1504, 1440, 1120, 1056, 1248, 1184, 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, 688,
1189  656, 752, 720, 560, 528, 624, 592, 944, 912, 1008, 976, 816, 784, 880, 848
1190  };
1191  const Sint16 mulaw_lut[256] = {
1192  -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, -15996,
1193  -15484, -14972, -14460, -13948, -13436, -12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, -7932,
1194  -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900,
1195  -3772, -3644, -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, -1884,
1196  -1820, -1756, -1692, -1628, -1564, -1500, -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876,
1197  -844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, -492, -460, -428, -396, -372,
1198  -356, -340, -324, -308, -292, -276, -260, -244, -228, -212, -196, -180, -164, -148, -132, -120,
1199  -112, -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, 32124,
1200  31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 15996,
1201  15484, 14972, 14460, 13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, 7932,
1202  7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900,
1203  3772, 3644, 3516, 3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, 1884,
1204  1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, 876,
1205  844, 812, 780, 748, 716, 684, 652, 620, 588, 556, 524, 492, 460, 428, 396, 372,
1206  356, 340, 324, 308, 292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120,
1207  112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0
1208  };
1209 #endif
1210 
1211  WaveFormat *format = &file->format;
1212  WaveChunk *chunk = &file->chunk;
1213  size_t i, sample_count, expanded_len;
1214  Uint8 *src;
1215  Sint16 *dst;
1216 
1217  if (chunk->length != chunk->size) {
1218  file->sampleframes = WaveAdjustToFactValue(file, chunk->size / format->blockalign);
1219  if (file->sampleframes < 0) {
1220  return -1;
1221  }
1222  }
1223 
1224  /* Nothing to decode, nothing to return. */
1225  if (file->sampleframes == 0) {
1226  *audio_buf = NULL;
1227  *audio_len = 0;
1228  return 0;
1229  }
1230 
1231  sample_count = (size_t)file->sampleframes;
1232  if (SafeMult(&sample_count, format->channels)) {
1233  return SDL_OutOfMemory();
1234  }
1235 
1236  expanded_len = sample_count;
1237  if (SafeMult(&expanded_len, sizeof(Sint16))) {
1238  return SDL_OutOfMemory();
1239  } else if (expanded_len > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
1240  return SDL_SetError("WAVE file too big");
1241  }
1242 
1243  /* 1 to avoid allocating zero bytes, to keep static analysis happy. */
1244  src = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1);
1245  if (src == NULL) {
1246  return SDL_OutOfMemory();
1247  }
1248  chunk->data = NULL;
1249  chunk->size = 0;
1250 
1251  dst = (Sint16 *)src;
1252 
1253  /* Work backwards, since we're expanding in-place. SDL_AudioSpec.format will
1254  * inform the caller about the byte order.
1255  */
1256  i = sample_count;
1257  switch (file->format.encoding) {
1258 #ifdef SDL_WAVE_LAW_LUT
1259  case ALAW_CODE:
1260  while (i--) {
1261  dst[i] = alaw_lut[src[i]];
1262  }
1263  break;
1264  case MULAW_CODE:
1265  while (i--) {
1266  dst[i] = mulaw_lut[src[i]];
1267  }
1268  break;
1269 #else
1270  case ALAW_CODE:
1271  while (i--) {
1272  Uint8 nibble = src[i];
1273  Uint8 exponent = (nibble & 0x7f) ^ 0x55;
1274  Sint16 mantissa = exponent & 0xf;
1275 
1276  exponent >>= 4;
1277  if (exponent > 0) {
1278  mantissa |= 0x10;
1279  }
1280  mantissa = (mantissa << 4) | 0x8;
1281  if (exponent > 1) {
1282  mantissa <<= exponent - 1;
1283  }
1284 
1285  dst[i] = nibble & 0x80 ? mantissa : -mantissa;
1286  }
1287  break;
1288  case MULAW_CODE:
1289  while (i--) {
1290  Uint8 nibble = ~src[i];
1291  Sint16 mantissa = nibble & 0xf;
1292  Uint8 exponent = (nibble >> 4) & 0x7;
1293  Sint16 step = 4 << (exponent + 1);
1294 
1295  mantissa = (0x80 << exponent) + step * mantissa + step / 2 - 132;
1296 
1297  dst[i] = nibble & 0x80 ? -mantissa : mantissa;
1298  }
1299  break;
1300 #endif
1301  default:
1302  SDL_free(src);
1303  return SDL_SetError("Unknown companded encoding");
1304  }
1305 
1306  *audio_buf = src;
1307  *audio_len = (Uint32)expanded_len;
1308 
1309  return 0;
1310 }

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.

1142 {
1143  WaveFormat *format = &file->format;
1144 
1145  /* Standards Update requires this to be 8. */
1146  if (format->bitspersample != 8) {
1147  return SDL_SetError("Invalid companded bits per sample of %u", (unsigned int)format->bitspersample);
1148  }
1149 
1150  /* Not going to bother with weird padding. */
1151  if (format->blockalign != format->channels) {
1152  return SDL_SetError("Unsupported block alignment");
1153  }
1154 
1155  if ((file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict)) {
1156  if (format->blockalign > 1 && datalength % format->blockalign) {
1157  return SDL_SetError("Truncated data chunk in WAVE file");
1158  }
1159  }
1160 
1161  file->sampleframes = WaveAdjustToFactValue(file, datalength / format->blockalign);
1162  if (file->sampleframes < 0) {
1163  return -1;
1164  }
1165 
1166  return 0;
1167 }

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.

337 {
338  WaveFormat *format = &file->format;
339  const size_t blockheadersize = (size_t)file->format.channels * 7;
340  const size_t availableblocks = datalength / file->format.blockalign;
341  const size_t blockframebitsize = (size_t)file->format.bitspersample * file->format.channels;
342  const size_t trailingdata = datalength % file->format.blockalign;
343 
344  if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
345  /* The size of the data chunk must be a multiple of the block size. */
346  if (datalength < blockheadersize || trailingdata > 0) {
347  return SDL_SetError("Truncated MS ADPCM block");
348  }
349  }
350 
351  /* Calculate number of sample frames that will be decoded. */
352  file->sampleframes = (Sint64)availableblocks * format->samplesperblock;
353  if (trailingdata > 0) {
354  /* The last block is truncated. Check if we can get any samples out of it. */
355  if (file->trunchint == TruncDropFrame) {
356  /* Drop incomplete sample frame. */
357  if (trailingdata >= blockheadersize) {
358  size_t trailingsamples = 2 + (trailingdata - blockheadersize) * 8 / blockframebitsize;
359  if (trailingsamples > format->samplesperblock) {
360  trailingsamples = format->samplesperblock;
361  }
362  file->sampleframes += trailingsamples;
363  }
364  }
365  }
366 
367  file->sampleframes = WaveAdjustToFactValue(file, file->sampleframes);
368  if (file->sampleframes < 0) {
369  return -1;
370  }
371 
372  return 0;
373 }

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.

642 {
643  int result;
644  size_t bytesleft, outputsize;
645  WaveChunk *chunk = &file->chunk;
647  MS_ADPCM_ChannelState cstate[2];
648 
649  SDL_zero(state);
650  SDL_zero(cstate);
651 
652  if (chunk->size != chunk->length) {
653  /* Could not read everything. Recalculate number of sample frames. */
654  if (MS_ADPCM_CalculateSampleFrames(file, chunk->size) < 0) {
655  return -1;
656  }
657  }
658 
659  /* Nothing to decode, nothing to return. */
660  if (file->sampleframes == 0) {
661  *audio_buf = NULL;
662  *audio_len = 0;
663  return 0;
664  }
665 
666  state.blocksize = file->format.blockalign;
667  state.channels = file->format.channels;
668  state.blockheadersize = (size_t)state.channels * 7;
669  state.samplesperblock = file->format.samplesperblock;
670  state.framesize = state.channels * sizeof(Sint16);
671  state.ddata = file->decoderdata;
672  state.framestotal = file->sampleframes;
673  state.framesleft = state.framestotal;
674 
675  state.input.data = chunk->data;
676  state.input.size = chunk->size;
677  state.input.pos = 0;
678 
679  /* The output size in bytes. May get modified if data is truncated. */
680  outputsize = (size_t)state.framestotal;
681  if (SafeMult(&outputsize, state.framesize)) {
682  return SDL_OutOfMemory();
683  } else if (outputsize > SDL_MAX_UINT32 || state.framestotal > SIZE_MAX) {
684  return SDL_SetError("WAVE file too big");
685  }
686 
687  state.output.pos = 0;
688  state.output.size = outputsize / sizeof(Sint16);
689  state.output.data = (Sint16 *)SDL_malloc(outputsize);
690  if (state.output.data == NULL) {
691  return SDL_OutOfMemory();
692  }
693 
694  state.cstate = &cstate;
695 
696  /* Decode block by block. A truncated block will stop the decoding. */
697  bytesleft = state.input.size - state.input.pos;
698  while (state.framesleft > 0 && bytesleft >= state.blockheadersize) {
699  state.block.data = state.input.data + state.input.pos;
700  state.block.size = bytesleft < state.blocksize ? bytesleft : state.blocksize;
701  state.block.pos = 0;
702 
703  if (state.output.size - state.output.pos < (Uint64)state.framesleft * state.channels) {
704  /* Somehow didn't allocate enough space for the output. */
705  SDL_free(state.output.data);
706  return SDL_SetError("Unexpected overflow in MS ADPCM decoder");
707  }
708 
709  /* Initialize decoder with the values from the block header. */
711  if (result == -1) {
712  SDL_free(state.output.data);
713  return -1;
714  }
715 
716  /* Decode the block data. It stores the samples directly in the output. */
718  if (result == -1) {
719  /* Unexpected end. Stop decoding and return partial data if necessary. */
720  if (file->trunchint == TruncVeryStrict || file->trunchint == TruncVeryStrict) {
721  SDL_free(state.output.data);
722  return SDL_SetError("Truncated data chunk");
723  } else if (file->trunchint != TruncDropFrame) {
724  state.output.pos -= state.output.pos % (state.samplesperblock * state.channels);
725  }
726  outputsize = state.output.pos * sizeof(Sint16); /* Can't overflow, is always smaller. */
727  break;
728  }
729 
730  state.input.pos += state.block.size;
731  bytesleft = state.input.size - state.input.pos;
732  }
733 
734  *audio_buf = (Uint8 *)state.output.data;
735  *audio_len = (Uint32)outputsize;
736 
737  return 0;
738 }

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.

594 {
595  Uint16 nybble = 0;
596  Sint16 sample1, sample2;
597  const Uint32 channels = state->channels;
598  Uint32 c;
600 
601  size_t blockpos = state->block.pos;
602  size_t blocksize = state->block.size;
603 
604  size_t outpos = state->output.pos;
605 
606  Sint64 blockframesleft = state->samplesperblock - 2;
607  if (blockframesleft > state->framesleft) {
608  blockframesleft = state->framesleft;
609  }
610 
611  while (blockframesleft > 0) {
612  for (c = 0; c < channels; c++) {
613  if (nybble & 0x4000) {
614  nybble <<= 4;
615  } else if (blockpos < blocksize) {
616  nybble = state->block.data[blockpos++] | 0x4000;
617  } else {
618  /* Out of input data. Drop the incomplete frame and return. */
619  state->output.pos = outpos - c;
620  return -1;
621  }
622 
623  /* Load previous samples which may come from the block header. */
624  sample1 = state->output.data[outpos - channels];
625  sample2 = state->output.data[outpos - channels * 2];
626 
627  sample1 = MS_ADPCM_ProcessNibble(cstate + c, sample1, sample2, (nybble >> 4) & 0x0f);
628  state->output.data[outpos++] = sample1;
629  }
630 
631  state->framesleft--;
632  blockframesleft--;
633  }
634 
635  state->output.pos = outpos;
636 
637  return 0;
638 }

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.

533 {
534  Uint8 coeffindex;
535  const Uint32 channels = state->channels;
536  Sint32 sample;
537  Uint32 c;
539  MS_ADPCM_CoeffData *ddata = (MS_ADPCM_CoeffData *)state->ddata;
540 
541  for (c = 0; c < channels; c++) {
542  size_t o = c;
543 
544  /* Load the coefficient pair into the channel state. */
545  coeffindex = state->block.data[o];
546  if (coeffindex > ddata->coeffcount) {
547  return SDL_SetError("Invalid MS ADPCM coefficient index in block header");
548  }
549  cstate[c].coeff1 = ddata->coeff[coeffindex * 2];
550  cstate[c].coeff2 = ddata->coeff[coeffindex * 2 + 1];
551 
552  /* Initial delta value. */
553  o = channels + c * 2;
554  cstate[c].delta = state->block.data[o] | ((Uint16)state->block.data[o + 1] << 8);
555 
556  /* Load the samples from the header. Interestingly, the sample later in
557  * the output stream comes first.
558  */
559  o = channels * 3 + c * 2;
560  sample = state->block.data[o] | ((Sint32)state->block.data[o + 1] << 8);
561  if (sample >= 0x8000) {
562  sample -= 0x10000;
563  }
564  state->output.data[state->output.pos + channels] = (Sint16)sample;
565 
566  o = channels * 5 + c * 2;
567  sample = state->block.data[o] | ((Sint32)state->block.data[o + 1] << 8);
568  if (sample >= 0x8000) {
569  sample -= 0x10000;
570  }
571  state->output.data[state->output.pos] = (Sint16)sample;
572 
573  state->output.pos++;
574  }
575 
576  state->block.pos += state->blockheadersize;
577 
578  /* Skip second sample frame that came from the header. */
579  state->output.pos += state->channels;
580 
581  /* Header provided two sample frames. */
582  state->framesleft -= 2;
583 
584  return 0;
585 }

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.

377 {
378  WaveFormat *format = &file->format;
379  WaveChunk *chunk = &file->chunk;
380  const size_t blockheadersize = (size_t)format->channels * 7;
381  const size_t blockdatasize = (size_t)format->blockalign - blockheadersize;
382  const size_t blockframebitsize = (size_t)format->bitspersample * format->channels;
383  const size_t blockdatasamples = (blockdatasize * 8) / blockframebitsize;
384  const Sint16 presetcoeffs[14] = {256, 0, 512, -256, 0, 0, 192, 64, 240, 0, 460, -208, 392, -232};
385  size_t i, coeffcount;
386  MS_ADPCM_CoeffData *coeffdata;
387 
388  /* Sanity checks. */
389 
390  /* While it's clear how IMA ADPCM handles more than two channels, the nibble
391  * order of MS ADPCM makes it awkward. The Standards Update does not talk
392  * about supporting more than stereo anyway.
393  */
394  if (format->channels > 2) {
395  return SDL_SetError("Invalid number of channels");
396  }
397 
398  if (format->bitspersample != 4) {
399  return SDL_SetError("Invalid MS ADPCM bits per sample of %u", (unsigned int)format->bitspersample);
400  }
401 
402  /* The block size must be big enough to contain the block header. */
403  if (format->blockalign < blockheadersize) {
404  return SDL_SetError("Invalid MS ADPCM block size (nBlockAlign)");
405  }
406 
407  if (format->formattag == EXTENSIBLE_CODE) {
408  /* Does have a GUID (like all format tags), but there's no specification
409  * for how the data is packed into the extensible header. Making
410  * assumptions here could lead to new formats nobody wants to support.
411  */
412  return SDL_SetError("MS ADPCM with the extensible header is not supported");
413  }
414 
415  /* There are wSamplesPerBlock, wNumCoef, and at least 7 coefficient pairs in
416  * the extended part of the header.
417  */
418  if (chunk->size < 22) {
419  return SDL_SetError("Could not read MS ADPCM format header");
420  }
421 
422  format->samplesperblock = chunk->data[18] | ((Uint16)chunk->data[19] << 8);
423  /* Number of coefficient pairs. A pair has two 16-bit integers. */
424  coeffcount = chunk->data[20] | ((size_t)chunk->data[21] << 8);
425  /* bPredictor, the integer offset into the coefficients array, is only
426  * 8 bits. It can only address the first 256 coefficients. Let's limit
427  * the count number here.
428  */
429  if (coeffcount > 256) {
430  coeffcount = 256;
431  }
432 
433  if (chunk->size < 22 + coeffcount * 4) {
434  return SDL_SetError("Could not read custom coefficients in MS ADPCM format header");
435  } else if (format->extsize < 4 + coeffcount * 4) {
436  return SDL_SetError("Invalid MS ADPCM format header (too small)");
437  } else if (coeffcount < 7) {
438  return SDL_SetError("Missing required coefficients in MS ADPCM format header");
439  }
440 
441  coeffdata = (MS_ADPCM_CoeffData *)SDL_malloc(sizeof(MS_ADPCM_CoeffData) + coeffcount * 4);
442  file->decoderdata = coeffdata; /* Freed in cleanup. */
443  if (coeffdata == NULL) {
444  return SDL_OutOfMemory();
445  }
446  coeffdata->coeff = &coeffdata->aligndummy;
447  coeffdata->coeffcount = (Uint16)coeffcount;
448 
449  /* Copy the 16-bit pairs. */
450  for (i = 0; i < coeffcount * 2; i++) {
451  Sint32 c = chunk->data[22 + i * 2] | ((Sint32)chunk->data[23 + i * 2] << 8);
452  if (c >= 0x8000) {
453  c -= 0x10000;
454  }
455  if (i < 14 && c != presetcoeffs[i]) {
456  return SDL_SetError("Wrong preset coefficients in MS ADPCM format header");
457  }
458  coeffdata->coeff[i] = (Sint16)c;
459  }
460 
461  /* Technically, wSamplesPerBlock is required, but we have all the
462  * information in the other fields to calculate it, if it's zero.
463  */
464  if (format->samplesperblock == 0) {
465  /* Let's be nice to the encoders that didn't know how to fill this.
466  * The Standards Update calculates it this way:
467  *
468  * x = Block size (in bits) minus header size (in bits)
469  * y = Bit depth multiplied by channel count
470  * z = Number of samples per channel in block header
471  * wSamplesPerBlock = x / y + z
472  */
473  format->samplesperblock = (Uint32)blockdatasamples + 2;
474  }
475 
476  /* nBlockAlign can be in conflict with wSamplesPerBlock. For example, if
477  * the number of samples doesn't fit into the block. The Standards Update
478  * also describes wSamplesPerBlock with a formula that makes it necessary to
479  * always fill the block with the maximum amount of samples, but this is not
480  * enforced here as there are no compatibility issues.
481  * A truncated block header with just one sample is not supported.
482  */
483  if (format->samplesperblock == 1 || blockdatasamples < format->samplesperblock - 2) {
484  return SDL_SetError("Invalid number of samples per MS ADPCM block (wSamplesPerBlock)");
485  }
486 
487  if (MS_ADPCM_CalculateSampleFrames(file, datalength) < 0) {
488  return -1;
489  }
490 
491  return 0;
492 }

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.

496 {
497  const Sint32 max_audioval = 32767;
498  const Sint32 min_audioval = -32768;
499  const Uint16 max_deltaval = 65535;
500  const Uint16 adaptive[] = {
501  230, 230, 230, 230, 307, 409, 512, 614,
502  768, 614, 512, 409, 307, 230, 230, 230
503  };
504  Sint32 new_sample;
505  Sint32 errordelta;
506  Uint32 delta = cstate->delta;
507 
508  new_sample = (sample1 * cstate->coeff1 + sample2 * cstate->coeff2) / 256;
509  /* The nibble is a signed 4-bit error delta. */
510  errordelta = (Sint32)nybble - (nybble >= 0x08 ? 0x10 : 0);
511  new_sample += (Sint32)delta * errordelta;
512  if (new_sample < min_audioval) {
513  new_sample = min_audioval;
514  } else if (new_sample > max_audioval) {
515  new_sample = max_audioval;
516  }
517  delta = (delta * adaptive[nybble]) / 256;
518  if (delta < 16) {
519  delta = 16;
520  } else if (delta > max_deltaval) {
521  /* This issue is not described in the Standards Update and therefore
522  * undefined. It seems sensible to prevent overflows with a limit.
523  */
524  delta = max_deltaval;
525  }
526 
527  cstate->delta = (Uint16)delta;
528  return (Sint16)new_sample;
529 }

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.

1357 {
1358  WaveFormat *format = &file->format;
1359  WaveChunk *chunk = &file->chunk;
1360  size_t i, expanded_len, sample_count;
1361  Uint8 *ptr;
1362 
1363  sample_count = (size_t)file->sampleframes;
1364  if (SafeMult(&sample_count, format->channels)) {
1365  return SDL_OutOfMemory();
1366  }
1367 
1368  expanded_len = sample_count;
1369  if (SafeMult(&expanded_len, sizeof(Sint32))) {
1370  return SDL_OutOfMemory();
1371  } else if (expanded_len > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
1372  return SDL_SetError("WAVE file too big");
1373  }
1374 
1375  /* 1 to avoid allocating zero bytes, to keep static analysis happy. */
1376  ptr = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1);
1377  if (ptr == NULL) {
1378  return SDL_OutOfMemory();
1379  }
1380 
1381  /* This pointer is now invalid. */
1382  chunk->data = NULL;
1383  chunk->size = 0;
1384 
1385  *audio_buf = ptr;
1386  *audio_len = (Uint32)expanded_len;
1387 
1388  /* work from end to start, since we're expanding in-place. */
1389  for (i = sample_count; i > 0; i--) {
1390  const size_t o = i - 1;
1391  uint8_t b[4];
1392 
1393  b[0] = 0;
1394  b[1] = ptr[o * 3];
1395  b[2] = ptr[o * 3 + 1];
1396  b[3] = ptr[o * 3 + 2];
1397 
1398  ptr[o * 4 + 0] = b[0];
1399  ptr[o * 4 + 1] = b[1];
1400  ptr[o * 4 + 2] = b[2];
1401  ptr[o * 4 + 3] = b[3];
1402  }
1403 
1404  return 0;
1405 }

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.

1409 {
1410  WaveFormat *format = &file->format;
1411  WaveChunk *chunk = &file->chunk;
1412  size_t outputsize;
1413 
1414  if (chunk->length != chunk->size) {
1415  file->sampleframes = WaveAdjustToFactValue(file, chunk->size / format->blockalign);
1416  if (file->sampleframes < 0) {
1417  return -1;
1418  }
1419  }
1420 
1421  /* Nothing to decode, nothing to return. */
1422  if (file->sampleframes == 0) {
1423  *audio_buf = NULL;
1424  *audio_len = 0;
1425  return 0;
1426  }
1427 
1428  /* 24-bit samples get shifted to 32 bits. */
1429  if (format->encoding == PCM_CODE && format->bitspersample == 24) {
1430  return PCM_ConvertSint24ToSint32(file, audio_buf, audio_len);
1431  }
1432 
1433  outputsize = (size_t)file->sampleframes;
1434  if (SafeMult(&outputsize, format->blockalign)) {
1435  return SDL_OutOfMemory();
1436  } else if (outputsize > SDL_MAX_UINT32 || file->sampleframes > SIZE_MAX) {
1437  return SDL_SetError("WAVE file too big");
1438  }
1439 
1440  *audio_buf = chunk->data;
1441  *audio_len = (Uint32)outputsize;
1442 
1443  /* This pointer is going to be returned to the caller. Prevent free in cleanup. */
1444  chunk->data = NULL;
1445  chunk->size = 0;
1446 
1447  return 0;
1448 }

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.

1314 {
1315  WaveFormat *format = &file->format;
1316 
1317  if (format->encoding == PCM_CODE) {
1318  switch (format->bitspersample) {
1319  case 8:
1320  case 16:
1321  case 24:
1322  case 32:
1323  /* These are supported. */
1324  break;
1325  default:
1326  return SDL_SetError("%u-bit PCM format not supported", (unsigned int)format->bitspersample);
1327  }
1328  } else if (format->encoding == IEEE_FLOAT_CODE) {
1329  if (format->bitspersample != 32) {
1330  return SDL_SetError("%u-bit IEEE floating-point format not supported", (unsigned int)format->bitspersample);
1331  }
1332  }
1333 
1334  /* It wouldn't be that hard to support more exotic block sizes, but
1335  * the most common formats should do for now.
1336  */
1337  if (format->blockalign * 8 != format->channels * format->bitspersample) {
1338  return SDL_SetError("Unsupported block alignment");
1339  }
1340 
1341  if ((file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict)) {
1342  if (format->blockalign > 1 && datalength % format->blockalign) {
1343  return SDL_SetError("Truncated data chunk in WAVE file");
1344  }
1345  }
1346 
1347  file->sampleframes = WaveAdjustToFactValue(file, datalength / format->blockalign);
1348  if (file->sampleframes < 0) {
1349  return -1;
1350  }
1351 
1352  return 0;
1353 }

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.

49 {
50  if (*f1 > 0 && SIZE_MAX / *f1 <= f2) {
51  return -1;
52  }
53  *f1 *= f2;
54  return 0;
55 }

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.

2149 {
2150  SDL_free(audio_buf);
2151 }

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
srcThe data source with the WAVE data
freesrcA integer value that makes the function close the data source if non-zero
specA pointer filled with the audio format of the audio data
audio_bufA pointer filled with the audio data allocated by the function
audio_lenA 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.

2096 {
2097  int result;
2098  WaveFile file;
2099 
2100  SDL_zero(file);
2101 
2102  /* Make sure we are passed a valid data source */
2103  if (src == NULL) {
2104  /* Error may come from RWops. */
2105  return NULL;
2106  } else if (spec == NULL) {
2107  SDL_InvalidParamError("spec");
2108  return NULL;
2109  } else if (audio_buf == NULL) {
2110  SDL_InvalidParamError("audio_buf");
2111  return NULL;
2112  } else if (audio_len == NULL) {
2113  SDL_InvalidParamError("audio_len");
2114  return NULL;
2115  }
2116 
2117  *audio_buf = NULL;
2118  *audio_len = 0;
2119 
2120  file.riffhint = WaveGetRiffSizeHint();
2122  file.facthint = WaveGetFactChunkHint();
2123 
2124  result = WaveLoad(src, &file, spec, audio_buf, audio_len);
2125  if (result < 0) {
2126  SDL_free(*audio_buf);
2127  spec = NULL;
2128  audio_buf = NULL;
2129  audio_len = 0;
2130  }
2131 
2132  /* Cleanup */
2133  if (freesrc) {
2134  SDL_RWclose(src);
2135  } else {
2137  }
2138  WaveFreeChunkData(&file.chunk);
2139  SDL_free(file.decoderdata);
2140 
2141  return spec;
2142 }

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.

323 {
324  if (file->fact.status == 2) {
325  if (file->facthint == FactStrict && sampleframes < file->fact.samplelength) {
326  return SDL_SetError("Invalid number of sample frames in WAVE fact chunk (too many)");
327  } else if (sampleframes > file->fact.samplelength) {
328  return file->fact.samplelength;
329  }
330  }
331 
332  return sampleframes;
333 }

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.

1680 {
1681  WaveFormat *format = &file->format;
1682 
1683  /* Check for some obvious issues. */
1684 
1685  if (format->channels == 0) {
1686  return SDL_SetError("Invalid number of channels");
1687  } else if (format->channels > 255) {
1688  /* Limit given by SDL_AudioSpec.channels. */
1689  return SDL_SetError("Number of channels exceeds limit of 255");
1690  }
1691 
1692  if (format->frequency == 0) {
1693  return SDL_SetError("Invalid sample rate");
1694  } else if (format->frequency > INT_MAX) {
1695  /* Limit given by SDL_AudioSpec.freq. */
1696  return SDL_SetError("Sample rate exceeds limit of %d", INT_MAX);
1697  }
1698 
1699  /* Reject invalid fact chunks in strict mode. */
1700  if (file->facthint == FactStrict && file->fact.status == -1) {
1701  return SDL_SetError("Invalid fact chunk in WAVE file");
1702  }
1703 
1704  /* Check for issues common to all encodings. Some unsupported formats set
1705  * the bits per sample to zero. These fall through to the 'unsupported
1706  * format' error.
1707  */
1708  switch (format->encoding) {
1709  case IEEE_FLOAT_CODE:
1710  case ALAW_CODE:
1711  case MULAW_CODE:
1712  case MS_ADPCM_CODE:
1713  case IMA_ADPCM_CODE:
1714  /* These formats require a fact chunk. */
1715  if (file->facthint == FactStrict && file->fact.status <= 0) {
1716  return SDL_SetError("Missing fact chunk in WAVE file");
1717  }
1718  /* fallthrough */
1719  case PCM_CODE:
1720  /* All supported formats require a non-zero bit depth. */
1721  if (file->chunk.size < 16) {
1722  return SDL_SetError("Missing wBitsPerSample field in WAVE fmt chunk");
1723  } else if (format->bitspersample == 0) {
1724  return SDL_SetError("Invalid bits per sample");
1725  }
1726 
1727  /* All supported formats must have a proper block size. */
1728  if (format->blockalign == 0) {
1729  return SDL_SetError("Invalid block alignment");
1730  }
1731 
1732  /* If the fact chunk is valid and the appropriate hint is set, the
1733  * decoders will use the number of sample frames from the fact chunk.
1734  */
1735  if (file->fact.status == 1) {
1736  WaveFactChunkHint hint = file->facthint;
1737  Uint32 samples = file->fact.samplelength;
1738  if (hint == FactTruncate || hint == FactStrict || (hint == FactIgnoreZero && samples > 0)) {
1739  file->fact.status = 2;
1740  }
1741  }
1742  }
1743 
1744  /* Check the format for encoding specific issues and initialize decoders. */
1745  switch (format->encoding) {
1746  case PCM_CODE:
1747  case IEEE_FLOAT_CODE:
1748  if (PCM_Init(file, datalength) < 0) {
1749  return -1;
1750  }
1751  break;
1752  case ALAW_CODE:
1753  case MULAW_CODE:
1754  if (LAW_Init(file, datalength) < 0) {
1755  return -1;
1756  }
1757  break;
1758  case MS_ADPCM_CODE:
1759  if (MS_ADPCM_Init(file, datalength) < 0) {
1760  return -1;
1761  }
1762  break;
1763  case IMA_ADPCM_CODE:
1764  if (IMA_ADPCM_Init(file, datalength) < 0) {
1765  return -1;
1766  }
1767  break;
1768  case MPEG_CODE:
1769  case MPEGLAYER3_CODE:
1770  return SDL_SetError("MPEG formats not supported");
1771  default:
1772  if (format->formattag == EXTENSIBLE_CODE) {
1773  const char *errstr = "Unknown WAVE format GUID: %08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x";
1774  const Uint8 *g = format->subformat;
1775  const Uint32 g1 = g[0] | ((Uint32)g[1] << 8) | ((Uint32)g[2] << 16) | ((Uint32)g[3] << 24);
1776  const Uint32 g2 = g[4] | ((Uint32)g[5] << 8);
1777  const Uint32 g3 = g[6] | ((Uint32)g[7] << 8);
1778  return SDL_SetError(errstr, g1, g2, g3, g[8], g[9], g[10], g[11], g[12], g[13], g[14], g[15]);
1779  }
1780  return SDL_SetError("Unknown WAVE format tag: 0x%04x", (unsigned int)format->encoding);
1781  }
1782 
1783  return 0;
1784 }

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.

1512 {
1513  if (chunk->data != NULL) {
1514  SDL_free(chunk->data);
1515  chunk->data = NULL;
1516  }
1517  chunk->size = 0;
1518 }

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.

1492 {
1493  const char *hint = SDL_GetHint(SDL_HINT_WAVE_FACT_CHUNK);
1494 
1495  if (hint != NULL) {
1496  if (SDL_strcmp(hint, "truncate") == 0) {
1497  return FactTruncate;
1498  } else if (SDL_strcmp(hint, "strict") == 0) {
1499  return FactStrict;
1500  } else if (SDL_strcmp(hint, "ignorezero") == 0) {
1501  return FactIgnoreZero;
1502  } else if (SDL_strcmp(hint, "ignore") == 0) {
1503  return FactIgnore;
1504  }
1505  }
1506 
1507  return FactNoHint;
1508 }

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.

1606 {
1607  size_t i;
1608  for (i = 0; i < SDL_arraysize(extensible_guids); i++) {
1609  if (SDL_memcmp(format->subformat, extensible_guids[i].guid, 16) == 0) {
1610  return extensible_guids[i].encoding;
1611  }
1612  }
1613  return UNKNOWN_CODE;
1614 }

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.

1452 {
1453  const char *hint = SDL_GetHint(SDL_HINT_WAVE_RIFF_CHUNK_SIZE);
1454 
1455  if (hint != NULL) {
1456  if (SDL_strcmp(hint, "force") == 0) {
1457  return RiffSizeForce;
1458  } else if (SDL_strcmp(hint, "ignore") == 0) {
1459  return RiffSizeIgnore;
1460  } else if (SDL_strcmp(hint, "ignorezero") == 0) {
1461  return RiffSizeIgnoreZero;
1462  } else if (SDL_strcmp(hint, "maximum") == 0) {
1463  return RiffSizeMaximum;
1464  }
1465  }
1466 
1467  return RiffSizeNoHint;
1468 }

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.

1472 {
1473  const char *hint = SDL_GetHint(SDL_HINT_WAVE_TRUNCATION);
1474 
1475  if (hint != NULL) {
1476  if (SDL_strcmp(hint, "verystrict") == 0) {
1477  return TruncVeryStrict;
1478  } else if (SDL_strcmp(hint, "strict") == 0) {
1479  return TruncStrict;
1480  } else if (SDL_strcmp(hint, "dropframe") == 0) {
1481  return TruncDropFrame;
1482  } else if (SDL_strcmp(hint, "dropblock") == 0) {
1483  return TruncDropBlock;
1484  }
1485  }
1486 
1487  return TruncNoHint;
1488 }

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.

1788 {
1789  int result;
1790  Uint32 chunkcount = 0;
1791  Uint32 chunkcountlimit = 10000;
1792  char *envchunkcountlimit;
1793  Sint64 RIFFstart, RIFFend, lastchunkpos;
1794  SDL_bool RIFFlengthknown = SDL_FALSE;
1795  WaveFormat *format = &file->format;
1796  WaveChunk *chunk = &file->chunk;
1797  WaveChunk RIFFchunk;
1798  WaveChunk fmtchunk;
1799  WaveChunk datachunk;
1800 
1801  SDL_zero(RIFFchunk);
1802  SDL_zero(fmtchunk);
1803  SDL_zero(datachunk);
1804 
1805  envchunkcountlimit = SDL_getenv("SDL_WAVE_CHUNK_LIMIT");
1806  if (envchunkcountlimit != NULL) {
1807  unsigned int count;
1808  if (SDL_sscanf(envchunkcountlimit, "%u", &count) == 1) {
1809  chunkcountlimit = count <= SDL_MAX_UINT32 ? count : SDL_MAX_UINT32;
1810  }
1811  }
1812 
1813  RIFFstart = SDL_RWtell(src);
1814  if (RIFFstart < 0) {
1815  return SDL_SetError("Could not seek in file");
1816  }
1817 
1818  RIFFchunk.position = RIFFstart;
1819  if (WaveNextChunk(src, &RIFFchunk) < 0) {
1820  return SDL_SetError("Could not read RIFF header");
1821  }
1822 
1823  /* Check main WAVE file identifiers. */
1824  if (RIFFchunk.fourcc == RIFF) {
1825  Uint32 formtype;
1826  /* Read the form type. "WAVE" expected. */
1827  if (SDL_RWread(src, &formtype, sizeof(Uint32), 1) != 1) {
1828  return SDL_SetError("Could not read RIFF form type");
1829  } else if (SDL_SwapLE32(formtype) != WAVE) {
1830  return SDL_SetError("RIFF form type is not WAVE (not a Waveform file)");
1831  }
1832  } else if (RIFFchunk.fourcc == WAVE) {
1833  /* RIFF chunk missing or skipped. Length unknown. */
1834  RIFFchunk.position = 0;
1835  RIFFchunk.length = 0;
1836  } else {
1837  return SDL_SetError("Could not find RIFF or WAVE identifiers (not a Waveform file)");
1838  }
1839 
1840  /* The 4-byte form type is immediately followed by the first chunk.*/
1841  chunk->position = RIFFchunk.position + 4;
1842 
1843  /* Use the RIFF chunk size to limit the search for the chunks. This is not
1844  * always reliable and the hint can be used to tune the behavior. By
1845  * default, it will never search past 4 GiB.
1846  */
1847  switch (file->riffhint) {
1848  case RiffSizeIgnore:
1849  RIFFend = RIFFchunk.position + SDL_MAX_UINT32;
1850  break;
1851  default:
1852  case RiffSizeIgnoreZero:
1853  if (RIFFchunk.length == 0) {
1854  RIFFend = RIFFchunk.position + SDL_MAX_UINT32;
1855  break;
1856  }
1857  /* fallthrough */
1858  case RiffSizeForce:
1859  RIFFend = RIFFchunk.position + RIFFchunk.length;
1860  RIFFlengthknown = SDL_TRUE;
1861  break;
1862  case RiffSizeMaximum:
1863  RIFFend = SDL_MAX_SINT64;
1864  break;
1865  }
1866 
1867  /* Step through all chunks and save information on the fmt, data, and fact
1868  * chunks. Ignore the chunks we don't know as per specification. This
1869  * currently also ignores cue, list, and slnt chunks.
1870  */
1871  while ((Uint64)RIFFend > (Uint64)chunk->position + chunk->length + (chunk->length & 1)) {
1872  /* Abort after too many chunks or else corrupt files may waste time. */
1873  if (chunkcount++ >= chunkcountlimit) {
1874  return SDL_SetError("Chunk count in WAVE file exceeds limit of %u", chunkcountlimit);
1875  }
1876 
1877  result = WaveNextChunk(src, chunk);
1878  if (result == -1) {
1879  /* Unexpected EOF. Corrupt file or I/O issues. */
1880  if (file->trunchint == TruncVeryStrict) {
1881  return SDL_SetError("Unexpected end of WAVE file");
1882  }
1883  /* Let the checks after this loop sort this issue out. */
1884  break;
1885  } else if (result == -2) {
1886  return SDL_SetError("Could not seek to WAVE chunk header");
1887  }
1888 
1889  if (chunk->fourcc == FMT) {
1890  if (fmtchunk.fourcc == FMT) {
1891  /* Multiple fmt chunks. Ignore or error? */
1892  } else {
1893  /* The fmt chunk must occur before the data chunk. */
1894  if (datachunk.fourcc == DATA) {
1895  return SDL_SetError("fmt chunk after data chunk in WAVE file");
1896  }
1897  fmtchunk = *chunk;
1898  }
1899  } else if (chunk->fourcc == DATA) {
1900  /* Only use the first data chunk. Handling the wavl list madness
1901  * may require a different approach.
1902  */
1903  if (datachunk.fourcc != DATA) {
1904  datachunk = *chunk;
1905  }
1906  } else if (chunk->fourcc == FACT) {
1907  /* The fact chunk data must be at least 4 bytes for the
1908  * dwSampleLength field. Ignore all fact chunks after the first one.
1909  */
1910  if (file->fact.status == 0) {
1911  if (chunk->length < 4) {
1912  file->fact.status = -1;
1913  } else {
1914  /* Let's use src directly, it's just too convenient. */
1915  Sint64 position = SDL_RWseek(src, chunk->position, RW_SEEK_SET);
1916  Uint32 samplelength;
1917  if (position == chunk->position && SDL_RWread(src, &samplelength, sizeof(Uint32), 1) == 1) {
1918  file->fact.status = 1;
1919  file->fact.samplelength = SDL_SwapLE32(samplelength);
1920  } else {
1921  file->fact.status = -1;
1922  }
1923  }
1924  }
1925  }
1926 
1927  /* Go through all chunks in verystrict mode or stop the search early if
1928  * all required chunks were found.
1929  */
1930  if (file->trunchint == TruncVeryStrict) {
1931  if ((Uint64)RIFFend < (Uint64)chunk->position + chunk->length) {
1932  return SDL_SetError("RIFF size truncates chunk");
1933  }
1934  } else if (fmtchunk.fourcc == FMT && datachunk.fourcc == DATA) {
1935  if (file->fact.status == 1 || file->facthint == FactIgnore || file->facthint == FactNoHint) {
1936  break;
1937  }
1938  }
1939  }
1940 
1941  /* Save the position after the last chunk. This position will be used if the
1942  * RIFF length is unknown.
1943  */
1944  lastchunkpos = chunk->position + chunk->length;
1945 
1946  /* The fmt chunk is mandatory. */
1947  if (fmtchunk.fourcc != FMT) {
1948  return SDL_SetError("Missing fmt chunk in WAVE file");
1949  }
1950  /* A data chunk must be present. */
1951  if (datachunk.fourcc != DATA) {
1952  return SDL_SetError("Missing data chunk in WAVE file");
1953  }
1954  /* Check if the last chunk has all of its data in verystrict mode. */
1955  if (file->trunchint == TruncVeryStrict) {
1956  /* data chunk is handled later. */
1957  if (chunk->fourcc != DATA && chunk->length > 0) {
1958  Uint8 tmp;
1959  Uint64 position = (Uint64)chunk->position + chunk->length - 1;
1960  if (position > SDL_MAX_SINT64 || SDL_RWseek(src, (Sint64)position, RW_SEEK_SET) != (Sint64)position) {
1961  return SDL_SetError("Could not seek to WAVE chunk data");
1962  } else if (SDL_RWread(src, &tmp, 1, 1) != 1) {
1963  return SDL_SetError("RIFF size truncates chunk");
1964  }
1965  }
1966  }
1967 
1968  /* Process fmt chunk. */
1969  *chunk = fmtchunk;
1970 
1971  /* No need to read more than 1046 bytes of the fmt chunk data with the
1972  * formats that are currently supported. (1046 because of MS ADPCM coefficients)
1973  */
1974  if (WaveReadPartialChunkData(src, chunk, 1046) < 0) {
1975  return SDL_SetError("Could not read data of WAVE fmt chunk");
1976  }
1977 
1978  /* The fmt chunk data must be at least 14 bytes to include all common fields.
1979  * It usually is 16 and larger depending on the header and encoding.
1980  */
1981  if (chunk->length < 14) {
1982  return SDL_SetError("Invalid WAVE fmt chunk length (too small)");
1983  } else if (chunk->size < 14) {
1984  return SDL_SetError("Could not read data of WAVE fmt chunk");
1985  } else if (WaveReadFormat(file) < 0) {
1986  return -1;
1987  } else if (WaveCheckFormat(file, (size_t)datachunk.length) < 0) {
1988  return -1;
1989  }
1990 
1991 #ifdef SDL_WAVE_DEBUG_LOG_FORMAT
1992  WaveDebugLogFormat(file);
1993 #endif
1994 #ifdef SDL_WAVE_DEBUG_DUMP_FORMAT
1995  WaveDebugDumpFormat(file, RIFFchunk.length, fmtchunk.length, datachunk.length);
1996 #endif
1997 
1998  WaveFreeChunkData(chunk);
1999 
2000  /* Process data chunk. */
2001  *chunk = datachunk;
2002 
2003  if (chunk->length > 0) {
2004  result = WaveReadChunkData(src, chunk);
2005  if (result == -1) {
2006  return -1;
2007  } else if (result == -2) {
2008  return SDL_SetError("Could not seek data of WAVE data chunk");
2009  }
2010  }
2011 
2012  if (chunk->length != chunk->size) {
2013  /* I/O issues or corrupt file. */
2014  if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) {
2015  return SDL_SetError("Could not read data of WAVE data chunk");
2016  }
2017  /* The decoders handle this truncation. */
2018  }
2019 
2020  /* Decode or convert the data if necessary. */
2021  switch (format->encoding) {
2022  case PCM_CODE:
2023  case IEEE_FLOAT_CODE:
2024  if (PCM_Decode(file, audio_buf, audio_len) < 0) {
2025  return -1;
2026  }
2027  break;
2028  case ALAW_CODE:
2029  case MULAW_CODE:
2030  if (LAW_Decode(file, audio_buf, audio_len) < 0) {
2031  return -1;
2032  }
2033  break;
2034  case MS_ADPCM_CODE:
2035  if (MS_ADPCM_Decode(file, audio_buf, audio_len) < 0) {
2036  return -1;
2037  }
2038  break;
2039  case IMA_ADPCM_CODE:
2040  if (IMA_ADPCM_Decode(file, audio_buf, audio_len) < 0) {
2041  return -1;
2042  }
2043  break;
2044  }
2045 
2046  /* Setting up the SDL_AudioSpec. All unsupported formats were filtered out
2047  * by checks earlier in this function.
2048  */
2049  SDL_zerop(spec);
2050  spec->freq = format->frequency;
2051  spec->channels = (Uint8)format->channels;
2052  spec->samples = 4096; /* Good default buffer size */
2053 
2054  switch (format->encoding) {
2055  case MS_ADPCM_CODE:
2056  case IMA_ADPCM_CODE:
2057  case ALAW_CODE:
2058  case MULAW_CODE:
2059  /* These can be easily stored in the byte order of the system. */
2061  break;
2062  case IEEE_FLOAT_CODE:
2064  break;
2065  case PCM_CODE:
2066  switch (format->bitspersample) {
2067  case 8:
2068  spec->format = AUDIO_U8;
2069  break;
2070  case 16:
2072  break;
2073  case 24: /* Has been shifted to 32 bits. */
2074  case 32:
2076  break;
2077  default:
2078  /* Just in case something unexpected happened in the checks. */
2079  return SDL_SetError("Unexpected %u-bit PCM data format", (unsigned int)format->bitspersample);
2080  }
2081  break;
2082  }
2083 
2084  /* Report the end position back to the cleanup code. */
2085  if (RIFFlengthknown) {
2086  chunk->position = RIFFend;
2087  } else {
2088  chunk->position = lastchunkpos;
2089  }
2090 
2091  return 0;
2092 }

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.

1522 {
1523  Uint32 chunkheader[2];
1524  Sint64 nextposition = chunk->position + chunk->length;
1525 
1526  /* Data is no longer valid after this function returns. */
1527  WaveFreeChunkData(chunk);
1528 
1529  /* Error on overflows. */
1530  if (SDL_MAX_SINT64 - chunk->length < chunk->position || SDL_MAX_SINT64 - 8 < nextposition) {
1531  return -1;
1532  }
1533 
1534  /* RIFF chunks have a 2-byte alignment. Skip padding byte. */
1535  if (chunk->length & 1) {
1536  nextposition++;
1537  }
1538 
1539  if (SDL_RWseek(src, nextposition, RW_SEEK_SET) != nextposition) {
1540  /* Not sure how we ended up here. Just abort. */
1541  return -2;
1542  } else if (SDL_RWread(src, chunkheader, 4, 2) != 2) {
1543  return -1;
1544  }
1545 
1546  chunk->fourcc = SDL_SwapLE32(chunkheader[0]);
1547  chunk->length = SDL_SwapLE32(chunkheader[1]);
1548  chunk->position = nextposition + 8;
1549 
1550  return 0;
1551 }

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.

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

References WaveChunk::length, and WaveReadPartialChunkData().

Referenced by WaveLoad().

◆ WaveReadFormat()

static int WaveReadFormat ( WaveFile file)
static

Definition at line 1617 of file SDL_wave.c.

1618 {
1619  WaveChunk *chunk = &file->chunk;
1620  WaveFormat *format = &file->format;
1621  SDL_RWops *fmtsrc;
1622  size_t fmtlen = chunk->size;
1623 
1624  if (fmtlen > SDL_MAX_SINT32) {
1625  /* Limit given by SDL_RWFromConstMem. */
1626  return SDL_SetError("Data of WAVE fmt chunk too big");
1627  }
1628  fmtsrc = SDL_RWFromConstMem(chunk->data, (int)chunk->size);
1629  if (fmtsrc == NULL) {
1630  return SDL_OutOfMemory();
1631  }
1632 
1633  format->formattag = SDL_ReadLE16(fmtsrc);
1634  format->encoding = format->formattag;
1635  format->channels = SDL_ReadLE16(fmtsrc);
1636  format->frequency = SDL_ReadLE32(fmtsrc);
1637  format->byterate = SDL_ReadLE32(fmtsrc);
1638  format->blockalign = SDL_ReadLE16(fmtsrc);
1639 
1640  /* This is PCM specific in the first version of the specification. */
1641  if (fmtlen >= 16) {
1642  format->bitspersample = SDL_ReadLE16(fmtsrc);
1643  } else if (format->encoding == PCM_CODE) {
1644  SDL_RWclose(fmtsrc);
1645  return SDL_SetError("Missing wBitsPerSample field in WAVE fmt chunk");
1646  }
1647 
1648  /* The earlier versions also don't have this field. */
1649  if (fmtlen >= 18) {
1650  format->extsize = SDL_ReadLE16(fmtsrc);
1651  }
1652 
1653  if (format->formattag == EXTENSIBLE_CODE) {
1654  /* note that this ignores channel masks, smaller valid bit counts
1655  * inside a larger container, and most subtypes. This is just enough
1656  * to get things that didn't really _need_ WAVE_FORMAT_EXTENSIBLE
1657  * to be useful working when they use this format flag.
1658  */
1659 
1660  /* Extensible header must be at least 22 bytes. */
1661  if (fmtlen < 40 || format->extsize < 22) {
1662  SDL_RWclose(fmtsrc);
1663  return SDL_SetError("Extensible WAVE header too small");
1664  }
1665 
1666  format->validsamplebits = SDL_ReadLE16(fmtsrc);
1667  format->samplesperblock = format->validsamplebits;
1668  format->channelmask = SDL_ReadLE32(fmtsrc);
1669  SDL_RWread(fmtsrc, format->subformat, 1, 16);
1671  }
1672 
1673  SDL_RWclose(fmtsrc);
1674 
1675  return 0;
1676 }

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.

1555 {
1556  WaveFreeChunkData(chunk);
1557 
1558  if (length > chunk->length) {
1559  length = chunk->length;
1560  }
1561 
1562  if (length > 0) {
1563  chunk->data = SDL_malloc(length);
1564  if (chunk->data == NULL) {
1565  return SDL_OutOfMemory();
1566  }
1567 
1568  if (SDL_RWseek(src, chunk->position, RW_SEEK_SET) != chunk->position) {
1569  /* Not sure how we ended up here. Just abort. */
1570  return -2;
1571  }
1572 
1573  chunk->size = SDL_RWread(src, chunk->data, 1, length);
1574  if (chunk->size != length) {
1575  /* Expected to be handled by the caller. */
1576  }
1577  }
1578 
1579  return 0;
1580 }

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

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