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

Go to the source code of this file.

Data Structures

struct  MS_ADPCM_decodestate
 
struct  MS_ADPCM_decoder
 
struct  IMA_ADPCM_decodestate
 
struct  IMA_ADPCM_decoder
 

Functions

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

Variables

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

Function Documentation

◆ ConvertSint24ToSint32()

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

Definition at line 419 of file SDL_wave.c.

References i, SDL_OutOfMemory, and SDL_realloc.

Referenced by SDL_LoadWAV_RW().

420 {
421  const double DIVBY8388608 = 0.00000011920928955078125;
422  const Uint32 original_len = *audio_len;
423  const Uint32 samples = original_len / 3;
424  const Uint32 expanded_len = samples * sizeof (Uint32);
425  Uint8 *ptr = (Uint8 *) SDL_realloc(*audio_buf, expanded_len);
426  const Uint8 *src;
427  Uint32 *dst;
428  Uint32 i;
429 
430  if (!ptr) {
431  return SDL_OutOfMemory();
432  }
433 
434  *audio_buf = ptr;
435  *audio_len = expanded_len;
436 
437  /* work from end to start, since we're expanding in-place. */
438  src = (ptr + original_len) - 3;
439  dst = ((Uint32 *) (ptr + expanded_len)) - 1;
440  for (i = 0; i < samples; i++) {
441  /* There's probably a faster way to do all this. */
442  const Sint32 converted = ((Sint32) ( (((Uint32) src[2]) << 24) |
443  (((Uint32) src[1]) << 16) |
444  (((Uint32) src[0]) << 8) )) >> 8;
445  const double scaled = (((double) converted) * DIVBY8388608);
446  src -= 3;
447  *(dst--) = (Sint32) (scaled * 2147483647.0);
448  }
449 
450  return 0;
451 }
GLenum GLenum dst
#define SDL_realloc
GLenum src
uint8_t Uint8
Definition: SDL_stdinc.h:179
int32_t Sint32
Definition: SDL_stdinc.h:197
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
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
uint32_t Uint32
Definition: SDL_stdinc.h:203
GLsizei samples

◆ Fill_IMA_ADPCM_block()

static void Fill_IMA_ADPCM_block ( Uint8 decoded,
Uint8 encoded,
int  channel,
int  numchannels,
struct IMA_ADPCM_decodestate state 
)
static

Definition at line 320 of file SDL_wave.c.

References i, and IMA_ADPCM_nibble().

Referenced by IMA_ADPCM_decode().

323 {
324  int i;
325  Sint8 nybble;
326  Sint32 new_sample;
327 
328  decoded += (channel * 2);
329  for (i = 0; i < 4; ++i) {
330  nybble = (*encoded) & 0x0F;
331  new_sample = IMA_ADPCM_nibble(state, nybble);
332  decoded[0] = new_sample & 0xFF;
333  new_sample >>= 8;
334  decoded[1] = new_sample & 0xFF;
335  decoded += 2 * numchannels;
336 
337  nybble = (*encoded) >> 4;
338  new_sample = IMA_ADPCM_nibble(state, nybble);
339  decoded[0] = new_sample & 0xFF;
340  new_sample >>= 8;
341  decoded[1] = new_sample & 0xFF;
342  decoded += 2 * numchannels;
343 
344  ++encoded;
345  }
346 }
int8_t Sint8
Definition: SDL_stdinc.h:173
int32_t Sint32
Definition: SDL_stdinc.h:197
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
static Sint32 IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state, Uint8 nybble)
Definition: SDL_wave.c:265

◆ IMA_ADPCM_decode()

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

Definition at line 349 of file SDL_wave.c.

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

Referenced by SDL_LoadWAV_RW().

