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 "SDL_audio_c.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 1595 of file SDL_wave.c.

Function Documentation

◆ IMA_ADPCM_CalculateSampleFrames()

static int IMA_ADPCM_CalculateSampleFrames ( WaveFile file,
size_t  datalength 
)
static

Definition at line 742 of file SDL_wave.c.

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

References WaveFormat::channels, WaveFile::format, if, 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 1038 of file SDL_wave.c.

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

References WaveFormat::blockalign, WaveFormat::channels, WaveFile::chunk, WaveChunk::data, WaveFile::format, if, 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, TruncStrict, and TruncVeryStrict.

Referenced by WaveLoad().

◆ IMA_ADPCM_DecodeBlockData()

static int IMA_ADPCM_DecodeBlockData ( ADPCM_DecoderState state)
static

Definition at line 968 of file SDL_wave.c.

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

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 928 of file SDL_wave.c.

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

References state.

Referenced by IMA_ADPCM_Decode().

◆ IMA_ADPCM_Init()

static int IMA_ADPCM_Init ( WaveFile file,
size_t  datalength 
)
static

Definition at line 796 of file SDL_wave.c.

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

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 862 of file SDL_wave.c.

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

Referenced by IMA_ADPCM_DecodeBlockData().

◆ LAW_Decode()

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

Definition at line 1171 of file SDL_wave.c.

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

References ALAW_CODE, WaveFile::chunk, WaveChunk::data, WaveFormat::encoding, WaveFile::format, i, if, 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 1142 of file SDL_wave.c.

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

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 337 of file SDL_wave.c.

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

References WaveFormat::bitspersample, WaveFormat::blockalign, WaveFormat::channels, WaveFile::format, if, 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 642 of file SDL_wave.c.

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

References WaveFormat::blockalign, WaveFormat::channels, WaveFile::chunk, WaveChunk::data, WaveFile::decoderdata, WaveFile::format, if, 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, SDL_zeroa, WaveChunk::size, SIZE_MAX, state, TruncDropFrame, WaveFile::trunchint, TruncStrict, and TruncVeryStrict.

Referenced by WaveLoad().

◆ MS_ADPCM_DecodeBlockData()

static int MS_ADPCM_DecodeBlockData ( ADPCM_DecoderState state)
static

Definition at line 594 of file SDL_wave.c.

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

References if, 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 533 of file SDL_wave.c.

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

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 377 of file SDL_wave.c.

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

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 496 of file SDL_wave.c.

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

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 1357 of file SDL_wave.c.

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

References WaveFile::chunk, WaveChunk::data, WaveFile::format, i, if, NULL, ptr, 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 1409 of file SDL_wave.c.

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

References WaveFile::chunk, WaveChunk::data, WaveFile::format, if, 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 1314 of file SDL_wave.c.

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

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 49 of file SDL_wave.c.

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

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 2151 of file SDL_wave.c.

2152 {
2153  SDL_free(audio_buf);
2154 }

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 2098 of file SDL_wave.c.

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

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 323 of file SDL_wave.c.

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

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 1680 of file SDL_wave.c.

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

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 1512 of file SDL_wave.c.

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

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 1492 of file SDL_wave.c.

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

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 1606 of file SDL_wave.c.

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

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 1452 of file SDL_wave.c.

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

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 1472 of file SDL_wave.c.

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

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 1788 of file SDL_wave.c.

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

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, if, 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_SilenceValueForFormat(), SDL_sscanf, SDL_SwapLE32, SDL_TRUE, SDL_zero, SDL_zerop, SDL_AudioSpec::silence, 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 1522 of file SDL_wave.c.

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

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 1584 of file SDL_wave.c.

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

References WaveChunk::length, and WaveReadPartialChunkData().

Referenced by WaveLoad().

◆ WaveReadFormat()

static int WaveReadFormat ( WaveFile file)
static

