SDL  2.0
SDL_audiocvt.c File Reference
#include "../SDL_internal.h"
#include "SDL.h"
#include "SDL_audio.h"
#include "SDL_audio_c.h"
#include "SDL_loadso.h"
#include "SDL_assert.h"
#include "../SDL_dataqueue.h"
#include "SDL_cpuinfo.h"
+ Include dependency graph for SDL_audiocvt.c:

Go to the source code of this file.

Data Structures

struct  SDL_AudioStream
 

Macros

#define DEBUG_AUDIOSTREAM   0
 
#define RESAMPLER_ZERO_CROSSINGS   5
 
#define RESAMPLER_BITS_PER_SAMPLE   16
 
#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING   (1 << ((RESAMPLER_BITS_PER_SAMPLE / 2) + 1))
 
#define RESAMPLER_FILTER_SIZE   ((RESAMPLER_SAMPLES_PER_ZERO_CROSSING * RESAMPLER_ZERO_CROSSINGS) + 1)
 
#define CASESWAP(b)
 
#define RESAMPLER_FUNCS(chans)
 

Typedefs

typedef int(* SDL_ResampleAudioStreamFunc) (SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen)
 
typedef void(* SDL_ResetAudioStreamResamplerFunc) (SDL_AudioStream *stream)
 
typedef void(* SDL_CleanupAudioStreamResamplerFunc) (SDL_AudioStream *stream)
 

Functions