350 {
352  Uint8 *freeable, *encoded, *decoded;
353  Sint32 encoded_len, samplesleft;
354  unsigned int c, channels;
355 
356  /* Check to make sure we have enough variables in the state array */
357  channels = IMA_ADPCM_state.wavefmt.channels;
358  if (channels > SDL_arraysize(IMA_ADPCM_state.state)) {
359  SDL_SetError("IMA ADPCM decoder can only handle %u channels",
360  (unsigned int)SDL_arraysize(IMA_ADPCM_state.state));
361  return (-1);
362  }
363  state = IMA_ADPCM_state.state;
364 
365  /* Allocate the proper sized output buffer */
366  encoded_len = *audio_len;
367  encoded = *audio_buf;
368  freeable = *audio_buf;
369  *audio_len = (encoded_len / IMA_ADPCM_state.wavefmt.blockalign) *
372  *audio_buf = (Uint8 *) SDL_malloc(*audio_len);
373  if (*audio_buf == NULL) {
374  return SDL_OutOfMemory();
375  }
376  decoded = *audio_buf;
377 
378  /* Get ready... Go! */
379  while (encoded_len >= IMA_ADPCM_state.wavefmt.blockalign) {
380  /* Grab the initial information for this block */
381  for (c = 0; c < channels; ++c) {
382  /* Fill the state information for this block */
383  state[c].sample = ((encoded[1] << 8) | encoded[0]);
384  encoded += 2;
385  if (state[c].sample & 0x8000) {
386  state[c].sample -= 0x10000;
387  }
388  state[c].index = *encoded++;
389  /* Reserved byte in buffer header, should be 0 */
390  if (*encoded++ != 0) {
391  /* Uh oh, corrupt data? Buggy code? */ ;
392  }
393 
394  /* Store the initial sample we start with */
395  decoded[0] = (Uint8) (state[c].sample & 0xFF);
396  decoded[1] = (Uint8) (state[c].sample >> 8);
397  decoded += 2;
398  }
399 
400  /* Decode and store the other samples in this block */
401  samplesleft = (IMA_ADPCM_state.wSamplesPerBlock - 1) * channels;
402  while (samplesleft > 0) {
403  for (c = 0; c < channels; ++c) {
404  Fill_IMA_ADPCM_block(decoded, encoded,
405  c, channels, &state[c]);
406  encoded += 4;
407  samplesleft -= 8;
408  }
409  decoded += (channels * 8 * 2);
410  }
411  encoded_len -= IMA_ADPCM_state.wavefmt.blockalign;
412  }
413  SDL_free(freeable);
414  return (0);
415 }
Uint16 blockalign
Definition: SDL_wave.h:56
static void Fill_IMA_ADPCM_block(Uint8 *decoded, Uint8 *encoded, int channel, int numchannels, struct IMA_ADPCM_decodestate *state)
Definition: SDL_wave.c:320
struct xkb_state * state
static struct IMA_ADPCM_decoder IMA_ADPCM_state
WaveFMT wavefmt
Definition: SDL_wave.c:231
Uint16 channels
Definition: SDL_wave.h:53
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_free
struct IMA_ADPCM_decodestate state[2]
Definition: SDL_wave.c:234
const GLubyte * c
int32_t Sint32
Definition: SDL_stdinc.h:197
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_SetError
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
#define SDL_malloc
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:232
int16_t Sint16
Definition: SDL_stdinc.h:185

◆ IMA_ADPCM_nibble()

static Sint32 IMA_ADPCM_nibble ( struct IMA_ADPCM_decodestate state,
Uint8  nybble 
)
static

Definition at line 265 of file SDL_wave.c.

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

Referenced by Fill_IMA_ADPCM_block().