Definition at line 1618 of file SDL_wave.c.

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

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 1555 of file SDL_wave.c.

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

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:418
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
WaveGetFactChunkHint
static WaveFactChunkHint WaveGetFactChunkHint()
Definition: SDL_wave.c:1492
c
const GLubyte * c
Definition: SDL_opengl_glext.h:11096
MS_ADPCM_CoeffData::coeff
Sint16 * coeff
Definition: SDL_wave.c:95
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:1452
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
if
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
Definition: pixman-arm-neon-asm.h:469
PCM_Decode
static int PCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:1409
MS_ADPCM_ChannelState::delta
Uint16 delta
Definition: SDL_wave.c:101
NULL
#define NULL
Definition: begin_code.h:167
b
GLboolean GLboolean GLboolean b
Definition: SDL_opengl_glext.h:1112
MS_ADPCM_CoeffData::aligndummy
Sint16 aligndummy
Definition: SDL_wave.c:96
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:1112
exponent
GLint * exponent
Definition: SDL_opengl_glext.h:4714
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:419
samples
GLsizei samples
Definition: SDL_opengl_glext.h:1188
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:642
SafeMult
static int SafeMult(size_t *f1, size_t f2)
Definition: SDL_wave.c:49
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:102
IMA_ADPCM_CalculateSampleFrames
static int IMA_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:742
IMA_ADPCM_DecodeBlockHeader
static int IMA_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state)
Definition: SDL_wave.c:928
RiffSizeForce
@ RiffSizeForce
Definition: SDL_wave.h:106
RIFF
#define RIFF
Definition: SDL_wave.h:29
MS_ADPCM_ChannelState
Definition: SDL_wave.c:99
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:663
SDL_GetHint
#define SDL_GetHint
Definition: SDL_dynapi_overrides.h:191
WaveFile
Definition: SDL_wave.h:130
SDL_SilenceValueForFormat
Uint8 SDL_SilenceValueForFormat(const SDL_AudioFormat format)
Definition: SDL_audio.c:1668
SDL_ReadLE32
#define SDL_ReadLE32
Definition: SDL_dynapi_overrides.h:359
SDL_zeroa
#define SDL_zeroa(x)
Definition: SDL_stdinc.h:420
RiffSizeNoHint
@ RiffSizeNoHint
Definition: SDL_wave.h:105
MS_ADPCM_DecodeBlockHeader
static int MS_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state)
Definition: SDL_wave.c:533
length
GLuint GLsizei GLsizei * length
Definition: SDL_opengl_glext.h:672
WaveLoad
static int WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:1788
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9435
WaveReadPartialChunkData
static int WaveReadPartialChunkData(SDL_RWops *src, WaveChunk *chunk, size_t length)
Definition: SDL_wave.c:1555
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:968
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:1740
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:1618
WaveFact::samplelength
Uint32 samplelength
Definition: SDL_wave.h:90
WaveReadChunkData
static int WaveReadChunkData(SDL_RWops *src, WaveChunk *chunk)
Definition: SDL_wave.c:1584
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:1522
WaveGetTruncationHint
static WaveTruncationHint WaveGetTruncationHint()
Definition: SDL_wave.c:1472
IMA_ADPCM_Decode
static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:1038
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:1591
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:1993
size_t
unsigned int size_t
Definition: SDL_config_windows.h:68
WaveFile::sampleframes
Sint64 sampleframes
Definition: SDL_wave.h:140
WaveGetFormatGUIDEncoding
static Uint16 WaveGetFormatGUIDEncoding(WaveFormat *format)
Definition: SDL_wave.c:1606
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:58
SDL_AudioSpec::freq
int freq
Definition: SDL_audio.h:180
WaveFormat::samplesperblock
Uint32 samplesperblock
Definition: SDL_wave.h:67
SDL_AudioSpec::silence
Uint8 silence
Definition: SDL_audio.h:183
MS_ADPCM_CoeffData::coeffcount
Uint16 coeffcount
Definition: SDL_wave.c:94
WaveFile::chunk
WaveChunk chunk
Definition: SDL_wave.h:132
WaveCheckFormat
static int WaveCheckFormat(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:1680
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:496
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:1142
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:1259
MS_ADPCM_DecodeBlockData
static int MS_ADPCM_DecodeBlockData(ADPCM_DecoderState *state)
Definition: SDL_wave.c:594
WaveChunk::length
Uint32 length
Definition: SDL_wave.h:97
src
GLenum src
Definition: SDL_opengl_glext.h:1740
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:1596
MS_ADPCM_ChannelState::coeff2
Sint16 coeff2
Definition: SDL_wave.c:103
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:377
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:337
WaveExtensibleGUID::encoding
Uint16 encoding
Definition: SDL_wave.c:1590
TruncDropBlock
@ TruncDropBlock
Definition: SDL_wave.h:118
IMA_ADPCM_Init
static int IMA_ADPCM_Init(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:796
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:1512
SDL_HINT_WAVE_TRUNCATION
#define SDL_HINT_WAVE_TRUNCATION
Controls how a truncated WAVE file is handled.
Definition: SDL_hints.h:1232
MS_ADPCM_CoeffData
Definition: SDL_wave.c:92
FactNoHint
@ FactNoHint
Definition: SDL_wave.h:123
AUDIO_S16LSB
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
LAW_Decode
static int LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:1171
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:1216
SDL_RWops
Definition: SDL_rwops.h:52
PCM_Init
static int PCM_Init(WaveFile *file, size_t datalength)
Definition: SDL_wave.c:1314
Sint8
int8_t Sint8
Definition: SDL_stdinc.h:173
WaveChunk::position
Sint64 position
Definition: SDL_wave.h:98
ptr
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF ptr
Definition: pixman-arm-simd-asm.h:171
state
struct xkb_state * state
Definition: SDL_waylandsym.h:114
PCM_ConvertSint24ToSint32
static int PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:1357
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:1595
SDL_SwapLE32
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:245
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
IMA_ADPCM_CODE
#define IMA_ADPCM_CODE
Definition: SDL_wave.h:44
WaveAdjustToFactValue
static Sint64 WaveAdjustToFactValue(WaveFile *file, Sint64 sampleframes)
Definition: SDL_wave.c:323
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:862
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179