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)
 
static Sint32 MS_ADPCM_nibble (struct MS_ADPCM_decodestate *state, Uint8 nybble, Sint16 *coeff)
 
static int MS_ADPCM_decode (Uint8 **audio_buf, Uint32 *audio_len)
 
static int InitIMA_ADPCM (WaveFMT *format)
 
static Sint32 IMA_ADPCM_nibble (struct IMA_ADPCM_decodestate *state, Uint8 nybble)
 
static void Fill_IMA_ADPCM_block (Uint8 *decoded, Uint8 *encoded, int channel, int numchannels, struct IMA_ADPCM_decodestate *state)
 
static int IMA_ADPCM_decode (Uint8 **audio_buf, Uint32 *audio_len)
 
static int ConvertSint24ToSint32 (Uint8 **audio_buf, Uint32 *audio_len)
 
SDL_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 408 of file SDL_wave.c.

References i, SDL_OutOfMemory, and SDL_realloc.

Referenced by SDL_LoadWAV_RW().

409 {
410  const double DIVBY8388608 = 0.00000011920928955078125;
411  const Uint32 original_len = *audio_len;
412  const Uint32 samples = original_len / 3;
413  const Uint32 expanded_len = samples * sizeof (Uint32);
414  Uint8 *ptr = (Uint8 *) SDL_realloc(*audio_buf, expanded_len);
415  const Uint8 *src;
416  Uint32 *dst;
417  Uint32 i;
418 
419  if (!ptr) {
420  return SDL_OutOfMemory();
421  }
422 
423  *audio_buf = ptr;
424  *audio_len = expanded_len;
425 
426  /* work from end to start, since we're expanding in-place. */
427  src = (ptr + original_len) - 3;
428  dst = ((Uint32 *) (ptr + expanded_len)) - 1;
429  for (i = 0; i < samples; i++) {
430  /* There's probably a faster way to do all this. */
431  const Sint32 converted = ((Sint32) ( (((Uint32) src[2]) << 24) |
432  (((Uint32) src[1]) << 16) |
433  (((Uint32) src[0]) << 8) )) >> 8;
434  const double scaled = (((double) converted) * DIVBY8388608);
435  src -= 3;
436  *(dst--) = (Sint32) (scaled * 2147483647.0);
437  }
438 
439  return 0;
440 }
GLenum GLenum dst
uint32_t Uint32
Definition: SDL_stdinc.h:181
#define SDL_realloc
GLenum src
uint8_t Uint8
Definition: SDL_stdinc.h:157
int32_t Sint32
Definition: SDL_stdinc.h:175
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
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 309 of file SDL_wave.c.

References i, and IMA_ADPCM_nibble().

Referenced by IMA_ADPCM_decode().

312 {
313  int i;
314  Sint8 nybble;
315  Sint32 new_sample;
316 
317  decoded += (channel * 2);
318  for (i = 0; i < 4; ++i) {
319  nybble = (*encoded) & 0x0F;
320  new_sample = IMA_ADPCM_nibble(state, nybble);
321  decoded[0] = new_sample & 0xFF;
322  new_sample >>= 8;
323  decoded[1] = new_sample & 0xFF;
324  decoded += 2 * numchannels;
325 
326  nybble = (*encoded) >> 4;
327  new_sample = IMA_ADPCM_nibble(state, nybble);
328  decoded[0] = new_sample & 0xFF;
329  new_sample >>= 8;
330  decoded[1] = new_sample & 0xFF;
331  decoded += 2 * numchannels;
332 
333  ++encoded;
334  }
335 }
int8_t Sint8
Definition: SDL_stdinc.h:151
int32_t Sint32
Definition: SDL_stdinc.h:175
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:254

◆ IMA_ADPCM_decode()

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

Definition at line 338 of file SDL_wave.c.

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

Referenced by SDL_LoadWAV_RW().