266 {
267  const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
268  const Sint32 min_audioval = -(1 << (16 - 1));
269  const int index_table[16] = {
270  -1, -1, -1, -1,
271  2, 4, 6, 8,
272  -1, -1, -1, -1,
273  2, 4, 6, 8
274  };
275  const Sint32 step_table[89] = {
276  7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
277  34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130,
278  143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408,
279  449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282,
280  1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
281  3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
282  9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350,
283  22385, 24623, 27086, 29794, 32767
284  };
285  Sint32 delta, step;
286 
287  /* Compute difference and new sample value */
288  if (state->index > 88) {
289  state->index = 88;
290  } else if (state->index < 0) {
291  state->index = 0;
292  }
293  /* explicit cast to avoid gcc warning about using 'char' as array index */
294  step = step_table[(int)state->index];
295  delta = step >> 3;
296  if (nybble & 0x04)
297  delta += step;
298  if (nybble & 0x02)
299  delta += (step >> 1);
300  if (nybble & 0x01)
301  delta += (step >> 2);
302  if (nybble & 0x08)
303  delta = -delta;
304  state->sample += delta;
305 
306  /* Update index value */
307  state->index += index_table[nybble];
308 
309  /* Clamp output sample */
310  if (state->sample > max_audioval) {
311  state->sample = max_audioval;
312  } else if (state->sample < min_audioval) {
313  state->sample = min_audioval;
314  }
315  return (state->sample);
316 }
int32_t Sint32
Definition: SDL_stdinc.h:197

◆ InitIMA_ADPCM()

static int InitIMA_ADPCM ( WaveFMT format,
int  length 
)
static

Definition at line 238 of file SDL_wave.c.

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

Referenced by SDL_LoadWAV_RW().