static void SDL_ConvertStereoToMono (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static void SDL_Convert51ToStereo (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static void SDL_ConvertQuadToStereo (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static void SDL_Convert71To51 (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static void SDL_Convert51ToQuad (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static void SDL_ConvertMonoToStereo (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static void SDL_ConvertStereoTo51 (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static void SDL_ConvertQuadTo51 (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static void SDL_ConvertStereoToQuad (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static void SDL_Convert51To71 (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static double bessel (const double x)
 
static void kaiser_and_sinc (float *table, float *diffs, const int tablelen, const double beta)
 
int SDL_PrepareResampleFilter (void)
 
void SDL_FreeResampleFilter (void)
 
static int ResamplerPadding (const int inrate, const int outrate)
 
static int SDL_ResampleAudio (const int chans, const int inrate, const int outrate, const float *lpadding, const float *rpadding, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
 
int SDL_ConvertAudio (SDL_AudioCVT *cvt)
 
static void SDL_Convert_Byteswap (SDL_AudioCVT *cvt, SDL_AudioFormat format)
 
static int SDL_AddAudioCVTFilter (SDL_AudioCVT *cvt, const SDL_AudioFilter filter)
 
static int SDL_BuildAudioTypeCVTToFloat (SDL_AudioCVT *cvt, const SDL_AudioFormat src_fmt)
 
static int SDL_BuildAudioTypeCVTFromFloat (SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt)
 
static void SDL_ResampleCVT (SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format)
 
static SDL_AudioFilter ChooseCVTResampler (const int dst_channels)
 
static int SDL_BuildAudioResampleCVT (SDL_AudioCVT *cvt, const int dst_channels, const int src_rate, const int dst_rate)
 
static SDL_bool SDL_SupportedAudioFormat (const SDL_AudioFormat fmt)
 
static SDL_bool SDL_SupportedChannelCount (const int channels)
 
int SDL_BuildAudioCVT (SDL_AudioCVT *cvt, SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate, SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
 
static Uint8EnsureStreamBufferSize (SDL_AudioStream *stream, const int newlen)
 
static int SDL_ResampleAudioStream (SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
 
static void SDL_ResetAudioStreamResampler (SDL_AudioStream *stream)
 
static void SDL_CleanupAudioStreamResampler (SDL_AudioStream *stream)
 
SDL_AudioStream * SDL_NewAudioStream (const SDL_AudioFormat src_format, const Uint8 src_channels, const int src_rate, const SDL_AudioFormat dst_format, const Uint8 dst_channels, const int dst_rate)
 
static int SDL_AudioStreamPutInternal (SDL_AudioStream *stream, const void *buf, int len, int *maxputbytes)
 
int SDL_AudioStreamPut (SDL_AudioStream *stream, const void *buf, int len)
 
int SDL_AudioStreamFlush (SDL_AudioStream *stream)
 
int SDL_AudioStreamGet (SDL_AudioStream *stream, void *buf, int len)
 
int SDL_AudioStreamAvailable (SDL_AudioStream *stream)
 
void SDL_AudioStreamClear (SDL_AudioStream *stream)
 
void SDL_FreeAudioStream (SDL_AudioStream *stream)
 

Variables

static SDL_SpinLock ResampleFilterSpinlock = 0
 
static float * ResamplerFilter = NULL
 
static float * ResamplerFilterDifference = NULL
 

Macro Definition Documentation

◆ CASESWAP

#define CASESWAP (   b)
Value:
case b: { \
Uint##b *ptr = (Uint##b *) cvt->buf; \
int i; \
for (i = cvt->len_cvt / sizeof (*ptr); i; --i, ++ptr) { \
*ptr = SDL_Swap##b(*ptr); \
} \
break; \
}
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
GLboolean GLboolean GLboolean b

Referenced by SDL_Convert_Byteswap().

◆ DEBUG_AUDIOSTREAM

#define DEBUG_AUDIOSTREAM   0

Definition at line 37 of file SDL_audiocvt.c.

Referenced by SDL_AudioStreamFlush().

◆ RESAMPLER_BITS_PER_SAMPLE

#define RESAMPLER_BITS_PER_SAMPLE   16

Definition at line 381 of file SDL_audiocvt.c.

◆ RESAMPLER_FILTER_SIZE

#define RESAMPLER_FILTER_SIZE   ((RESAMPLER_SAMPLES_PER_ZERO_CROSSING * RESAMPLER_ZERO_CROSSINGS) + 1)

Definition at line 383 of file SDL_audiocvt.c.

Referenced by SDL_PrepareResampleFilter(), and SDL_ResampleAudio().

◆ RESAMPLER_FUNCS

#define RESAMPLER_FUNCS (   chans)
Value:
static void SDLCALL \
SDL_ResampleCVT_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
SDL_ResampleCVT(cvt, chans, format); \
}
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
A structure to hold a set of audio conversion filters and buffers.
Definition: SDL_audio.h:225
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572

Definition at line 748 of file SDL_audiocvt.c.

◆ RESAMPLER_SAMPLES_PER_ZERO_CROSSING

#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING   (1 << ((RESAMPLER_BITS_PER_SAMPLE / 2) + 1))

Definition at line 382 of file SDL_audiocvt.c.

Referenced by kaiser_and_sinc(), ResamplerPadding(), and SDL_ResampleAudio().

◆ RESAMPLER_ZERO_CROSSINGS

#define RESAMPLER_ZERO_CROSSINGS   5

Definition at line 380 of file SDL_audiocvt.c.

Typedef Documentation

◆ SDL_CleanupAudioStreamResamplerFunc

typedef void(* SDL_CleanupAudioStreamResamplerFunc) (SDL_AudioStream *stream)

Definition at line 1081 of file SDL_audiocvt.c.

◆ SDL_ResampleAudioStreamFunc

typedef int(* SDL_ResampleAudioStreamFunc) (SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen)

Definition at line 1079 of file SDL_audiocvt.c.

◆ SDL_ResetAudioStreamResamplerFunc

typedef void(* SDL_ResetAudioStreamResamplerFunc) (SDL_AudioStream *stream)

Definition at line 1080 of file SDL_audiocvt.c.

Function Documentation

◆ bessel()

static double bessel ( const double  x)
static

Definition at line 387 of file SDL_audiocvt.c.

References e, i, SDL_pow, and SDL_TRUE.

Referenced by kaiser_and_sinc().

388 {
389  const double xdiv2 = x / 2.0;
390  double i0 = 1.0f;
391  double f = 1.0f;
392  int i = 1;
393 
394  while (SDL_TRUE) {
395  const double diff = SDL_pow(xdiv2, i * 2) / SDL_pow(f, 2);
396  if (diff < 1.0e-21f) {
397  break;
398  }
399  i0 += diff;
400  i++;
401  f *= (double) i;
402  }
403 
404  return i0;
405 }
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 Uint32 * e
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
GLfloat f
#define SDL_pow
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

◆ ChooseCVTResampler()

static SDL_AudioFilter ChooseCVTResampler ( const int  dst_channels)
static

Definition at line 761 of file SDL_audiocvt.c.

References NULL.

Referenced by SDL_BuildAudioResampleCVT().

762 {
763  switch (dst_channels) {
764  case 1: return SDL_ResampleCVT_c1;
765  case 2: return SDL_ResampleCVT_c2;
766  case 4: return SDL_ResampleCVT_c4;
767  case 6: return SDL_ResampleCVT_c6;
768  case 8: return SDL_ResampleCVT_c8;
769  default: break;
770  }
771 
772  return NULL;
773 }
#define NULL
Definition: begin_code.h:164

◆ EnsureStreamBufferSize()

static Uint8* EnsureStreamBufferSize ( SDL_AudioStream *  stream,
const int  newlen 
)
static

Definition at line 1114 of file SDL_audiocvt.c.

References NULL, SDL_assert, SDL_FALSE, SDL_OutOfMemory, SDL_realloc, SDL_SetError, SDL_TRUE, and state.

Referenced by SDL_AudioStreamPutInternal().

1115 {
1116  Uint8 *ptr;
1117  size_t offset;
1118 
1119  if (stream->work_buffer_len >= newlen) {
1120  ptr = stream->work_buffer_base;
1121  } else {
1122  ptr = (Uint8 *) SDL_realloc(stream->work_buffer_base, newlen + 32);
1123  if (!ptr) {
1124  SDL_OutOfMemory();
1125  return NULL;
1126  }
1127  /* Make sure we're aligned to 16 bytes for SIMD code. */
1128  stream->work_buffer_base = ptr;
1129  stream->work_buffer_len = newlen;
1130  }
1131 
1132  offset = ((size_t) ptr) & 15;
1133  return offset ? ptr + (16 - offset) : ptr;
1134 }
GLintptr offset
#define SDL_realloc
unsigned int size_t
GLuint GLuint stream
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52

◆ kaiser_and_sinc()

static void kaiser_and_sinc ( float *  table,
float *  diffs,
const int  tablelen,
const double  beta 
)
static

Definition at line 409 of file SDL_audiocvt.c.

References bessel(), i, RESAMPLER_SAMPLES_PER_ZERO_CROSSING, SDL_pow, SDL_sinf, and SDL_sqrt.

Referenced by SDL_PrepareResampleFilter().

410 {
411  const int lenm1 = tablelen - 1;
412  const int lenm1div2 = lenm1 / 2;
413  int i;
414 
415  table[0] = 1.0f;
416  for (i = 1; i < tablelen; i++) {
417  const double kaiser = bessel(beta * SDL_sqrt(1.0 - SDL_pow(((i - lenm1) / 2.0) / lenm1div2, 2.0))) / bessel(beta);
418  table[tablelen - i] = (float) kaiser;
419  }
420 
421  for (i = 1; i < tablelen; i++) {
422  const float x = (((float) i) / ((float) RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) * ((float) M_PI);
423  table[i] *= SDL_sinf(x) / x;
424  diffs[i - 1] = table[i] - table[i - 1];
425  }
426  diffs[lenm1] = 0.0f;
427 }
#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING
Definition: SDL_audiocvt.c:382
GLenum GLsizei GLenum GLenum const void * table
#define SDL_sinf
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
static double bessel(const double x)
Definition: SDL_audiocvt.c:387
#define SDL_pow
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_sqrt

◆ ResamplerPadding()

static int ResamplerPadding ( const int  inrate,
const int  outrate 
)
static

Definition at line 473 of file SDL_audiocvt.c.

References RESAMPLER_SAMPLES_PER_ZERO_CROSSING, and SDL_ceil.

Referenced by SDL_NewAudioStream(), SDL_ResampleAudio(), and SDL_ResampleCVT().

474 {
475  if (inrate == outrate) {
476  return 0;
477  } else if (inrate > outrate) {
478  return (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate)));
479  }
481 }
#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING
Definition: SDL_audiocvt.c:382
#define SDL_ceil

◆ SDL_AddAudioCVTFilter()

static int SDL_AddAudioCVTFilter ( SDL_AudioCVT cvt,
const SDL_AudioFilter  filter 
)
static

Definition at line 601 of file SDL_audiocvt.c.

References SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, NULL, SDL_AUDIOCVT_MAX_FILTERS, and SDL_SetError.

Referenced by SDL_BuildAudioCVT(), SDL_BuildAudioResampleCVT(), SDL_BuildAudioTypeCVTFromFloat(), and SDL_BuildAudioTypeCVTToFloat().

602 {
604  return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS);
605  }
606  if (filter == NULL) {
607  return SDL_SetError("Audio filter pointer is NULL");
608  }
609  cvt->filters[cvt->filter_index++] = filter;
610  cvt->filters[cvt->filter_index] = NULL; /* Moving terminator */
611  return 0;
612 }
#define SDL_AUDIOCVT_MAX_FILTERS
Upper limit of filters in SDL_AudioCVT.
Definition: SDL_audio.h:202
int filter_index
Definition: SDL_audio.h:237
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define NULL
Definition: begin_code.h:164
#define SDL_SetError
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter

◆ SDL_AudioStreamAvailable()

int SDL_AudioStreamAvailable ( SDL_AudioStream *  stream)

Get the number of converted/resampled bytes available. The stream may be buffering data behind the scenes until it has enough to resample correctly, so this number might be lower than what you expect, or even be zero. Add more data or flush the stream if you need the data now.

See also
SDL_NewAudioStream
SDL_AudioStreamPut
SDL_AudioStreamGet
SDL_AudioStreamFlush
SDL_AudioStreamClear
SDL_FreeAudioStream

Definition at line 1636 of file SDL_audiocvt.c.

References SDL_CountDataQueue().

1637 {
1638  return stream ? (int) SDL_CountDataQueue(stream->queue) : 0;
1639 }
GLuint GLuint stream
size_t SDL_CountDataQueue(SDL_DataQueue *queue)

◆ SDL_AudioStreamClear()

void SDL_AudioStreamClear ( SDL_AudioStream *  stream)

Clear any pending data in the stream without converting it

See also
SDL_NewAudioStream
SDL_AudioStreamPut
SDL_AudioStreamGet
SDL_AudioStreamAvailable
SDL_AudioStreamFlush
SDL_FreeAudioStream

Definition at line 1642 of file SDL_audiocvt.c.

References SDL_ClearDataQueue(), SDL_InvalidParamError, and SDL_TRUE.

1643 {
1644  if (!stream) {
1645  SDL_InvalidParamError("stream");
1646  } else {
1647  SDL_ClearDataQueue(stream->queue, stream->packetlen * 2);
1648  if (stream->reset_resampler_func) {
1649  stream->reset_resampler_func(stream);
1650  }
1651  stream->first_run = SDL_TRUE;
1652  stream->staging_buffer_filled = 0;
1653  }
1654 }
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
GLuint GLuint stream
void SDL_ClearDataQueue(SDL_DataQueue *queue, const size_t slack)
Definition: SDL_dataqueue.c:98

◆ SDL_AudioStreamFlush()

int SDL_AudioStreamFlush ( SDL_AudioStream *  stream)

Tell the stream that you're done sending data, and anything being buffered should be converted/resampled and made available immediately.

It is legal to add more data to a stream after flushing, but there will be audio gaps in the output. Generally this is intended to signal the end of input, so the complete output becomes available.

See also
SDL_NewAudioStream
SDL_AudioStreamPut
SDL_AudioStreamGet
SDL_AudioStreamAvailable
SDL_AudioStreamClear
SDL_FreeAudioStream

Definition at line 1561 of file SDL_audiocvt.c.

References DEBUG_AUDIOSTREAM, SDL_AudioStream::first_run, SDL_assert, SDL_AudioStreamPutInternal(), SDL_ceil, SDL_InvalidParamError, SDL_memset, and SDL_TRUE.

1562 {
1563  if (!stream) {
1564  return SDL_InvalidParamError("stream");
1565  }
1566 
1567  #if DEBUG_AUDIOSTREAM
1568  printf("AUDIOSTREAM: flushing! staging_buffer_filled=%d bytes\n", stream->staging_buffer_filled);
1569  #endif
1570 
1571  /* shouldn't use a staging buffer if we're not resampling. */
1572  SDL_assert((stream->dst_rate != stream->src_rate) || (stream->staging_buffer_filled == 0));
1573 
1574  if (stream->staging_buffer_filled > 0) {
1575  /* push the staging buffer + silence. We need to flush out not just
1576  the staging buffer, but the piece that the stream was saving off
1577  for right-side resampler padding. */
1578  const SDL_bool first_run = stream->first_run;
1579  const int filled = stream->staging_buffer_filled;
1580  int actual_input_frames = filled / stream->src_sample_frame_size;
1581  if (!first_run)
1582  actual_input_frames += stream->resampler_padding_samples / stream->pre_resample_channels;
1583 
1584  if (actual_input_frames > 0) { /* don't bother if nothing to flush. */
1585  /* This is how many bytes we're expecting without silence appended. */
1586  int flush_remaining = ((int) SDL_ceil(actual_input_frames * stream->rate_incr)) * stream->dst_sample_frame_size;
1587 
1588  #if DEBUG_AUDIOSTREAM
1589  printf("AUDIOSTREAM: flushing with padding to get max %d bytes!\n", flush_remaining);
1590  #endif
1591 
1592  SDL_memset(stream->staging_buffer + filled, '\0', stream->staging_buffer_size - filled);
1593  if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, &flush_remaining) < 0) {
1594  return -1;
1595  }
1596 
1597  /* we have flushed out (or initially filled) the pending right-side
1598  resampler padding, but we need to push more silence to guarantee
1599  the staging buffer is fully flushed out, too. */
1600  SDL_memset(stream->staging_buffer, '\0', filled);
1601  if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, &flush_remaining) < 0) {
1602  return -1;
1603  }
1604  }
1605  }
1606 
1607  stream->staging_buffer_filled = 0;
1608  stream->first_run = SDL_TRUE;
1609 
1610  return 0;
1611 }
#define SDL_ceil
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
GLuint GLuint stream
static int SDL_AudioStreamPutInternal(SDL_AudioStream *stream, const void *buf, int len, int *maxputbytes)
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_bool
Definition: SDL_stdinc.h:139
#define SDL_memset
#define DEBUG_AUDIOSTREAM
Definition: SDL_audiocvt.c:37

◆ SDL_AudioStreamGet()

int SDL_AudioStreamGet ( SDL_AudioStream *  stream,
void buf,
int  len 
)

Get converted/resampled data from the stream

Parameters
streamThe stream the audio is being requested from
bufA buffer to fill with audio data
lenThe maximum number of bytes to fill
Returns
The number of bytes read from the stream, or -1 on error
See also
SDL_NewAudioStream
SDL_AudioStreamPut
SDL_AudioStreamAvailable
SDL_AudioStreamFlush
SDL_AudioStreamClear
SDL_FreeAudioStream

Definition at line 1615 of file SDL_audiocvt.c.

References SDL_InvalidParamError, SDL_ReadFromDataQueue(), and SDL_SetError.

1616 {
1617  #if DEBUG_AUDIOSTREAM
1618  printf("AUDIOSTREAM: want to get %d converted bytes\n", len);
1619  #endif
1620 
1621  if (!stream) {
1622  return SDL_InvalidParamError("stream");
1623  } else if (!buf) {
1624  return SDL_InvalidParamError("buf");
1625  } else if (len <= 0) {
1626  return 0; /* nothing to do. */
1627  } else if ((len % stream->dst_sample_frame_size) != 0) {
1628  return SDL_SetError("Can't request partial sample frames");
1629  }
1630 
1631  return (int) SDL_ReadFromDataQueue(stream->queue, buf, len);
1632 }
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
GLenum GLsizei len
GLuint GLuint stream
size_t SDL_ReadFromDataQueue(SDL_DataQueue *queue, void *_buf, const size_t _len)
GLenum GLuint GLenum GLsizei const GLchar * buf
#define SDL_SetError

◆ SDL_AudioStreamPut()

int SDL_AudioStreamPut ( SDL_AudioStream *  stream,
const void buf,
int  len 
)

Add data to be converted/resampled to the stream

Parameters
streamThe stream the audio data is being added to
bufA pointer to the audio data to add
lenThe number of bytes to write to the stream
Returns
0 on success, or -1 on error.
See also
SDL_NewAudioStream
SDL_AudioStreamGet
SDL_AudioStreamAvailable
SDL_AudioStreamFlush
SDL_AudioStreamClear
SDL_FreeAudioStream

Definition at line 1497 of file SDL_audiocvt.c.

References NULL, SDL_assert, SDL_AudioStreamPutInternal(), SDL_InvalidParamError, SDL_memcpy, SDL_SetError, and SDL_WriteToDataQueue().

1498 {
1499  /* !!! FIXME: several converters can take advantage of SIMD, but only
1500  !!! FIXME: if the data is aligned to 16 bytes. EnsureStreamBufferSize()
1501  !!! FIXME: guarantees the buffer will align, but the
1502  !!! FIXME: converters will iterate over the data backwards if
1503  !!! FIXME: the output grows, and this means we won't align if buflen
1504  !!! FIXME: isn't a multiple of 16. In these cases, we should chop off
1505  !!! FIXME: a few samples at the end and convert them separately. */
1506 
1507  #if DEBUG_AUDIOSTREAM
1508  printf("AUDIOSTREAM: wants to put %d preconverted bytes\n", buflen);
1509  #endif
1510 
1511  if (!stream) {
1512  return SDL_InvalidParamError("stream");
1513  } else if (!buf) {
1514  return SDL_InvalidParamError("buf");
1515  } else if (len == 0) {
1516  return 0; /* nothing to do. */
1517  } else if ((len % stream->src_sample_frame_size) != 0) {
1518  return SDL_SetError("Can't add partial sample frames");
1519  }
1520 
1521  if (!stream->cvt_before_resampling.needed &&
1522  (stream->dst_rate == stream->src_rate) &&
1523  !stream->cvt_after_resampling.needed) {
1524  #if DEBUG_AUDIOSTREAM
1525  printf("AUDIOSTREAM: no conversion needed at all, queueing %d bytes.\n", len);
1526  #endif
1527  return SDL_WriteToDataQueue(stream->queue, buf, len);
1528  }
1529 
1530  while (len > 0) {
1531  int amount;
1532 
1533  /* If we don't have a staging buffer or we're given enough data that
1534  we don't need to store it for later, skip the staging process.
1535  */
1536  if (!stream->staging_buffer_filled && len >= stream->staging_buffer_size) {
1538  }
1539 
1540  /* If there's not enough data to fill the staging buffer, just save it */
1541  if ((stream->staging_buffer_filled + len) < stream->staging_buffer_size) {
1542  SDL_memcpy(stream->staging_buffer + stream->staging_buffer_filled, buf, len);
1543  stream->staging_buffer_filled += len;
1544  return 0;
1545  }
1546 
1547  /* Fill the staging buffer, process it, and continue */
1548  amount = (stream->staging_buffer_size - stream->staging_buffer_filled);
1549  SDL_assert(amount > 0);
1550  SDL_memcpy(stream->staging_buffer + stream->staging_buffer_filled, buf, amount);
1551  stream->staging_buffer_filled = 0;
1552  if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, NULL) < 0) {
1553  return -1;
1554  }
1555  buf = (void *)((Uint8 *)buf + amount);
1556  len -= amount;
1557  }
1558  return 0;
1559 }
int SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
GLenum GLsizei len
#define SDL_memcpy
GLuint GLuint stream
uint8_t Uint8
Definition: SDL_stdinc.h:157
static int SDL_AudioStreamPutInternal(SDL_AudioStream *stream, const void *buf, int len, int *maxputbytes)
GLenum GLuint GLenum GLsizei const GLchar * buf
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
#define SDL_SetError

◆ SDL_AudioStreamPutInternal()

static int SDL_AudioStreamPutInternal ( SDL_AudioStream *  stream,
const void buf,
int  len,
int *  maxputbytes 
)
static

Definition at line 1368 of file SDL_audiocvt.c.

References EnsureStreamBufferSize(), NULL, SDL_assert, SDL_ceil, SDL_ConvertAudio(), SDL_FALSE, SDL_memcpy, and SDL_WriteToDataQueue().

Referenced by SDL_AudioStreamFlush(), and SDL_AudioStreamPut().

1369 {
1370  int buflen = len;
1371  int workbuflen;
1372  Uint8 *workbuf;
1373  Uint8 *resamplebuf = NULL;
1374  int resamplebuflen = 0;
1375  int neededpaddingbytes;
1376  int paddingbytes;
1377 
1378  /* !!! FIXME: several converters can take advantage of SIMD, but only
1379  !!! FIXME: if the data is aligned to 16 bytes. EnsureStreamBufferSize()
1380  !!! FIXME: guarantees the buffer will align, but the
1381  !!! FIXME: converters will iterate over the data backwards if
1382  !!! FIXME: the output grows, and this means we won't align if buflen
1383  !!! FIXME: isn't a multiple of 16. In these cases, we should chop off
1384  !!! FIXME: a few samples at the end and convert them separately. */
1385 
1386  /* no padding prepended on first run. */
1387  neededpaddingbytes = stream->resampler_padding_samples * sizeof (float);
1388  paddingbytes = stream->first_run ? 0 : neededpaddingbytes;
1389  stream->first_run = SDL_FALSE;
1390 
1391  /* Make sure the work buffer can hold all the data we need at once... */
1392  workbuflen = buflen;
1393  if (stream->cvt_before_resampling.needed) {
1394  workbuflen *= stream->cvt_before_resampling.len_mult;
1395  }
1396 
1397  if (stream->dst_rate != stream->src_rate) {
1398  /* resamples can't happen in place, so make space for second buf. */
1399  const int framesize = stream->pre_resample_channels * sizeof (float);
1400  const int frames = workbuflen / framesize;
1401  resamplebuflen = ((int) SDL_ceil(frames * stream->rate_incr)) * framesize;
1402  #if DEBUG_AUDIOSTREAM
1403  printf("AUDIOSTREAM: will resample %d bytes to %d (ratio=%.6f)\n", workbuflen, resamplebuflen, stream->rate_incr);
1404  #endif
1405  workbuflen += resamplebuflen;
1406  }
1407 
1408  if (stream->cvt_after_resampling.needed) {
1409  /* !!! FIXME: buffer might be big enough already? */
1410  workbuflen *= stream->cvt_after_resampling.len_mult;
1411  }
1412 
1413  workbuflen += neededpaddingbytes;
1414 
1415  #if DEBUG_AUDIOSTREAM
1416  printf("AUDIOSTREAM: Putting %d bytes of preconverted audio, need %d byte work buffer\n", buflen, workbuflen);
1417  #endif
1418 
1419  workbuf = EnsureStreamBufferSize(stream, workbuflen);
1420  if (!workbuf) {
1421  return -1; /* probably out of memory. */
1422  }
1423 
1424  resamplebuf = workbuf; /* default if not resampling. */
1425 
1426  SDL_memcpy(workbuf + paddingbytes, buf, buflen);
1427 
1428  if (stream->cvt_before_resampling.needed) {
1429  stream->cvt_before_resampling.buf = workbuf + paddingbytes;
1430  stream->cvt_before_resampling.len = buflen;
1431  if (SDL_ConvertAudio(&stream->cvt_before_resampling) == -1) {
1432  return -1; /* uhoh! */
1433  }
1434  buflen = stream->cvt_before_resampling.len_cvt;
1435 
1436  #if DEBUG_AUDIOSTREAM
1437  printf("AUDIOSTREAM: After initial conversion we have %d bytes\n", buflen);
1438  #endif
1439  }
1440 
1441  if (stream->dst_rate != stream->src_rate) {
1442  /* save off some samples at the end; they are used for padding now so
1443  the resampler is coherent and then used at the start of the next
1444  put operation. Prepend last put operation's padding, too. */
1445 
1446  /* prepend prior put's padding. :P */
1447  if (paddingbytes) {
1448  SDL_memcpy(workbuf, stream->resampler_padding, paddingbytes);
1449  buflen += paddingbytes;
1450  }
1451 
1452  /* save off the data at the end for the next run. */
1453  SDL_memcpy(stream->resampler_padding, workbuf + (buflen - neededpaddingbytes), neededpaddingbytes);
1454 
1455  resamplebuf = workbuf + buflen; /* skip to second piece of workbuf. */
1456  SDL_assert(buflen >= neededpaddingbytes);
1457  if (buflen > neededpaddingbytes) {
1458  buflen = stream->resampler_func(stream, workbuf, buflen - neededpaddingbytes, resamplebuf, resamplebuflen);
1459  } else {
1460  buflen = 0;
1461  }
1462 
1463  #if DEBUG_AUDIOSTREAM
1464  printf("AUDIOSTREAM: After resampling we have %d bytes\n", buflen);
1465  #endif
1466  }
1467 
1468  if (stream->cvt_after_resampling.needed && (buflen > 0)) {
1469  stream->cvt_after_resampling.buf = resamplebuf;
1470  stream->cvt_after_resampling.len = buflen;
1471  if (SDL_ConvertAudio(&stream->cvt_after_resampling) == -1) {
1472  return -1; /* uhoh! */
1473  }
1474  buflen = stream->cvt_after_resampling.len_cvt;
1475 
1476  #if DEBUG_AUDIOSTREAM
1477  printf("AUDIOSTREAM: After final conversion we have %d bytes\n", buflen);
1478  #endif
1479  }
1480 
1481  #if DEBUG_AUDIOSTREAM
1482  printf("AUDIOSTREAM: Final output is %d bytes\n", buflen);
1483  #endif
1484 
1485  if (maxputbytes) {
1486  const int maxbytes = *maxputbytes;
1487  if (buflen > maxbytes)
1488  buflen = maxbytes;
1489  *maxputbytes -= buflen;
1490  }
1491 
1492  /* resamplebuf holds the final output, even if we didn't resample. */
1493  return buflen ? SDL_WriteToDataQueue(stream->queue, resamplebuf, buflen) : 0;
1494 }
#define SDL_ceil
int SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
static Uint8 * EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen)
GLenum GLsizei len
#define SDL_memcpy
GLuint GLuint stream
uint8_t Uint8
Definition: SDL_stdinc.h:157
int SDL_ConvertAudio(SDL_AudioCVT *cvt)
Definition: SDL_audiocvt.c:540
GLenum GLuint GLenum GLsizei const GLchar * buf
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164

◆ SDL_BuildAudioCVT()

int SDL_BuildAudioCVT ( SDL_AudioCVT cvt,
SDL_AudioFormat  src_format,
Uint8  src_channels,
int  src_rate,
SDL_AudioFormat  dst_format,
Uint8  dst_channels,
int  dst_rate 
)

This function takes a source format and rate and a destination format and rate, and initializes the cvt structure with information needed by SDL_ConvertAudio() to convert a buffer of audio data from one format to the other. An unsupported format causes an error and -1 will be returned.

Returns
0 if no conversion is needed, 1 if the audio filter is set up, or -1 on error.

Definition at line 872 of file SDL_audiocvt.c.

References SDL_AudioCVT::dst_format, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, SDL_AudioCVT::len_mult, SDL_AudioCVT::len_ratio, SDL_AudioCVT::needed, NULL, SDL_AudioCVT::rate_incr, SDL_AddAudioCVTFilter(), SDL_AUDIO_MASK_ENDIAN, SDL_BuildAudioResampleCVT(), SDL_BuildAudioTypeCVTFromFloat(), SDL_BuildAudioTypeCVTToFloat(), SDL_ChooseAudioConverters(), SDL_Convert51To71(), SDL_Convert51ToQuad(), SDL_Convert51ToStereo(), SDL_Convert71To51(), SDL_Convert_Byteswap(), SDL_ConvertMonoToStereo(), SDL_ConvertQuadTo51(), SDL_ConvertQuadToStereo(), SDL_ConvertStereoTo51(), SDL_ConvertStereoToMono(), SDL_ConvertStereoToQuad(), SDL_HasSSE3, SDL_InvalidParamError, SDL_SetError, SDL_SupportedAudioFormat(), SDL_SupportedChannelCount(), SDL_zero, SDL_zerop, and SDL_AudioCVT::src_format.

Referenced by SDL_NewAudioStream().

875 {
876  /* Sanity check target pointer */
877  if (cvt == NULL) {
878  return SDL_InvalidParamError("cvt");
879  }
880 
881  /* Make sure we zero out the audio conversion before error checking */
882  SDL_zerop(cvt);
883 
884  if (!SDL_SupportedAudioFormat(src_fmt)) {
885  return SDL_SetError("Invalid source format");
886  } else if (!SDL_SupportedAudioFormat(dst_fmt)) {
887  return SDL_SetError("Invalid destination format");
888  } else if (!SDL_SupportedChannelCount(src_channels)) {
889  return SDL_SetError("Invalid source channels");
890  } else if (!SDL_SupportedChannelCount(dst_channels)) {
891  return SDL_SetError("Invalid destination channels");
892  } else if (src_rate == 0) {
893  return SDL_SetError("Source rate is zero");
894  } else if (dst_rate == 0) {
895  return SDL_SetError("Destination rate is zero");
896  }
897 
898 #if DEBUG_CONVERT
899  printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
900  src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
901 #endif
902 
903  /* Start off with no conversion necessary */
904  cvt->src_format = src_fmt;
905  cvt->dst_format = dst_fmt;
906  cvt->needed = 0;
907  cvt->filter_index = 0;
908  SDL_zero(cvt->filters);
909  cvt->len_mult = 1;
910  cvt->len_ratio = 1.0;
911  cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
912 
913  /* Make sure we've chosen audio conversion functions (MMX, scalar, etc.) */
915 
916  /* Type conversion goes like this now:
917  - byteswap to CPU native format first if necessary.
918  - convert to native Float32 if necessary.
919  - resample and change channel count if necessary.
920  - convert back to native format.
921  - byteswap back to foreign format if necessary.
922 
923  The expectation is we can process data faster in float32
924  (possibly with SIMD), and making several passes over the same
925  buffer is likely to be CPU cache-friendly, avoiding the
926  biggest performance hit in modern times. Previously we had
927  (script-generated) custom converters for every data type and
928  it was a bloat on SDL compile times and final library size. */
929 
930  /* see if we can skip float conversion entirely. */
931  if (src_rate == dst_rate && src_channels == dst_channels) {
932  if (src_fmt == dst_fmt) {
933  return 0;
934  }
935 
936  /* just a byteswap needed? */
937  if ((src_fmt & ~SDL_AUDIO_MASK_ENDIAN) == (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN)) {
939  return -1;
940  }
941  cvt->needed = 1;
942  return 1;
943  }
944  }
945 
946  /* Convert data types, if necessary. Updates (cvt). */
947  if (SDL_BuildAudioTypeCVTToFloat(cvt, src_fmt) < 0) {
948  return -1; /* shouldn't happen, but just in case... */
949  }
950 
951  /* Channel conversion */
952  if (src_channels < dst_channels) {
953  /* Upmixing */
954  /* Mono -> Stereo [-> ...] */
955  if ((src_channels == 1) && (dst_channels > 1)) {
957  return -1;
958  }
959  cvt->len_mult *= 2;
960  src_channels = 2;
961  cvt->len_ratio *= 2;
962  }
963  /* [Mono ->] Stereo -> 5.1 [-> 7.1] */
964  if ((src_channels == 2) && (dst_channels >= 6)) {
966  return -1;
967  }
968  src_channels = 6;
969  cvt->len_mult *= 3;
970  cvt->len_ratio *= 3;
971  }
972  /* Quad -> 5.1 [-> 7.1] */
973  if ((src_channels == 4) && (dst_channels >= 6)) {
975  return -1;
976  }
977  src_channels = 6;
978  cvt->len_mult = (cvt->len_mult * 3 + 1) / 2;
979  cvt->len_ratio *= 1.5;
980  }
981  /* [[Mono ->] Stereo ->] 5.1 -> 7.1 */
982  if ((src_channels == 6) && (dst_channels == 8)) {
984  return -1;
985  }
986  src_channels = 8;
987  cvt->len_mult = (cvt->len_mult * 4 + 2) / 3;
988  /* Should be numerically exact with every valid input to this
989  function */
990  cvt->len_ratio = cvt->len_ratio * 4 / 3;
991  }
992  /* [Mono ->] Stereo -> Quad */
993  if ((src_channels == 2) && (dst_channels == 4)) {
995  return -1;
996  }
997  src_channels = 4;
998  cvt->len_mult *= 2;
999  cvt->len_ratio *= 2;
1000  }
1001  } else if (src_channels > dst_channels) {
1002  /* Downmixing */
1003  /* 7.1 -> 5.1 [-> Stereo [-> Mono]] */
1004  /* 7.1 -> 5.1 [-> Quad] */
1005  if ((src_channels == 8) && (dst_channels <= 6)) {
1006  if (SDL_AddAudioCVTFilter(cvt, SDL_Convert71To51) < 0) {
1007  return -1;
1008  }
1009  src_channels = 6;
1010  cvt->len_ratio *= 0.75;
1011  }
1012  /* [7.1 ->] 5.1 -> Stereo [-> Mono] */
1013  if ((src_channels == 6) && (dst_channels <= 2)) {
1015  return -1;
1016  }
1017  src_channels = 2;
1018  cvt->len_ratio /= 3;
1019  }
1020  /* 5.1 -> Quad */
1021  if ((src_channels == 6) && (dst_channels == 4)) {
1023  return -1;
1024  }
1025  src_channels = 4;
1026  cvt->len_ratio = cvt->len_ratio * 2 / 3;
1027  }
1028  /* Quad -> Stereo [-> Mono] */
1029  if ((src_channels == 4) && (dst_channels <= 2)) {
1031  return -1;
1032  }
1033  src_channels = 2;
1034  cvt->len_ratio /= 2;
1035  }
1036  /* [... ->] Stereo -> Mono */
1037  if ((src_channels == 2) && (dst_channels == 1)) {
1039 
1040  #if HAVE_SSE3_INTRINSICS
1041  if (SDL_HasSSE3()) {
1042  filter = SDL_ConvertStereoToMono_SSE3;
1043  }
1044  #endif
1045 
1046  if (!filter) {
1047  filter = SDL_ConvertStereoToMono;
1048  }
1049 
1050  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
1051  return -1;
1052  }
1053 
1054  src_channels = 1;
1055  cvt->len_ratio /= 2;
1056  }
1057  }
1058 
1059  if (src_channels != dst_channels) {
1060  /* All combinations of supported channel counts should have been
1061  handled by now, but let's be defensive */
1062  return SDL_SetError("Invalid channel combination");
1063  }
1064 
1065  /* Do rate conversion, if necessary. Updates (cvt). */
1066  if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) < 0) {
1067  return -1; /* shouldn't happen, but just in case... */
1068  }
1069 
1070  /* Move to final data type. */
1071  if (SDL_BuildAudioTypeCVTFromFloat(cvt, dst_fmt) < 0) {
1072  return -1; /* shouldn't happen, but just in case... */
1073  }
1074 
1075  cvt->needed = (cvt->filter_index != 0);
1076  return (cvt->needed);
1077 }
static void SDL_Convert71To51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:151
void SDL_ChooseAudioConverters(void)
int filter_index
Definition: SDL_audio.h:237
static void SDL_Convert51ToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:103
static SDL_bool SDL_SupportedAudioFormat(const SDL_AudioFormat fmt)
Definition: SDL_audiocvt.c:825
double len_ratio
Definition: SDL_audio.h:235
static void SDL_ConvertStereoToQuad(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:305
#define SDL_HasSSE3
static void SDL_Convert51ToQuad(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:181
#define SDL_AUDIO_MASK_ENDIAN
Definition: SDL_audio.h:73
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
static int SDL_BuildAudioTypeCVTToFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat src_fmt)
Definition: SDL_audiocvt.c:615
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
static void SDL_Convert_Byteswap(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:563
static void SDL_Convert51To71(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:335
static int SDL_BuildAudioResampleCVT(SDL_AudioCVT *cvt, const int dst_channels, const int src_rate, const int dst_rate)
Definition: SDL_audiocvt.c:776
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
static void SDL_ConvertQuadToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:128
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_AudioFormat src_format
Definition: SDL_audio.h:228
void(* SDL_AudioFilter)(struct SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audio.h:192
static void SDL_ConvertQuadTo51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:268
#define NULL
Definition: begin_code.h:164
static SDL_bool SDL_SupportedChannelCount(const int channels)
Definition: SDL_audiocvt.c:848
#define SDL_SetError
SDL_AudioFormat dst_format
Definition: SDL_audio.h:229
static void SDL_ConvertMonoToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:210
double rate_incr
Definition: SDL_audio.h:230
static int SDL_AddAudioCVTFilter(SDL_AudioCVT *cvt, const SDL_AudioFilter filter)
Definition: SDL_audiocvt.c:601
static int SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt)
Definition: SDL_audiocvt.c:662
static void SDL_ConvertStereoTo51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:234
static void SDL_ConvertStereoToMono(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:81
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter

◆ SDL_BuildAudioResampleCVT()

static int SDL_BuildAudioResampleCVT ( SDL_AudioCVT cvt,
const int  dst_channels,
const int  src_rate,
const int  dst_rate 
)
static

Definition at line 776 of file SDL_audiocvt.c.

References ChooseCVTResampler(), SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, SDL_AudioCVT::len_mult, SDL_AudioCVT::len_ratio, NULL, SDL_AddAudioCVTFilter(), SDL_AUDIOCVT_MAX_FILTERS, SDL_ceil, SDL_PrepareResampleFilter(), and SDL_SetError.

Referenced by SDL_BuildAudioCVT().

778 {
780 
781  if (src_rate == dst_rate) {
782  return 0; /* no conversion necessary. */
783  }
784 
785  filter = ChooseCVTResampler(dst_channels);
786  if (filter == NULL) {
787  return SDL_SetError("No conversion available for these rates");
788  }
789 
790  if (SDL_PrepareResampleFilter() < 0) {
791  return -1;
792  }
793 
794  /* Update (cvt) with filter details... */
795  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
796  return -1;
797  }
798 
799  /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator).
800  !!! FIXME in 2.1: We need to store data for this resampler, because the cvt structure doesn't store the original sample rates,
801  !!! FIXME in 2.1: so we steal the ninth and tenth slot. :( */
802  if (cvt->filter_index >= (SDL_AUDIOCVT_MAX_FILTERS-2)) {
803  return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS-2);
804  }
805  cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1] = (SDL_AudioFilter) (size_t) src_rate;
806  cvt->filters[SDL_AUDIOCVT_MAX_FILTERS] = (SDL_AudioFilter) (size_t) dst_rate;
807 
808  if (src_rate < dst_rate) {
809  const double mult = ((double) dst_rate) / ((double) src_rate);
810  cvt->len_mult *= (int) SDL_ceil(mult);
811  cvt->len_ratio *= mult;
812  } else {
813  cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
814  }
815 
816  /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
817  /* the buffer is big enough to hold the destination now, but
818  we need it large enough to hold a separate scratch buffer. */
819  cvt->len_mult *= 2;
820 
821  return 1; /* added a converter. */
822 }
static SDL_AudioFilter ChooseCVTResampler(const int dst_channels)
Definition: SDL_audiocvt.c:761
#define SDL_AUDIOCVT_MAX_FILTERS
Upper limit of filters in SDL_AudioCVT.
Definition: SDL_audio.h:202
#define SDL_ceil
int filter_index
Definition: SDL_audio.h:237
double len_ratio
Definition: SDL_audio.h:235
int SDL_PrepareResampleFilter(void)
Definition: SDL_audiocvt.c:435
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
void(* SDL_AudioFilter)(struct SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audio.h:192
#define NULL
Definition: begin_code.h:164
#define SDL_SetError
static int SDL_AddAudioCVTFilter(SDL_AudioCVT *cvt, const SDL_AudioFilter filter)
Definition: SDL_audiocvt.c:601
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter

◆ SDL_BuildAudioTypeCVTFromFloat()

static int SDL_BuildAudioTypeCVTFromFloat ( SDL_AudioCVT cvt,
const SDL_AudioFormat  dst_fmt 
)
static

Definition at line 662 of file SDL_audiocvt.c.

References AUDIO_S16, AUDIO_S32, AUDIO_S8, AUDIO_U16, AUDIO_U8, SDL_AudioCVT::len_mult, SDL_AudioCVT::len_ratio, NULL, retval, SDL_AddAudioCVTFilter(), SDL_assert, SDL_AUDIO_BITSIZE, SDL_AUDIO_ISBIGENDIAN, SDL_AUDIO_ISFLOAT, SDL_AUDIO_MASK_ENDIAN, SDL_BYTEORDER, SDL_Convert_Byteswap(), SDL_Convert_F32_to_S16, SDL_Convert_F32_to_S32, SDL_Convert_F32_to_S8, SDL_Convert_F32_to_U16, SDL_Convert_F32_to_U8, SDL_LIL_ENDIAN, and SDL_SetError.

Referenced by SDL_BuildAudioCVT().

663 {
664  int retval = 0; /* 0 == no conversion necessary. */
665 
666  if (!SDL_AUDIO_ISFLOAT(dst_fmt)) {
667  const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
668  const Uint16 src_bitsize = 32;
670  switch (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN) {
671  case AUDIO_S8: filter = SDL_Convert_F32_to_S8; break;
672  case AUDIO_U8: filter = SDL_Convert_F32_to_U8; break;
673  case AUDIO_S16: filter = SDL_Convert_F32_to_S16; break;
674  case AUDIO_U16: filter = SDL_Convert_F32_to_U16; break;
675  case AUDIO_S32: filter = SDL_Convert_F32_to_S32; break;
676  default: SDL_assert(!"Unexpected audio format!"); break;
677  }
678 
679  if (!filter) {
680  return SDL_SetError("No conversion from float to destination format available");
681  }
682 
683  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
684  return -1;
685  }
686  if (src_bitsize < dst_bitsize) {
687  const int mult = (dst_bitsize / src_bitsize);
688  cvt->len_mult *= mult;
689  cvt->len_ratio *= mult;
690  } else if (src_bitsize > dst_bitsize) {
691  cvt->len_ratio /= (src_bitsize / dst_bitsize);
692  }
693  retval = 1; /* added a converter. */
694  }
695 
696  if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
698  return -1;
699  }
700  retval = 1; /* added a converter. */
701  }
702 
703  return retval;
704 }
#define SDL_AUDIO_ISBIGENDIAN(x)
Definition: SDL_audio.h:77
SDL_AudioFilter SDL_Convert_F32_to_S32
double len_ratio
Definition: SDL_audio.h:235
#define SDL_LIL_ENDIAN
Definition: SDL_endian.h:37
#define SDL_AUDIO_MASK_ENDIAN
Definition: SDL_audio.h:73
static void SDL_Convert_Byteswap(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:563
#define SDL_AUDIO_ISFLOAT(x)
Definition: SDL_audio.h:76
SDL_bool retval
#define AUDIO_U8
Definition: SDL_audio.h:89
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
#define AUDIO_S32
Definition: SDL_audio.h:105
SDL_AudioFilter SDL_Convert_F32_to_S8
SDL_AudioFilter SDL_Convert_F32_to_U8
void(* SDL_AudioFilter)(struct SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audio.h:192
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
#define SDL_SetError
SDL_AudioFilter SDL_Convert_F32_to_U16
#define AUDIO_S16
Definition: SDL_audio.h:96
static int SDL_AddAudioCVTFilter(SDL_AudioCVT *cvt, const SDL_AudioFilter filter)
Definition: SDL_audiocvt.c:601
uint16_t Uint16
Definition: SDL_stdinc.h:169
#define AUDIO_U16
Definition: SDL_audio.h:95
#define AUDIO_S8
Definition: SDL_audio.h:90
#define SDL_BYTEORDER
SDL_AudioFilter SDL_Convert_F32_to_S16
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter

◆ SDL_BuildAudioTypeCVTToFloat()

static int SDL_BuildAudioTypeCVTToFloat ( SDL_AudioCVT cvt,
const SDL_AudioFormat  src_fmt 
)
static

Definition at line 615 of file SDL_audiocvt.c.

References AUDIO_S16, AUDIO_S32, AUDIO_S8, AUDIO_U16, AUDIO_U8, SDL_AudioCVT::len_mult, SDL_AudioCVT::len_ratio, NULL, retval, SDL_AddAudioCVTFilter(), SDL_assert, SDL_AUDIO_BITSIZE, SDL_AUDIO_ISBIGENDIAN, SDL_AUDIO_ISFLOAT, SDL_AUDIO_MASK_ENDIAN, SDL_BYTEORDER, SDL_Convert_Byteswap(), SDL_Convert_S16_to_F32, SDL_Convert_S32_to_F32, SDL_Convert_S8_to_F32, SDL_Convert_U16_to_F32, SDL_Convert_U8_to_F32, SDL_LIL_ENDIAN, and SDL_SetError.

Referenced by SDL_BuildAudioCVT().

616 {
617  int retval = 0; /* 0 == no conversion necessary. */
618 
619  if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
621  return -1;
622  }
623  retval = 1; /* added a converter. */
624  }
625 
626  if (!SDL_AUDIO_ISFLOAT(src_fmt)) {
627  const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
628  const Uint16 dst_bitsize = 32;
630 
631  switch (src_fmt & ~SDL_AUDIO_MASK_ENDIAN) {
632  case AUDIO_S8: filter = SDL_Convert_S8_to_F32; break;
633  case AUDIO_U8: filter = SDL_Convert_U8_to_F32; break;
634  case AUDIO_S16: filter = SDL_Convert_S16_to_F32; break;
635  case AUDIO_U16: filter = SDL_Convert_U16_to_F32; break;
636  case AUDIO_S32: filter = SDL_Convert_S32_to_F32; break;
637  default: SDL_assert(!"Unexpected audio format!"); break;
638  }
639 
640  if (!filter) {
641  return SDL_SetError("No conversion from source format to float available");
642  }
643 
644  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
645  return -1;
646  }
647  if (src_bitsize < dst_bitsize) {
648  const int mult = (dst_bitsize / src_bitsize);
649  cvt->len_mult *= mult;
650  cvt->len_ratio *= mult;
651  } else if (src_bitsize > dst_bitsize) {
652  cvt->len_ratio /= (src_bitsize / dst_bitsize);
653  }
654 
655  retval = 1; /* added a converter. */
656  }
657 
658  return retval;
659 }
#define SDL_AUDIO_ISBIGENDIAN(x)
Definition: SDL_audio.h:77
double len_ratio
Definition: SDL_audio.h:235
SDL_AudioFilter SDL_Convert_S16_to_F32
SDL_AudioFilter SDL_Convert_U16_to_F32
#define SDL_LIL_ENDIAN
Definition: SDL_endian.h:37
#define SDL_AUDIO_MASK_ENDIAN
Definition: SDL_audio.h:73
static void SDL_Convert_Byteswap(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:563
#define SDL_AUDIO_ISFLOAT(x)
Definition: SDL_audio.h:76
SDL_bool retval
#define AUDIO_U8
Definition: SDL_audio.h:89
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
#define AUDIO_S32
Definition: SDL_audio.h:105
void(* SDL_AudioFilter)(struct SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audio.h:192
SDL_AudioFilter SDL_Convert_S8_to_F32
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_AudioFilter SDL_Convert_U8_to_F32
#define NULL
Definition: begin_code.h:164
#define SDL_SetError
#define AUDIO_S16
Definition: SDL_audio.h:96
static int SDL_AddAudioCVTFilter(SDL_AudioCVT *cvt, const SDL_AudioFilter filter)
Definition: SDL_audiocvt.c:601
uint16_t Uint16
Definition: SDL_stdinc.h:169
#define AUDIO_U16
Definition: SDL_audio.h:95
SDL_AudioFilter SDL_Convert_S32_to_F32
#define AUDIO_S8
Definition: SDL_audio.h:90
#define SDL_BYTEORDER
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter

◆ SDL_CleanupAudioStreamResampler()

static void SDL_CleanupAudioStreamResampler ( SDL_AudioStream *  stream)
static

Definition at line 1253 of file SDL_audiocvt.c.

References SDL_free.

Referenced by SDL_NewAudioStream().

1254 {
1255  SDL_free(stream->resampler_state);
1256 }
GLuint GLuint stream
#define SDL_free

◆ SDL_Convert51To71()

static void SDL_Convert51To71 ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 335 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, i, SDL_AudioCVT::len_cvt, LOG_DEBUG_CONVERT, and SDL_assert.

Referenced by SDL_BuildAudioCVT().

336 {
337  float lf, rf, lb, rb, ls, rs;
338  int i;
339  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
340  float *dst = (float *) (cvt->buf + cvt->len_cvt * 4 / 3);
341 
342  LOG_DEBUG_CONVERT("5.1", "7.1");
344  SDL_assert(cvt->len_cvt % (sizeof(float) * 6) == 0);
345 
346  for (i = cvt->len_cvt / (sizeof(float) * 6); i; --i) {
347  dst -= 8;
348  src -= 6;
349  lf = src[0];
350  rf = src[1];
351  lb = src[4];
352  rb = src[5];
353  ls = (lf + lb) * 0.5f;
354  rs = (rf + rb) * 0.5f;
355  /* !!! FIXME: these four may clip */
356  lf += lf - ls;
357  rf += rf - ls;
358  lb += lb - ls;
359  rb += rb - ls;
360  dst[3] = src[3]; /* LFE */
361  dst[2] = src[2]; /* FC */
362  dst[7] = rs; /* SR */
363  dst[6] = ls; /* SL */
364  dst[5] = rb; /* BR */
365  dst[4] = lb; /* BL */
366  dst[1] = rf; /* FR */
367  dst[0] = lf; /* FL */
368  }
369 
370  cvt->len_cvt = cvt->len_cvt * 4 / 3;
371 
372  if (cvt->filters[++cvt->filter_index]) {
373  cvt->filters[cvt->filter_index] (cvt, format);
374  }
375 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLfloat f
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
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_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_Convert51ToQuad()

static void SDL_Convert51ToQuad ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 181 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, i, SDL_AudioCVT::len_cvt, LOG_DEBUG_CONVERT, SDL_assert, and SDLCALL.

Referenced by SDL_BuildAudioCVT().

182 {
183  float *dst = (float *) cvt->buf;
184  const float *src = dst;
185  int i;
186 
187  LOG_DEBUG_CONVERT("5.1", "quad");
189 
190  /* SDL's 4.0 layout: FL+FR+BL+BR */
191  /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */
192  for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 4) {
193  const float front_center_distributed = src[2] * 0.5f;
194  dst[0] = (src[0] + front_center_distributed) / 1.5f; /* FL */
195  dst[1] = (src[1] + front_center_distributed) / 1.5f; /* FR */
196  dst[2] = src[4] / 1.5f; /* BL */
197  dst[3] = src[5] / 1.5f; /* BR */
198  }
199 
200  cvt->len_cvt /= 6;
201  cvt->len_cvt *= 4;
202  if (cvt->filters[++cvt->filter_index]) {
203  cvt->filters[cvt->filter_index] (cvt, format);
204  }
205 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLfloat f
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
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_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_Convert51ToStereo()

static void SDL_Convert51ToStereo ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 103 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, i, SDL_AudioCVT::len_cvt, LOG_DEBUG_CONVERT, SDL_assert, and SDLCALL.

Referenced by SDL_BuildAudioCVT().

104 {
105  float *dst = (float *) cvt->buf;
106  const float *src = dst;
107  int i;
108 
109  LOG_DEBUG_CONVERT("5.1", "stereo");
111 
112  /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */
113  for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 2) {
114  const float front_center_distributed = src[2] * 0.5f;
115  dst[0] = (src[0] + front_center_distributed + src[4]) / 2.5f; /* left */
116  dst[1] = (src[1] + front_center_distributed + src[5]) / 2.5f; /* right */
117  }
118 
119  cvt->len_cvt /= 3;
120  if (cvt->filters[++cvt->filter_index]) {
121  cvt->filters[cvt->filter_index] (cvt, format);
122  }
123 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLfloat f
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
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_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_Convert71To51()

static void SDL_Convert71To51 ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 151 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, i, SDL_AudioCVT::len_cvt, LOG_DEBUG_CONVERT, SDL_assert, and SDLCALL.

Referenced by SDL_BuildAudioCVT().

152 {
153  float *dst = (float *) cvt->buf;
154  const float *src = dst;
155  int i;
156 
157  LOG_DEBUG_CONVERT("7.1", "5.1");
159 
160  for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8, dst += 6) {
161  const float surround_left_distributed = src[6] * 0.5f;
162  const float surround_right_distributed = src[7] * 0.5f;
163  dst[0] = (src[0] + surround_left_distributed) / 1.5f; /* FL */
164  dst[1] = (src[1] + surround_right_distributed) / 1.5f; /* FR */
165  dst[2] = src[2] / 1.5f; /* CC */
166  dst[3] = src[3] / 1.5f; /* LFE */
167  dst[4] = (src[4] + surround_left_distributed) / 1.5f; /* BL */
168  dst[5] = (src[5] + surround_right_distributed) / 1.5f; /* BR */
169  }
170 
171  cvt->len_cvt /= 8;
172  cvt->len_cvt *= 6;
173  if (cvt->filters[++cvt->filter_index]) {
174  cvt->filters[cvt->filter_index] (cvt, format);
175  }
176 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLfloat f
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
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_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_Convert_Byteswap()

static void SDL_Convert_Byteswap ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 563 of file SDL_audiocvt.c.

References CASESWAP, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, SDL_assert, SDL_AUDIO_BITSIZE, and SDL_AUDIO_MASK_ENDIAN.

Referenced by SDL_BuildAudioCVT(), SDL_BuildAudioTypeCVTFromFloat(), and SDL_BuildAudioTypeCVTToFloat().

564 {
565 #if DEBUG_CONVERT
566  printf("Converting byte order\n");
567 #endif
568 
569  switch (SDL_AUDIO_BITSIZE(format)) {
570  #define CASESWAP(b) \
571  case b: { \
572  Uint##b *ptr = (Uint##b *) cvt->buf; \
573  int i; \
574  for (i = cvt->len_cvt / sizeof (*ptr); i; --i, ++ptr) { \
575  *ptr = SDL_Swap##b(*ptr); \
576  } \
577  break; \
578  }
579 
580  CASESWAP(16);
581  CASESWAP(32);
582  CASESWAP(64);
583 
584  #undef CASESWAP
585 
586  default: SDL_assert(!"unhandled byteswap datatype!"); break;
587  }
588 
589  if (cvt->filters[++cvt->filter_index]) {
590  /* flip endian flag for data. */
592  format &= ~SDL_AUDIO_MASK_ENDIAN;
593  } else {
595  }
596  cvt->filters[cvt->filter_index](cvt, format);
597  }
598 }
int filter_index
Definition: SDL_audio.h:237
#define CASESWAP(b)
#define SDL_AUDIO_MASK_ENDIAN
Definition: SDL_audio.h:73
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
#define SDL_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_ConvertAudio()

int SDL_ConvertAudio ( SDL_AudioCVT cvt)

Once you have initialized the cvt structure using SDL_BuildAudioCVT(), created an audio buffer cvt->buf, and filled it with cvt->len bytes of audio data in the source format, this function will convert it in-place to the desired format.

The data conversion may expand the size of the audio data, so the buffer cvt->buf should be allocated after the cvt structure is initialized by SDL_BuildAudioCVT(), and should be cvt->len*cvt->len_mult bytes long.

Returns
0 on success or -1 if cvt->buf is NULL.

Definition at line 540 of file SDL_audiocvt.c.

References SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, SDL_AudioCVT::len, SDL_AudioCVT::len_cvt, NULL, SDL_SetError, SDLCALL, and SDL_AudioCVT::src_format.

Referenced by SDL_AudioStreamPutInternal().

541 {
542  /* !!! FIXME: (cvt) should be const; stack-copy it here. */
543  /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
544 
545  /* Make sure there's data to convert */
546  if (cvt->buf == NULL) {
547  return SDL_SetError("No buffer allocated for conversion");
548  }
549 
550  /* Return okay if no conversion is necessary */
551  cvt->len_cvt = cvt->len;
552  if (cvt->filters[0] == NULL) {
553  return 0;
554  }
555 
556  /* Set up the conversion and go! */
557  cvt->filter_index = 0;
558  cvt->filters[0] (cvt, cvt->src_format);
559  return 0;
560 }
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
SDL_AudioFormat src_format
Definition: SDL_audio.h:228
#define NULL
Definition: begin_code.h:164
#define SDL_SetError

◆ SDL_ConvertMonoToStereo()

static void SDL_ConvertMonoToStereo ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 210 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, i, SDL_AudioCVT::len_cvt, LOG_DEBUG_CONVERT, SDL_assert, and SDLCALL.

Referenced by SDL_BuildAudioCVT().

211 {
212  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
213  float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
214  int i;
215 
216  LOG_DEBUG_CONVERT("mono", "stereo");
218 
219  for (i = cvt->len_cvt / sizeof (float); i; --i) {
220  src--;
221  dst -= 2;
222  dst[0] = dst[1] = *src;
223  }
224 
225  cvt->len_cvt *= 2;
226  if (cvt->filters[++cvt->filter_index]) {
227  cvt->filters[cvt->filter_index] (cvt, format);
228  }
229 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
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_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_ConvertQuadTo51()

static void SDL_ConvertQuadTo51 ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 268 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, i, SDL_AudioCVT::len_cvt, LOG_DEBUG_CONVERT, SDL_assert, and SDLCALL.

Referenced by SDL_BuildAudioCVT().

269 {
270  int i;
271  float lf, rf, lb, rb, ce;
272  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
273  float *dst = (float *) (cvt->buf + cvt->len_cvt * 3 / 2);
274 
275  LOG_DEBUG_CONVERT("quad", "5.1");
277  SDL_assert(cvt->len_cvt % (sizeof(float) * 4) == 0);
278 
279  for (i = cvt->len_cvt / (sizeof(float) * 4); i; --i) {
280  dst -= 6;
281  src -= 4;
282  lf = src[0];
283  rf = src[1];
284  lb = src[2];
285  rb = src[3];
286  ce = (lf + rf) * 0.5f;
287  /* !!! FIXME: FL and FR may clip */
288  dst[0] = lf + (lf - ce); /* FL */
289  dst[1] = rf + (rf - ce); /* FR */
290  dst[2] = ce; /* FC */
291  dst[3] = 0; /* LFE (only meant for special LFE effects) */
292  dst[4] = lb; /* BL */
293  dst[5] = rb; /* BR */
294  }
295 
296  cvt->len_cvt = cvt->len_cvt * 3 / 2;
297  if (cvt->filters[++cvt->filter_index]) {
298  cvt->filters[cvt->filter_index] (cvt, format);
299  }
300 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLfloat f
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
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_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_ConvertQuadToStereo()

static void SDL_ConvertQuadToStereo ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 128 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, i, SDL_AudioCVT::len_cvt, LOG_DEBUG_CONVERT, SDL_assert, and SDLCALL.

Referenced by SDL_BuildAudioCVT().

129 {
130  float *dst = (float *) cvt->buf;
131  const float *src = dst;
132  int i;
133 
134  LOG_DEBUG_CONVERT("quad", "stereo");
136 
137  for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src += 4, dst += 2) {
138  dst[0] = (src[0] + src[2]) * 0.5f; /* left */
139  dst[1] = (src[1] + src[3]) * 0.5f; /* right */
140  }
141 
142  cvt->len_cvt /= 2;
143  if (cvt->filters[++cvt->filter_index]) {
144  cvt->filters[cvt->filter_index] (cvt, format);
145  }
146 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLfloat f
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
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_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_ConvertStereoTo51()

static void SDL_ConvertStereoTo51 ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 234 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, i, SDL_AudioCVT::len_cvt, LOG_DEBUG_CONVERT, SDL_assert, and SDLCALL.

Referenced by SDL_BuildAudioCVT().

235 {
236  int i;
237  float lf, rf, ce;
238  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
239  float *dst = (float *) (cvt->buf + cvt->len_cvt * 3);
240 
241  LOG_DEBUG_CONVERT("stereo", "5.1");
243 
244  for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) {
245  dst -= 6;
246  src -= 2;
247  lf = src[0];
248  rf = src[1];
249  ce = (lf + rf) * 0.5f;
250  /* !!! FIXME: FL and FR may clip */
251  dst[0] = lf + (lf - ce); /* FL */
252  dst[1] = rf + (rf - ce); /* FR */
253  dst[2] = ce; /* FC */
254  dst[3] = 0; /* LFE (only meant for special LFE effects) */
255  dst[4] = lf; /* BL */
256  dst[5] = rf; /* BR */
257  }
258 
259  cvt->len_cvt *= 3;
260  if (cvt->filters[++cvt->filter_index]) {
261  cvt->filters[cvt->filter_index] (cvt, format);
262  }
263 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLfloat f
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
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_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_ConvertStereoToMono()

static void SDL_ConvertStereoToMono ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 81 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, i, SDL_AudioCVT::len_cvt, LOG_DEBUG_CONVERT, SDL_assert, and SDLCALL.

Referenced by SDL_BuildAudioCVT().

82 {
83  float *dst = (float *) cvt->buf;
84  const float *src = dst;
85  int i;
86 
87  LOG_DEBUG_CONVERT("stereo", "mono");
89 
90  for (i = cvt->len_cvt / 8; i; --i, src += 2) {
91  *(dst++) = (src[0] + src[1]) * 0.5f;
92  }
93 
94  cvt->len_cvt /= 2;
95  if (cvt->filters[++cvt->filter_index]) {
96  cvt->filters[cvt->filter_index] (cvt, format);
97  }
98 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
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_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_ConvertStereoToQuad()

static void SDL_ConvertStereoToQuad ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 305 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, i, SDL_AudioCVT::len_cvt, LOG_DEBUG_CONVERT, SDL_assert, and SDLCALL.

Referenced by SDL_BuildAudioCVT().

306 {
307  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
308  float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
309  float lf, rf;
310  int i;
311 
312  LOG_DEBUG_CONVERT("stereo", "quad");
314 
315  for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) {
316  dst -= 4;
317  src -= 2;
318  lf = src[0];
319  rf = src[1];
320  dst[0] = lf; /* FL */
321  dst[1] = rf; /* FR */
322  dst[2] = lf; /* BL */
323  dst[3] = rf; /* BR */
324  }
325 
326  cvt->len_cvt *= 2;
327  if (cvt->filters[++cvt->filter_index]) {
328  cvt->filters[cvt->filter_index] (cvt, format);
329  }
330 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
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_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_FreeAudioStream()

void SDL_FreeAudioStream ( SDL_AudioStream *  stream)

Free an audio stream

See also
SDL_NewAudioStream
SDL_AudioStreamPut
SDL_AudioStreamGet
SDL_AudioStreamAvailable
SDL_AudioStreamFlush
SDL_AudioStreamClear

Definition at line 1658 of file SDL_audiocvt.c.

References SDL_free, and SDL_FreeDataQueue().

Referenced by SDL_NewAudioStream().

1659 {
1660  if (stream) {
1661  if (stream->cleanup_resampler_func) {
1662  stream->cleanup_resampler_func(stream);
1663  }
1664  SDL_FreeDataQueue(stream->queue);
1665  SDL_free(stream->staging_buffer);
1666  SDL_free(stream->work_buffer_base);
1667  SDL_free(stream->resampler_padding);
1668  SDL_free(stream);
1669  }
1670 }
GLuint GLuint stream
#define SDL_free
void SDL_FreeDataQueue(SDL_DataQueue *queue)
Definition: SDL_dataqueue.c:88

◆ SDL_FreeResampleFilter()

void SDL_FreeResampleFilter ( void  )

Definition at line 464 of file SDL_audiocvt.c.

References NULL, ResamplerFilter, ResamplerFilterDifference, and SDL_free.

Referenced by SDL_AudioQuit().

465 {
470 }
static float * ResamplerFilter
Definition: SDL_audiocvt.c:431
static float * ResamplerFilterDifference
Definition: SDL_audiocvt.c:432
#define SDL_free
#define NULL
Definition: begin_code.h:164

◆ SDL_NewAudioStream()

SDL_AudioStream* SDL_NewAudioStream ( const SDL_AudioFormat  src_format,
const Uint8  src_channels,
const int  src_rate,
const SDL_AudioFormat  dst_format,
const Uint8  dst_channels,
const int  dst_rate 
)

Create a new audio stream

Parameters
src_formatThe format of the source audio
src_channelsThe number of channels of the source audio
src_rateThe sampling rate of the source audio
dst_formatThe format of the desired audio output
dst_channelsThe number of channels of the desired audio output
dst_rateThe sampling rate of the desired audio output
Returns
0 on success, or -1 on error.
See also
SDL_AudioStreamPut
SDL_AudioStreamGet
SDL_AudioStreamAvailable
SDL_AudioStreamFlush
SDL_AudioStreamClear
SDL_FreeAudioStream

Definition at line 1259 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioStream::dst_channels, SDL_AudioStream::dst_format, SDL_AudioStream::dst_rate, NULL, SDL_AudioStream::packetlen, SDL_AudioStream::pre_resample_channels, ResamplerPadding(), retval, SDL_AUDIO_BITSIZE, SDL_BuildAudioCVT(), SDL_calloc, SDL_CleanupAudioStreamResampler(), SDL_FALSE, SDL_free, SDL_FreeAudioStream(), SDL_malloc, SDL_min, SDL_NewDataQueue(), SDL_OutOfMemory, SDL_PrepareResampleFilter(), SDL_ResampleAudioStream(), SDL_ResetAudioStreamResampler(), SDL_TRUE, SDL_AudioStream::src_channels, SDL_AudioStream::src_format, and SDL_AudioStream::src_rate.

1265 {
1266  const int packetlen = 4096; /* !!! FIXME: good enough for now. */
1267  Uint8 pre_resample_channels;
1268  SDL_AudioStream *retval;
1269 
1270  retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream));
1271  if (!retval) {
1272  return NULL;
1273  }
1274 
1275  /* If increasing channels, do it after resampling, since we'd just
1276  do more work to resample duplicate channels. If we're decreasing, do
1277  it first so we resample the interpolated data instead of interpolating
1278  the resampled data (!!! FIXME: decide if that works in practice, though!). */
1279  pre_resample_channels = SDL_min(src_channels, dst_channels);
1280 
1281  retval->first_run = SDL_TRUE;
1282  retval->src_sample_frame_size = (SDL_AUDIO_BITSIZE(src_format) / 8) * src_channels;
1283  retval->src_format = src_format;
1284  retval->src_channels = src_channels;
1285  retval->src_rate = src_rate;
1286  retval->dst_sample_frame_size = (SDL_AUDIO_BITSIZE(dst_format) / 8) * dst_channels;
1287  retval->dst_format = dst_format;
1288  retval->dst_channels = dst_channels;
1289  retval->dst_rate = dst_rate;
1290  retval->pre_resample_channels = pre_resample_channels;
1291  retval->packetlen = packetlen;
1292  retval->rate_incr = ((double) dst_rate) / ((double) src_rate);
1293  retval->resampler_padding_samples = ResamplerPadding(retval->src_rate, retval->dst_rate) * pre_resample_channels;
1294  retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples, sizeof (float));
1295 
1296  if (retval->resampler_padding == NULL) {
1297  SDL_FreeAudioStream(retval);
1298  SDL_OutOfMemory();
1299  return NULL;
1300  }
1301 
1302  retval->staging_buffer_size = ((retval->resampler_padding_samples / retval->pre_resample_channels) * retval->src_sample_frame_size);
1303  if (retval->staging_buffer_size > 0) {
1304  retval->staging_buffer = (Uint8 *) SDL_malloc(retval->staging_buffer_size);
1305  if (retval->staging_buffer == NULL) {
1306  SDL_FreeAudioStream(retval);
1307  SDL_OutOfMemory();
1308  return NULL;
1309  }
1310  }
1311 
1312  /* Not resampling? It's an easy conversion (and maybe not even that!) */
1313  if (src_rate == dst_rate) {
1314  retval->cvt_before_resampling.needed = SDL_FALSE;
1315  if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, src_format, src_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) {
1316  SDL_FreeAudioStream(retval);
1317  return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */
1318  }
1319  } else {
1320  /* Don't resample at first. Just get us to Float32 format. */
1321  /* !!! FIXME: convert to int32 on devices without hardware float. */
1322  if (SDL_BuildAudioCVT(&retval->cvt_before_resampling, src_format, src_channels, src_rate, AUDIO_F32SYS, pre_resample_channels, src_rate) < 0) {
1323  SDL_FreeAudioStream(retval);
1324  return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */
1325  }
1326 
1327 #ifdef HAVE_LIBSAMPLERATE_H
1328  SetupLibSampleRateResampling(retval);
1329 #endif
1330 
1331  if (!retval->resampler_func) {
1332  retval->resampler_state = SDL_calloc(retval->resampler_padding_samples, sizeof (float));
1333  if (!retval->resampler_state) {
1334  SDL_FreeAudioStream(retval);
1335  SDL_OutOfMemory();
1336  return NULL;
1337  }
1338 
1339  if (SDL_PrepareResampleFilter() < 0) {
1340  SDL_free(retval->resampler_state);
1341  retval->resampler_state = NULL;
1342  SDL_FreeAudioStream(retval);
1343  return NULL;
1344  }
1345 
1346  retval->resampler_func = SDL_ResampleAudioStream;
1347  retval->reset_resampler_func = SDL_ResetAudioStreamResampler;
1348  retval->cleanup_resampler_func = SDL_CleanupAudioStreamResampler;
1349  }
1350 
1351  /* Convert us to the final format after resampling. */
1352  if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, AUDIO_F32SYS, pre_resample_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) {
1353  SDL_FreeAudioStream(retval);
1354  return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */
1355  }
1356  }
1357 
1358  retval->queue = SDL_NewDataQueue(packetlen, packetlen * 2);
1359  if (!retval->queue) {
1360  SDL_FreeAudioStream(retval);
1361  return NULL; /* SDL_NewDataQueue should have called SDL_SetError. */
1362  }
1363 
1364  return retval;
1365 }
static int ResamplerPadding(const int inrate, const int outrate)
Definition: SDL_audiocvt.c:473
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
SDL_DataQueue * SDL_NewDataQueue(const size_t _packetlen, const size_t initialslack)
Definition: SDL_dataqueue.c:58
void SDL_FreeAudioStream(SDL_AudioStream *stream)
SDL_bool retval
static void SDL_ResetAudioStreamResampler(SDL_AudioStream *stream)
int SDL_PrepareResampleFilter(void)
Definition: SDL_audiocvt.c:435
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
static int SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
int SDL_BuildAudioCVT(SDL_AudioCVT *cvt, SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate, SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
Definition: SDL_audiocvt.c:872
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_calloc
static void SDL_CleanupAudioStreamResampler(SDL_AudioStream *stream)
#define SDL_malloc

◆ SDL_PrepareResampleFilter()

int SDL_PrepareResampleFilter ( void  )

Definition at line 435 of file SDL_audiocvt.c.

References kaiser_and_sinc(), NULL, ResampleFilterSpinlock, RESAMPLER_FILTER_SIZE, ResamplerFilter, ResamplerFilterDifference, SDL_AtomicLock, SDL_AtomicUnlock, SDL_free, SDL_malloc, and SDL_OutOfMemory.

Referenced by SDL_BuildAudioResampleCVT(), and SDL_NewAudioStream().

436 {
438  if (!ResamplerFilter) {
439  /* if dB > 50, beta=(0.1102 * (dB - 8.7)), according to Matlab. */
440  const double dB = 80.0;
441  const double beta = 0.1102 * (dB - 8.7);
442  const size_t alloclen = RESAMPLER_FILTER_SIZE * sizeof (float);
443 
444  ResamplerFilter = (float *) SDL_malloc(alloclen);
445  if (!ResamplerFilter) {
447  return SDL_OutOfMemory();
448  }
449 
450  ResamplerFilterDifference = (float *) SDL_malloc(alloclen);
455  return SDL_OutOfMemory();
456  }
458  }
460  return 0;
461 }
#define SDL_AtomicLock
static SDL_SpinLock ResampleFilterSpinlock
Definition: SDL_audiocvt.c:430
static float * ResamplerFilter
Definition: SDL_audiocvt.c:431
static void kaiser_and_sinc(float *table, float *diffs, const int tablelen, const double beta)
Definition: SDL_audiocvt.c:409
static float * ResamplerFilterDifference
Definition: SDL_audiocvt.c:432
#define SDL_AtomicUnlock
#define SDL_free
#define RESAMPLER_FILTER_SIZE
Definition: SDL_audiocvt.c:383
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_malloc