339 {
341  Uint8 *freeable, *encoded, *decoded;
342  Sint32 encoded_len, samplesleft;
343  unsigned int c, channels;
344 
345  /* Check to make sure we have enough variables in the state array */
346  channels = IMA_ADPCM_state.wavefmt.channels;
347  if (channels > SDL_arraysize(IMA_ADPCM_state.state)) {
348  SDL_SetError("IMA ADPCM decoder can only handle %u channels",
349  (unsigned int)SDL_arraysize(IMA_ADPCM_state.state));
350  return (-1);
351  }
352  state = IMA_ADPCM_state.state;
353 
354  /* Allocate the proper sized output buffer */
355  encoded_len = *audio_len;
356  encoded = *audio_buf;
357  freeable = *audio_buf;
358  *audio_len = (encoded_len / IMA_ADPCM_state.wavefmt.blockalign) *
361  *audio_buf = (Uint8 *) SDL_malloc(*audio_len);
362  if (*audio_buf == NULL) {
363  return SDL_OutOfMemory();
364  }
365  decoded = *audio_buf;
366 
367  /* Get ready... Go! */
368  while (encoded_len >= IMA_ADPCM_state.wavefmt.blockalign) {
369  /* Grab the initial information for this block */
370  for (c = 0; c < channels; ++c) {
371  /* Fill the state information for this block */
372  state[c].sample = ((encoded[1] << 8) | encoded[0]);
373  encoded += 2;
374  if (state[c].sample & 0x8000) {
375  state[c].sample -= 0x10000;
376  }
377  state[c].index = *encoded++;
378  /* Reserved byte in buffer header, should be 0 */
379  if (*encoded++ != 0) {
380  /* Uh oh, corrupt data? Buggy code? */ ;
381  }
382 
383  /* Store the initial sample we start with */
384  decoded[0] = (Uint8) (state[c].sample & 0xFF);
385  decoded[1] = (Uint8) (state[c].sample >> 8);
386  decoded += 2;
387  }
388 
389  /* Decode and store the other samples in this block */
390  samplesleft = (IMA_ADPCM_state.wSamplesPerBlock - 1) * channels;
391  while (samplesleft > 0) {
392  for (c = 0; c < channels; ++c) {
393  Fill_IMA_ADPCM_block(decoded, encoded,
394  c, channels, &state[c]);
395  encoded += 4;
396  samplesleft -= 8;
397  }
398  decoded += (channels * 8 * 2);
399  }
400  encoded_len -= IMA_ADPCM_state.wavefmt.blockalign;
401  }
402  SDL_free(freeable);
403  return (0);
404 }
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:309
struct xkb_state * state
static struct IMA_ADPCM_decoder IMA_ADPCM_state
WaveFMT wavefmt
Definition: SDL_wave.c:225
Uint16 channels
Definition: SDL_wave.h:53
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
struct IMA_ADPCM_decodestate state[2]
Definition: SDL_wave.c:228
const GLubyte * c
int32_t Sint32
Definition: SDL_stdinc.h:175
#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:93
#define SDL_malloc
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:226
int16_t Sint16
Definition: SDL_stdinc.h:163

◆ IMA_ADPCM_nibble()

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

Definition at line 254 of file SDL_wave.c.

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

Referenced by Fill_IMA_ADPCM_block().

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

◆ InitIMA_ADPCM()

static int InitIMA_ADPCM ( WaveFMT format)
static

Definition at line 232 of file SDL_wave.c.

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

Referenced by SDL_LoadWAV_RW().