239 {
240  Uint8 *rogue_feel, *rogue_feel_end;
241 
242 
243  /* Set the rogue pointer to the IMA_ADPCM specific data */
250  rogue_feel = (Uint8 *) format + sizeof(*format);
251  rogue_feel_end = (Uint8 *) format + length;
252  if (sizeof(*format) == 16) {
253  /* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
254  rogue_feel += sizeof(Uint16);
255  }
256  if (rogue_feel + 2 > rogue_feel_end) goto too_short;
257  IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
258  return (0);
259  too_short:
260  SDL_SetError("Unexpected length of a chunk with an IMA ADPCM format");
261  return (-1);
262 }
Uint16 blockalign
Definition: SDL_wave.h:56
uint16_t Uint16
Definition: SDL_stdinc.h:191
static struct IMA_ADPCM_decoder IMA_ADPCM_state
Uint16 encoding
Definition: SDL_wave.h:52
WaveFMT wavefmt
Definition: SDL_wave.c:231
Uint16 channels
Definition: SDL_wave.h:53
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:233
#define SDL_SetError
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:232
Uint32 frequency
Definition: SDL_wave.h:54
Uint16 bitspersample
Definition: SDL_wave.h:57
GLuint GLsizei GLsizei * length
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:232
Uint32 byterate
Definition: SDL_wave.h:55

◆ InitMS_ADPCM()

static int InitMS_ADPCM ( WaveFMT format,
int  length 
)
static

Definition at line 48 of file SDL_wave.c.

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

Referenced by SDL_LoadWAV_RW().

49 {
50  Uint8 *rogue_feel, *rogue_feel_end;
51  int i;
52 
53  /* Set the rogue pointer to the MS_ADPCM specific data */
54  if (length < sizeof(*format)) goto too_short;
61  SDL_SwapLE16(format->bitspersample);
62  rogue_feel = (Uint8 *) format + sizeof(*format);
63  rogue_feel_end = (Uint8 *)format + length;
64  if (sizeof(*format) == 16) {
65  /* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
66  rogue_feel += sizeof(Uint16);
67  }
68  if (rogue_feel + 4 > rogue_feel_end) goto too_short;
69  MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
70  rogue_feel += sizeof(Uint16);
71  MS_ADPCM_state.wNumCoef = ((rogue_feel[1] << 8) | rogue_feel[0]);
72  rogue_feel += sizeof(Uint16);
73  if (MS_ADPCM_state.wNumCoef != 7) {
74  SDL_SetError("Unknown set of MS_ADPCM coefficients");
75  return (-1);
76  }
77  for (i = 0; i < MS_ADPCM_state.wNumCoef; ++i) {
78  if (rogue_feel + 4 > rogue_feel_end) goto too_short;
79  MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1] << 8) | rogue_feel[0]);
80  rogue_feel += sizeof(Uint16);
81  MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1] << 8) | rogue_feel[0]);
82  rogue_feel += sizeof(Uint16);
83  }
84  return (0);
85 too_short:
86  SDL_SetError("Unexpected length of a chunk with a MS ADPCM format");
87  return(-1);
88 }
Uint16 wNumCoef
Definition: SDL_wave.c:42
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:41
Uint16 blockalign
Definition: SDL_wave.h:56
uint16_t Uint16
Definition: SDL_stdinc.h:191
Uint16 encoding
Definition: SDL_wave.h:52
Uint16 channels
Definition: SDL_wave.h:53
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:233
Sint16 aCoeff[7][2]
Definition: SDL_wave.c:43
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
#define SDL_SetError
Uint32 frequency
Definition: SDL_wave.h:54
Uint16 bitspersample
Definition: SDL_wave.h:57
GLuint GLsizei GLsizei * length
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:232
Uint32 byterate
Definition: SDL_wave.h:55
WaveFMT wavefmt
Definition: SDL_wave.c:40
static struct MS_ADPCM_decoder MS_ADPCM_state

◆ MS_ADPCM_decode()

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

Definition at line 125 of file SDL_wave.c.

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

Referenced by SDL_LoadWAV_RW().

126 {
127  struct MS_ADPCM_decodestate *state[2];
128  Uint8 *freeable, *encoded, *decoded;
129  Sint32 encoded_len, samplesleft;
130  Sint8 nybble;
131  Uint8 stereo;
132  Sint16 *coeff[2];
133  Sint32 new_sample;
134 
135  /* Allocate the proper sized output buffer */
136  encoded_len = *audio_len;
137  encoded = *audio_buf;
138  freeable = *audio_buf;
139  *audio_len = (encoded_len / MS_ADPCM_state.wavefmt.blockalign) *
142  *audio_buf = (Uint8 *) SDL_malloc(*audio_len);
143  if (*audio_buf == NULL) {
144  return SDL_OutOfMemory();
145  }
146  decoded = *audio_buf;
147 
148  /* Get ready... Go! */
149  stereo = (MS_ADPCM_state.wavefmt.channels == 2);
150  state[0] = &MS_ADPCM_state.state[0];
151  state[1] = &MS_ADPCM_state.state[stereo];
152  while (encoded_len >= MS_ADPCM_state.wavefmt.blockalign) {
153  /* Grab the initial information for this block */
154  state[0]->hPredictor = *encoded++;
155  if (stereo) {
156  state[1]->hPredictor = *encoded++;
157  }
158  state[0]->iDelta = ((encoded[1] << 8) | encoded[0]);
159  encoded += sizeof(Sint16);
160  if (stereo) {
161  state[1]->iDelta = ((encoded[1] << 8) | encoded[0]);
162  encoded += sizeof(Sint16);
163  }
164  state[0]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
165  encoded += sizeof(Sint16);
166  if (stereo) {
167  state[1]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
168  encoded += sizeof(Sint16);
169  }
170  state[0]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
171  encoded += sizeof(Sint16);
172  if (stereo) {
173  state[1]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
174  encoded += sizeof(Sint16);
175  }
176  coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor];
177  coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor];
178 
179  /* Store the two initial samples we start with */
180  decoded[0] = state[0]->iSamp2 & 0xFF;
181  decoded[1] = state[0]->iSamp2 >> 8;
182  decoded += 2;
183  if (stereo) {
184  decoded[0] = state[1]->iSamp2 & 0xFF;
185  decoded[1] = state[1]->iSamp2 >> 8;
186  decoded += 2;
187  }
188  decoded[0] = state[0]->iSamp1 & 0xFF;
189  decoded[1] = state[0]->iSamp1 >> 8;
190  decoded += 2;
191  if (stereo) {
192  decoded[0] = state[1]->iSamp1 & 0xFF;
193  decoded[1] = state[1]->iSamp1 >> 8;
194  decoded += 2;
195  }
196 
197  /* Decode and store the other samples in this block */
198  samplesleft = (MS_ADPCM_state.wSamplesPerBlock - 2) *
200  while (samplesleft > 0) {
201  nybble = (*encoded) >> 4;
202  new_sample = MS_ADPCM_nibble(state[0], nybble, coeff[0]);
203  decoded[0] = new_sample & 0xFF;
204  new_sample >>= 8;
205  decoded[1] = new_sample & 0xFF;
206  decoded += 2;
207 
208  nybble = (*encoded) & 0x0F;
209  new_sample = MS_ADPCM_nibble(state[1], nybble, coeff[1]);
210  decoded[0] = new_sample & 0xFF;
211  new_sample >>= 8;
212  decoded[1] = new_sample & 0xFF;
213  decoded += 2;
214 
215  ++encoded;
216  samplesleft -= 2;
217  }
218  encoded_len -= MS_ADPCM_state.wavefmt.blockalign;
219  }
220  SDL_free(freeable);
221  return (0);
222 }
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:41
Uint16 blockalign
Definition: SDL_wave.h:56
struct xkb_state * state
struct MS_ADPCM_decodestate state[2]
Definition: SDL_wave.c:45
static Sint32 MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state, Uint8 nybble, Sint16 *coeff)
Definition: SDL_wave.c:91
Uint16 channels
Definition: SDL_wave.h:53
int8_t Sint8
Definition: SDL_stdinc.h:173
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_free
Sint16 aCoeff[7][2]
Definition: SDL_wave.c:43
int32_t Sint32
Definition: SDL_stdinc.h:197
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_malloc
WaveFMT wavefmt
Definition: SDL_wave.c:40
int16_t Sint16
Definition: SDL_stdinc.h:185
static struct MS_ADPCM_decoder MS_ADPCM_state