◆ SDL_ResampleAudio()

static int SDL_ResampleAudio ( const int  chans,
const int  inrate,
const int  outrate,
const float *  lpadding,
const float *  rpadding,
const float *  inbuf,
const int  inbuflen,
float *  outbuf,
const int  outbuflen 
)
static

Definition at line 485 of file SDL_audiocvt.c.

References i, j, RESAMPLER_FILTER_SIZE, RESAMPLER_SAMPLES_PER_ZERO_CROSSING, ResamplerFilter, ResamplerFilterDifference, ResamplerPadding(), and SDL_min.

Referenced by SDL_ResampleAudioStream(), and SDL_ResampleCVT().

489 {
490  const double finrate = (double) inrate;
491  const double outtimeincr = 1.0 / ((float) outrate);
492  const double ratio = ((float) outrate) / ((float) inrate);
493  const int paddinglen = ResamplerPadding(inrate, outrate);
494  const int framelen = chans * (int)sizeof (float);
495  const int inframes = inbuflen / framelen;
496  const int wantedoutframes = (int) ((inbuflen / framelen) * ratio); /* outbuflen isn't total to write, it's total available. */
497  const int maxoutframes = outbuflen / framelen;
498  const int outframes = SDL_min(wantedoutframes, maxoutframes);
499  float *dst = outbuf;
500  double outtime = 0.0;
501  int i, j, chan;
502 
503  for (i = 0; i < outframes; i++) {
504  const int srcindex = (int) (outtime * inrate);
505  const double intime = ((double) srcindex) / finrate;
506  const double innexttime = ((double) (srcindex + 1)) / finrate;
507  const double interpolation1 = 1.0 - ((innexttime - outtime) / (innexttime - intime));
508  const int filterindex1 = (int) (interpolation1 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
509  const double interpolation2 = 1.0 - interpolation1;
510  const int filterindex2 = (int) (interpolation2 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
511 
512  for (chan = 0; chan < chans; chan++) {
513  float outsample = 0.0f;
514 
515  /* do this twice to calculate the sample, once for the "left wing" and then same for the right. */
516  /* !!! FIXME: do both wings in one loop */
517  for (j = 0; (filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) {
518  const int srcframe = srcindex - j;
519  /* !!! FIXME: we can bubble this conditional out of here by doing a pre loop. */
520  const float insample = (srcframe < 0) ? lpadding[((paddinglen + srcframe) * chans) + chan] : inbuf[(srcframe * chans) + chan];
521  outsample += (float)(insample * (ResamplerFilter[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation1 * ResamplerFilterDifference[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
522  }
523 
524  for (j = 0; (filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) {
525  const int srcframe = srcindex + 1 + j;
526  /* !!! FIXME: we can bubble this conditional out of here by doing a post loop. */
527  const float insample = (srcframe >= inframes) ? rpadding[((srcframe - inframes) * chans) + chan] : inbuf[(srcframe * chans) + chan];
528  outsample += (float)(insample * (ResamplerFilter[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation2 * ResamplerFilterDifference[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
529  }
530  *(dst++) = outsample;
531  }
532 
533  outtime += outtimeincr;
534  }
535 
536  return outframes * chans * sizeof (float);
537 }
static int ResamplerPadding(const int inrate, const int outrate)
Definition: SDL_audiocvt.c:473
#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING
Definition: SDL_audiocvt.c:382
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
GLenum GLenum dst
static float * ResamplerFilter
Definition: SDL_audiocvt.c:431
static float * ResamplerFilterDifference
Definition: SDL_audiocvt.c:432
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 int in j)
Definition: SDL_x11sym.h:50
#define RESAMPLER_FILTER_SIZE
Definition: SDL_audiocvt.c:383
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

◆ SDL_ResampleAudioStream()

static int SDL_ResampleAudioStream ( SDL_AudioStream *  stream,
const void _inbuf,
const int  inbuflen,
void _outbuf,
const int  outbuflen 
)
static

Definition at line 1220 of file SDL_audiocvt.c.

References retval, SDL_assert, SDL_memcpy, SDL_min, and SDL_ResampleAudio().

Referenced by SDL_NewAudioStream().

1221 {
1222  const Uint8 *inbufend = ((const Uint8 *) _inbuf) + inbuflen;
1223  const float *inbuf = (const float *) _inbuf;
1224  float *outbuf = (float *) _outbuf;
1225  const int chans = (int) stream->pre_resample_channels;
1226  const int inrate = stream->src_rate;
1227  const int outrate = stream->dst_rate;
1228  const int paddingsamples = stream->resampler_padding_samples;
1229  const int paddingbytes = paddingsamples * sizeof (float);
1230  float *lpadding = (float *) stream->resampler_state;
1231  const float *rpadding = (const float *) inbufend; /* we set this up so there are valid padding samples at the end of the input buffer. */
1232  const int cpy = SDL_min(inbuflen, paddingbytes);
1233  int retval;
1234 
1235  SDL_assert(inbuf != ((const float *) outbuf)); /* SDL_AudioStreamPut() shouldn't allow in-place resamples. */
1236 
1237  retval = SDL_ResampleAudio(chans, inrate, outrate, lpadding, rpadding, inbuf, inbuflen, outbuf, outbuflen);
1238 
1239  /* update our left padding with end of current input, for next run. */
1240  SDL_memcpy((lpadding + paddingsamples) - (cpy / sizeof (float)), inbufend - cpy, cpy);
1241  return retval;
1242 }
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
static int SDL_ResampleAudio(const int chans, const int inrate, const int outrate, const float *lpadding, const float *rpadding, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
Definition: SDL_audiocvt.c:485
SDL_bool retval
#define SDL_memcpy
GLuint GLuint stream
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_assert(condition)
Definition: SDL_assert.h:169

◆ SDL_ResampleCVT()

static void SDL_ResampleCVT ( SDL_AudioCVT cvt,
const int  chans,
const SDL_AudioFormat  format 
)
static

Definition at line 707 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioCVT::buf, SDL_AudioCVT::filter_index, SDL_AudioCVT::filters, SDL_AudioCVT::len, SDL_AudioCVT::len_cvt, SDL_AudioCVT::len_mult, ResamplerPadding(), SDL_assert, SDL_AUDIOCVT_MAX_FILTERS, SDL_calloc, SDL_free, SDL_memmove, SDL_OutOfMemory, and SDL_ResampleAudio().

708 {
709  /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator).
710  !!! FIXME in 2.1: We need to store data for this resampler, because the cvt structure doesn't store the original sample rates,
711  !!! FIXME in 2.1: so we steal the ninth and tenth slot. :( */
712  const int inrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1];
713  const int outrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS];
714  const float *src = (const float *) cvt->buf;
715  const int srclen = cvt->len_cvt;
716  /*float *dst = (float *) cvt->buf;
717  const int dstlen = (cvt->len * cvt->len_mult);*/
718  /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
719  float *dst = (float *) (cvt->buf + srclen);
720  const int dstlen = (cvt->len * cvt->len_mult) - srclen;
721  const int paddingsamples = (ResamplerPadding(inrate, outrate) * chans);
722  float *padding;
723 
725 
726  /* we keep no streaming state here, so pad with silence on both ends. */
727  padding = (float *) SDL_calloc(paddingsamples, sizeof (float));
728  if (!padding) {
729  SDL_OutOfMemory();
730  return;
731  }
732 
733  cvt->len_cvt = SDL_ResampleAudio(chans, inrate, outrate, padding, padding, src, srclen, dst, dstlen);
734 
735  SDL_free(padding);
736 
737  SDL_memmove(cvt->buf, dst, cvt->len_cvt); /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
738 
739  if (cvt->filters[++cvt->filter_index]) {
740  cvt->filters[cvt->filter_index](cvt, format);
741  }
742 }
static int ResamplerPadding(const int inrate, const int outrate)
Definition: SDL_audiocvt.c:473
#define SDL_AUDIOCVT_MAX_FILTERS
Upper limit of filters in SDL_AudioCVT.
Definition: SDL_audio.h:202
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:231
int filter_index
Definition: SDL_audio.h:237
GLenum src
static int SDL_ResampleAudio(const int chans, const int inrate, const int outrate, const float *lpadding, const float *rpadding, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
Definition: SDL_audiocvt.c:485
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:236
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
#define SDL_free
#define SDL_memmove
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_calloc

◆ SDL_ResetAudioStreamResampler()

static void SDL_ResetAudioStreamResampler ( SDL_AudioStream *  stream)
static

Definition at line 1245 of file SDL_audiocvt.c.

References SDL_memset.

Referenced by SDL_NewAudioStream().

1246 {
1247  /* set all the padding to silence. */
1248  const int len = stream->resampler_padding_samples;
1249  SDL_memset(stream->resampler_state, '\0', len * sizeof (float));
1250 }
GLenum GLsizei len
GLuint GLuint stream
#define SDL_memset

◆ SDL_SupportedAudioFormat()

static SDL_bool SDL_SupportedAudioFormat ( const SDL_AudioFormat  fmt)
static

Definition at line 825 of file SDL_audiocvt.c.

References AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S8, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, SDL_FALSE, and SDL_TRUE.

Referenced by SDL_BuildAudioCVT().

826 {
827  switch (fmt) {
828  case AUDIO_U8:
829  case AUDIO_S8:
830  case AUDIO_U16LSB:
831  case AUDIO_S16LSB:
832  case AUDIO_U16MSB:
833  case AUDIO_S16MSB:
834  case AUDIO_S32LSB:
835  case AUDIO_S32MSB:
836  case AUDIO_F32LSB:
837  case AUDIO_F32MSB:
838  return SDL_TRUE; /* supported. */
839 
840  default:
841  break;
842  }
843 
844  return SDL_FALSE; /* unsupported. */
845 }
#define AUDIO_S32MSB
Definition: SDL_audio.h:104
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
#define AUDIO_F32MSB
Definition: SDL_audio.h:113
#define AUDIO_U8
Definition: SDL_audio.h:89
#define AUDIO_F32LSB
Definition: SDL_audio.h:112
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
#define AUDIO_S8
Definition: SDL_audio.h:90
#define AUDIO_U16MSB
Definition: SDL_audio.h:93

◆ SDL_SupportedChannelCount()

static SDL_bool SDL_SupportedChannelCount ( const int  channels)
static

Definition at line 848 of file SDL_audiocvt.c.

References SDL_FALSE, and SDL_TRUE.

Referenced by SDL_BuildAudioCVT().

849 {
850  switch (channels) {
851  case 1: /* mono */
852  case 2: /* stereo */
853  case 4: /* quad */
854  case 6: /* 5.1 */
855  case 8: /* 7.1 */
856  return SDL_TRUE; /* supported. */
857 
858  default:
859  break;
860  }
861 
862  return SDL_FALSE; /* unsupported. */
863 }

Variable Documentation

◆ ResampleFilterSpinlock

SDL_SpinLock ResampleFilterSpinlock = 0
static

Definition at line 430 of file SDL_audiocvt.c.

Referenced by SDL_PrepareResampleFilter().

◆ ResamplerFilter

float* ResamplerFilter = NULL
static

◆ ResamplerFilterDifference

float* ResamplerFilterDifference = NULL
static