233 {
234  Uint8 *rogue_feel;
235 
236  /* Set the rogue pointer to the IMA_ADPCM specific data */
243  SDL_SwapLE16(format->bitspersample);
244  rogue_feel = (Uint8 *) format + sizeof(*format);
245  if (sizeof(*format) == 16) {
246  /* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
247  rogue_feel += sizeof(Uint16);
248  }
249  IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
250  return (0);
251 }
Uint16 blockalign
Definition: SDL_wave.h:56
static struct IMA_ADPCM_decoder IMA_ADPCM_state
Uint16 encoding
Definition: SDL_wave.h:52
WaveFMT wavefmt
Definition: SDL_wave.c:225
Uint16 channels
Definition: SDL_wave.h:53
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_SwapLE32(X)
Definition: SDL_endian.h:233
uint16_t Uint16
Definition: SDL_stdinc.h:169
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:226
Uint32 frequency
Definition: SDL_wave.h:54
Uint16 bitspersample
Definition: SDL_wave.h:57
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:232
Uint32 byterate
Definition: SDL_wave.h:55

◆ InitMS_ADPCM()

static int InitMS_ADPCM ( WaveFMT format)
static

Definition at line 49 of file SDL_wave.c.

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

Referenced by SDL_LoadWAV_RW().

50 {
51  Uint8 *rogue_feel;
52  int i;
53 
54  /* Set the rogue pointer to the MS_ADPCM specific data */
61  SDL_SwapLE16(format->bitspersample);
62  rogue_feel = (Uint8 *) format + sizeof(*format);
63  if (sizeof(*format) == 16) {
64  /* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
65  rogue_feel += sizeof(Uint16);
66  }
67  MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
68  rogue_feel += sizeof(Uint16);
69  MS_ADPCM_state.wNumCoef = ((rogue_feel[1] << 8) | rogue_feel[0]);
70  rogue_feel += sizeof(Uint16);
71  if (MS_ADPCM_state.wNumCoef != 7) {
72  SDL_SetError("Unknown set of MS_ADPCM coefficients");
73  return (-1);
74  }
75  for (i = 0; i < MS_ADPCM_state.wNumCoef; ++i) {
76  MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1] << 8) | rogue_feel[0]);
77  rogue_feel += sizeof(Uint16);
78  MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1] << 8) | rogue_feel[0]);
79  rogue_feel += sizeof(Uint16);
80  }
81  return (0);
82 }
Uint16 wNumCoef
Definition: SDL_wave.c:42
Uint16 wSamplesPerBlock
Definition: SDL_wave.c:41
Uint16 blockalign
Definition: SDL_wave.h:56
Uint16 encoding
Definition: SDL_wave.h:52
Uint16 channels
Definition: SDL_wave.h:53
uint8_t Uint8
Definition: SDL_stdinc.h:157
#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
uint16_t Uint16
Definition: SDL_stdinc.h:169
Uint32 frequency
Definition: SDL_wave.h:54
Uint16 bitspersample
Definition: SDL_wave.h:57
#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 119 of file SDL_wave.c.

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

Referenced by SDL_LoadWAV_RW().

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

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

Referenced by MS_ADPCM_decode().

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

◆ ReadChunk()

static int ReadChunk ( SDL_RWops src,
Chunk chunk 
)
static

Definition at line 678 of file SDL_wave.c.

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

Referenced by SDL_LoadWAV_RW().

679 {
680  chunk->magic = SDL_ReadLE32(src);
681  chunk->length = SDL_ReadLE32(src);
682  chunk->data = (Uint8 *) SDL_malloc(chunk->length);
683  if (chunk->data == NULL) {
684  return SDL_OutOfMemory();
685  }
686  if (SDL_RWread(src, chunk->data, chunk->length, 1) != 1) {
687  SDL_free(chunk->data);
688  chunk->data = NULL;
689  return SDL_Error(SDL_EFREAD);
690  }
691  return (chunk->length);
692 }
#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:157
#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 672 of file SDL_wave.c.

References SDL_free.

673 {
674  SDL_free(audio_buf);
675 }
#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 448 of file SDL_wave.c.

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

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

Variable Documentation

◆ extensible_ieee_guid

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

Definition at line 445 of file SDL_wave.c.

Referenced by SDL_LoadWAV_RW().

◆ extensible_pcm_guid

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

Definition at line 444 of file SDL_wave.c.

Referenced by SDL_LoadWAV_RW().

◆ IMA_ADPCM_state

struct IMA_ADPCM_decoder IMA_ADPCM_state
static

Referenced by IMA_ADPCM_decode(), and InitIMA_ADPCM().

◆ MS_ADPCM_state

struct MS_ADPCM_decoder MS_ADPCM_state
static

Referenced by InitMS_ADPCM(), and MS_ADPCM_decode().