◆ MS_ADPCM_nibble()

static Sint32 MS_ADPCM_nibble ( struct MS_ADPCM_decodestate state,
Uint8  nybble,
Sint16 coeff 
)
static

Definition at line 91 of file SDL_wave.c.

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

Referenced by MS_ADPCM_decode().

93 {
94  const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
95  const Sint32 min_audioval = -(1 << (16 - 1));
96  const Sint32 adaptive[] = {
97  230, 230, 230, 230, 307, 409, 512, 614,
98  768, 614, 512, 409, 307, 230, 230, 230
99  };
100  Sint32 new_sample, delta;
101 
102  new_sample = ((state->iSamp1 * coeff[0]) +
103  (state->iSamp2 * coeff[1])) / 256;
104  if (nybble & 0x08) {
105  new_sample += state->iDelta * (nybble - 0x10);
106  } else {
107  new_sample += state->iDelta * nybble;
108  }
109  if (new_sample < min_audioval) {
110  new_sample = min_audioval;
111  } else if (new_sample > max_audioval) {
112  new_sample = max_audioval;
113  }
114  delta = ((Sint32) state->iDelta * adaptive[nybble]) / 256;
115  if (delta < 16) {
116  delta = 16;
117  }
118  state->iDelta = (Uint16) delta;
119  state->iSamp2 = state->iSamp1;
120  state->iSamp1 = (Sint16) new_sample;
121  return (new_sample);
122 }
uint16_t Uint16
Definition: SDL_stdinc.h:191
int32_t Sint32
Definition: SDL_stdinc.h:197
int16_t Sint16
Definition: SDL_stdinc.h:185

◆ ReadChunk()

static int ReadChunk ( SDL_RWops src,
Chunk chunk 
)
static

Definition at line 689 of file SDL_wave.c.

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

Referenced by SDL_LoadWAV_RW().

690 {
691  chunk->magic = SDL_ReadLE32(src);
692  chunk->length = SDL_ReadLE32(src);
693  chunk->data = (Uint8 *) SDL_malloc(chunk->length);
694  if (chunk->data == NULL) {
695  return SDL_OutOfMemory();
696  }
697  if (SDL_RWread(src, chunk->data, chunk->length, 1) != 1) {
698  SDL_free(chunk->data);
699  chunk->data = NULL;
700  return SDL_Error(SDL_EFREAD);
701  }
702  return (chunk->length);
703 }
#define SDL_ReadLE32
#define SDL_RWread(ctx, ptr, size, n)
Definition: SDL_rwops.h:187
Uint32 length
Definition: SDL_wave.h:64
#define SDL_Error
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_free
Uint8 * data
Definition: SDL_wave.h:65
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
Uint32 magic
Definition: SDL_wave.h:63
#define SDL_malloc

◆ SDL_FreeWAV()

void SDL_FreeWAV ( Uint8 audio_buf)

This function frees data previously allocated with SDL_LoadWAV_RW()

Definition at line 683 of file SDL_wave.c.

References SDL_free.

684 {
685  SDL_free(audio_buf);
686 }
#define SDL_free

◆ SDL_LoadWAV_RW()

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

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

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

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

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

Definition at line 459 of file SDL_wave.c.

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

461 {
462  int was_error;
463  Chunk chunk;
464  int lenread;
465  int IEEE_float_encoded, MS_ADPCM_encoded, IMA_ADPCM_encoded;
466  int samplesize;
467 
468  /* WAV magic header */
469  Uint32 RIFFchunk;
470  Uint32 wavelen = 0;
471  Uint32 WAVEmagic;
472  Uint32 headerDiff = 0;
473 
474  /* FMT chunk */
475  WaveFMT *format = NULL;
476  WaveExtensibleFMT *ext = NULL;
477 
478  SDL_zero(chunk);
479 
480  /* Make sure we are passed a valid data source */
481  was_error = 0;
482  if (src == NULL) {
483  was_error = 1;
484  goto done;
485  }
486 
487  /* Check the magic header */
488  RIFFchunk = SDL_ReadLE32(src);
489  wavelen = SDL_ReadLE32(src);
490  if (wavelen == WAVE) { /* The RIFFchunk has already been read */
491  WAVEmagic = wavelen;
492  wavelen = RIFFchunk;
493  RIFFchunk = RIFF;
494  } else {
495  WAVEmagic = SDL_ReadLE32(src);
496  }
497  if ((RIFFchunk != RIFF) || (WAVEmagic != WAVE)) {
498  SDL_SetError("Unrecognized file type (not WAVE)");
499  was_error = 1;
500  goto done;
501  }
502  headerDiff += sizeof(Uint32); /* for WAVE */
503 
504  /* Read the audio data format chunk */
505  chunk.data = NULL;
506  do {
507  SDL_free(chunk.data);
508  chunk.data = NULL;
509  lenread = ReadChunk(src, &chunk);
510  if (lenread < 0) {
511  was_error = 1;
512  goto done;
513  }
514  /* 2 Uint32's for chunk header+len, plus the lenread */
515  headerDiff += lenread + 2 * sizeof(Uint32);
516  } while ((chunk.magic == FACT) || (chunk.magic == LIST) || (chunk.magic == BEXT) || (chunk.magic == JUNK));
517 
518  /* Decode the audio data format */
519  format = (WaveFMT *) chunk.data;
520  if (chunk.magic != FMT) {
521  SDL_SetError("Complex WAVE files not supported");
522  was_error = 1;
523  goto done;
524  }
525  IEEE_float_encoded = MS_ADPCM_encoded = IMA_ADPCM_encoded = 0;
526  switch (SDL_SwapLE16(format->encoding)) {
527  case PCM_CODE:
528  /* We can understand this */
529  break;
530  case IEEE_FLOAT_CODE:
531  IEEE_float_encoded = 1;
532  /* We can understand this */
533  break;
534  case MS_ADPCM_CODE:
535  /* Try to understand this */
536  if (InitMS_ADPCM(format,lenread) < 0) {
537  was_error = 1;
538  goto done;
539  }
540  MS_ADPCM_encoded = 1;
541  break;
542  case IMA_ADPCM_CODE:
543  /* Try to understand this */
544  if (InitIMA_ADPCM(format, lenread) < 0) {
545  was_error = 1;
546  goto done;
547  }
548  IMA_ADPCM_encoded = 1;
549  break;
550  case EXTENSIBLE_CODE:
551  /* note that this ignores channel masks, smaller valid bit counts
552  inside a larger container, and most subtypes. This is just enough
553  to get things that didn't really _need_ WAVE_FORMAT_EXTENSIBLE
554  to be useful working when they use this format flag. */
555  ext = (WaveExtensibleFMT *) format;
556  if (SDL_SwapLE16(ext->size) < 22) {
557  SDL_SetError("bogus extended .wav header");
558  was_error = 1;
559  goto done;
560  }
561  if (SDL_memcmp(ext->subformat, extensible_pcm_guid, 16) == 0) {
562  break; /* cool. */
563  } else if (SDL_memcmp(ext->subformat, extensible_ieee_guid, 16) == 0) {
564  IEEE_float_encoded = 1;
565  break;
566  }
567  break;
568  case MP3_CODE:
569  SDL_SetError("MPEG Layer 3 data not supported");
570  was_error = 1;
571  goto done;
572  default:
573  SDL_SetError("Unknown WAVE data format: 0x%.4x",
574  SDL_SwapLE16(format->encoding));
575  was_error = 1;
576  goto done;
577  }
578  SDL_zerop(spec);
579  spec->freq = SDL_SwapLE32(format->frequency);
580 
581  if (IEEE_float_encoded) {
582  if ((SDL_SwapLE16(format->bitspersample)) != 32) {
583  was_error = 1;
584  } else {
585  spec->format = AUDIO_F32;
586  }
587  } else {
588  switch (SDL_SwapLE16(format->bitspersample)) {
589  case 4:
590  if (MS_ADPCM_encoded || IMA_ADPCM_encoded) {
591  spec->format = AUDIO_S16;
592  } else {
593  was_error = 1;
594  }
595  break;
596  case 8:
597  spec->format = AUDIO_U8;
598  break;
599  case 16:
600  spec->format = AUDIO_S16;
601  break;
602  case 24: /* convert this. */
603  spec->format = AUDIO_S32;
604  break;
605  case 32:
606  spec->format = AUDIO_S32;
607  break;
608  default:
609  was_error = 1;
610  break;
611  }
612  }
613 
614  if (was_error) {
615  SDL_SetError("Unknown %d-bit PCM data format",
616  SDL_SwapLE16(format->bitspersample));
617  goto done;
618  }
619  spec->channels = (Uint8) SDL_SwapLE16(format->channels);
620  spec->samples = 4096; /* Good default buffer size */
621 
622  /* Read the audio data chunk */
623  *audio_buf = NULL;
624  do {
625  SDL_free(*audio_buf);
626  *audio_buf = NULL;
627  lenread = ReadChunk(src, &chunk);
628  if (lenread < 0) {
629  was_error = 1;
630  goto done;
631  }
632  *audio_len = lenread;
633  *audio_buf = chunk.data;
634  if (chunk.magic != DATA)
635  headerDiff += lenread + 2 * sizeof(Uint32);
636  } while (chunk.magic != DATA);
637  headerDiff += 2 * sizeof(Uint32); /* for the data chunk and len */
638 
639  if (MS_ADPCM_encoded) {
640  if (MS_ADPCM_decode(audio_buf, audio_len) < 0) {
641  was_error = 1;
642  goto done;
643  }
644  }
645  if (IMA_ADPCM_encoded) {
646  if (IMA_ADPCM_decode(audio_buf, audio_len) < 0) {
647  was_error = 1;
648  goto done;
649  }
650  }
651 
652  if (SDL_SwapLE16(format->bitspersample) == 24) {
653  if (ConvertSint24ToSint32(audio_buf, audio_len) < 0) {
654  was_error = 1;
655  goto done;
656  }
657  }
658 
659  /* Don't return a buffer that isn't a multiple of samplesize */
660  samplesize = ((SDL_AUDIO_BITSIZE(spec->format)) / 8) * spec->channels;
661  *audio_len &= ~(samplesize - 1);
662 
663  done:
664  SDL_free(format);
665  if (src) {
666  if (freesrc) {
667  SDL_RWclose(src);
668  } else {
669  /* seek to the end of the file (given by the RIFF chunk) */
670  SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR);
671  }
672  }
673  if (was_error) {
674  spec = NULL;
675  }
676  return (spec);
677 }
#define PCM_CODE
Definition: SDL_wave.h:36
#define RIFF
Definition: SDL_wave.h:28
#define LIST
Definition: SDL_wave.h:31
#define MP3_CODE
Definition: SDL_wave.h:40
Definition: SDL_wave.h:61
static int InitMS_ADPCM(WaveFMT *format, int length)
Definition: SDL_wave.c:48
#define SDL_ReadLE32
Uint32 length
Definition: SDL_wave.h:64
Uint16 samples
Definition: SDL_audio.h:184
static int InitIMA_ADPCM(WaveFMT *format, int length)
Definition: SDL_wave.c:238
Uint16 encoding
Definition: SDL_wave.h:52
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:125
Uint16 channels
Definition: SDL_wave.h:53
#define FMT
Definition: SDL_wave.h:34
#define SDL_RWseek(ctx, offset, whence)
Definition: SDL_rwops.h:185
static const Uint8 extensible_ieee_guid[16]
Definition: SDL_wave.c:456
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
#define AUDIO_U8
Definition: SDL_audio.h:89
#define DATA
Definition: SDL_wave.h:35
#define FACT
Definition: SDL_wave.h:30
Uint8 channels
Definition: SDL_audio.h:182
static int IMA_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:349
#define EXTENSIBLE_CODE
Definition: SDL_wave.h:41
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_free
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:233
static int ConvertSint24ToSint32(Uint8 **audio_buf, Uint32 *audio_len)
Definition: SDL_wave.c:419
int done
Definition: checkkeys.c:28
#define AUDIO_S32
Definition: SDL_audio.h:105
static const Uint8 extensible_pcm_guid[16]
Definition: SDL_wave.c:455
#define WAVE
Definition: SDL_wave.h:29
#define SDL_memcmp
#define JUNK
Definition: SDL_wave.h:33
Uint8 subformat[16]
Definition: SDL_wave.h:74
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
Uint8 * data
Definition: SDL_wave.h:65
#define NULL
Definition: begin_code.h:164
#define IEEE_FLOAT_CODE
Definition: SDL_wave.h:38
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
#define IMA_ADPCM_CODE
Definition: SDL_wave.h:39
#define SDL_SetError
SDL_AudioFormat format
Definition: SDL_audio.h:181
uint32_t Uint32
Definition: SDL_stdinc.h:203
Uint32 magic
Definition: SDL_wave.h:63
#define AUDIO_S16
Definition: SDL_audio.h:96
Uint32 frequency
Definition: SDL_wave.h:54
#define RW_SEEK_CUR
Definition: SDL_rwops.h:175
Uint16 bitspersample
Definition: SDL_wave.h:57
#define AUDIO_F32
Definition: SDL_audio.h:114
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:232
#define BEXT
Definition: SDL_wave.h:32
static int ReadChunk(SDL_RWops *src, Chunk *chunk)
Definition: SDL_wave.c:689
#define MS_ADPCM_CODE
Definition: SDL_wave.h:37

Variable Documentation

◆ extensible_ieee_guid

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

Definition at line 456 of file SDL_wave.c.

Referenced by SDL_LoadWAV_RW().

◆ extensible_pcm_guid

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

Definition at line 455 of file SDL_wave.c.

Referenced by SDL_LoadWAV_RW().

◆ IMA_ADPCM_state

struct IMA_ADPCM_decoder IMA_ADPCM_state
static

Referenced by IMA_ADPCM_decode(), and InitIMA_ADPCM().

◆ MS_ADPCM_state

struct MS_ADPCM_decoder MS_ADPCM_state
static

Referenced by InitMS_ADPCM(), and MS_ADPCM_decode().