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 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, float *lpadding, 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_AudioStreamSDL_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)
 
int SDL_AudioStreamPut (SDL_AudioStream *stream, const void *buf, const Uint32 _buflen)
 
void SDL_AudioStreamClear (SDL_AudioStream *stream)
 
int SDL_AudioStreamGet (SDL_AudioStream *stream, void *buf, const Uint32 len)
 
int SDL_AudioStreamAvailable (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().

◆ RESAMPLER_BITS_PER_SAMPLE

#define RESAMPLER_BITS_PER_SAMPLE   16

Definition at line 376 of file SDL_audiocvt.c.

◆ RESAMPLER_FILTER_SIZE

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

Definition at line 378 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:216
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572

Definition at line 739 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 377 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 375 of file SDL_audiocvt.c.

Typedef Documentation

◆ SDL_CleanupAudioStreamResamplerFunc

typedef void(* SDL_CleanupAudioStreamResamplerFunc) (SDL_AudioStream *stream)

Definition at line 1072 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 1070 of file SDL_audiocvt.c.

◆ SDL_ResetAudioStreamResamplerFunc

typedef void(* SDL_ResetAudioStreamResamplerFunc) (SDL_AudioStream *stream)

Definition at line 1071 of file SDL_audiocvt.c.

Function Documentation

◆ bessel()

static double bessel ( const double  x)
static

Definition at line 382 of file SDL_audiocvt.c.

References e, i, SDL_pow, and SDL_TRUE.

Referenced by kaiser_and_sinc().

383 {
384  const double xdiv2 = x / 2.0;
385  double i0 = 1.0f;
386  double f = 1.0f;
387  int i = 1;
388 
389  while (SDL_TRUE) {
390  const double diff = SDL_pow(xdiv2, i * 2) / SDL_pow(f, 2);
391  if (diff < 1.0e-21f) {
392  break;
393  }
394  i0 += diff;
395  i++;
396  f *= (double) i;
397  }
398 
399  return i0;
400 }
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 752 of file SDL_audiocvt.c.

References NULL.

Referenced by SDL_BuildAudioResampleCVT().

753 {
754  switch (dst_channels) {
755  case 1: return SDL_ResampleCVT_c1;
756  case 2: return SDL_ResampleCVT_c2;
757  case 4: return SDL_ResampleCVT_c4;
758  case 6: return SDL_ResampleCVT_c6;
759  case 8: return SDL_ResampleCVT_c8;
760  default: break;
761  }
762 
763  return NULL;
764 }
#define NULL
Definition: begin_code.h:164

◆ EnsureStreamBufferSize()

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

Definition at line 1099 of file SDL_audiocvt.c.

References SDL_AudioStream::cleanup_resampler_func, NULL, SDL_AudioStream::pre_resample_channels, SDL_AudioStream::rate_incr, SDL_AudioStream::resampler_func, SDL_AudioStream::resampler_state, SDL_AudioStream::reset_resampler_func, SDL_assert, SDL_FALSE, SDL_memcpy, SDL_OutOfMemory, SDL_realloc, SDL_SetError, SDL_TRUE, state, SDL_AudioStream::work_buffer_base, and SDL_AudioStream::work_buffer_len.

Referenced by SDL_AudioStreamPut(), and SDL_ResampleAudioStream().

1100 {
1101  Uint8 *ptr;
1102  size_t offset;
1103 
1104  if (stream->work_buffer_len >= newlen) {
1105  ptr = stream->work_buffer_base;
1106  } else {
1107  ptr = (Uint8 *) SDL_realloc(stream->work_buffer_base, newlen + 32);
1108  if (!ptr) {
1109  SDL_OutOfMemory();
1110  return NULL;
1111  }
1112  /* Make sure we're aligned to 16 bytes for SIMD code. */
1113  stream->work_buffer_base = ptr;
1114  stream->work_buffer_len = newlen;
1115  }
1116 
1117  offset = ((size_t) ptr) & 15;
1118  return offset ? ptr + (16 - offset) : ptr;
1119 }
GLintptr offset
#define SDL_realloc
unsigned int size_t
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
Uint8 * work_buffer_base

◆ kaiser_and_sinc()

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

Definition at line 404 of file SDL_audiocvt.c.

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

Referenced by SDL_PrepareResampleFilter().

405 {
406  const int lenm1 = tablelen - 1;
407  const int lenm1div2 = lenm1 / 2;
408  int i;
409 
410  table[0] = 1.0f;
411  for (i = 1; i < tablelen; i++) {
412  const double kaiser = bessel(beta * SDL_sqrt(1.0 - SDL_pow(((i - lenm1) / 2.0) / lenm1div2, 2.0))) / bessel(beta);
413  table[tablelen - i] = (float) kaiser;
414  }
415 
416  for (i = 1; i < tablelen; i++) {
417  const float x = (((float) i) / ((float) RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) * ((float) M_PI);
418  table[i] *= SDL_sinf(x) / x;
419  diffs[i - 1] = table[i] - table[i - 1];
420  }
421  diffs[lenm1] = 0.0f;
422 }
#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING
Definition: SDL_audiocvt.c:377
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:382
#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 468 of file SDL_audiocvt.c.

References RESAMPLER_SAMPLES_PER_ZERO_CROSSING, and SDL_ceil.

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

469 {
470  return (inrate > outrate) ? (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate))) : RESAMPLER_SAMPLES_PER_ZERO_CROSSING;
471 }
#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING
Definition: SDL_audiocvt.c:377
#define SDL_ceil

◆ SDL_AddAudioCVTFilter()

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

Definition at line 591 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().

592 {
594  return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS);
595  }
596  if (filter == NULL) {
597  return SDL_SetError("Audio filter pointer is NULL");
598  }
599  cvt->filters[cvt->filter_index++] = filter;
600  cvt->filters[cvt->filter_index] = NULL; /* Moving terminator */
601  return 0;
602 }
#define SDL_AUDIOCVT_MAX_FILTERS
Upper limit of filters in SDL_AudioCVT.
Definition: SDL_audio.h:193
int filter_index
Definition: SDL_audio.h:228
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:227
#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)

Definition at line 1476 of file SDL_audiocvt.c.

References SDL_AudioStream::queue, and SDL_CountDataQueue().

Referenced by SDL_CaptureAudio(), and SDL_RunAudio().

1477 {
1478  return stream ? (int) SDL_CountDataQueue(stream->queue) : 0;
1479 }
SDL_DataQueue * queue
size_t SDL_CountDataQueue(SDL_DataQueue *queue)

◆ SDL_AudioStreamClear()

void SDL_AudioStreamClear ( SDL_AudioStream stream)

Definition at line 1444 of file SDL_audiocvt.c.

References SDL_AudioStream::packetlen, SDL_AudioStream::queue, SDL_AudioStream::reset_resampler_func, SDL_ClearDataQueue(), and SDL_InvalidParamError.

Referenced by SDL_CaptureAudio().

1445 {
1446  if (!stream) {
1447  SDL_InvalidParamError("stream");
1448  } else {
1449  SDL_ClearDataQueue(stream->queue, stream->packetlen * 2);
1450  if (stream->reset_resampler_func) {
1451  stream->reset_resampler_func(stream);
1452  }
1453  }
1454 }
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
SDL_ResetAudioStreamResamplerFunc reset_resampler_func
void SDL_ClearDataQueue(SDL_DataQueue *queue, const size_t slack)
Definition: SDL_dataqueue.c:98
SDL_DataQueue * queue

◆ SDL_AudioStreamGet()

int SDL_AudioStreamGet ( SDL_AudioStream stream,
void buf,
const Uint32  len 
)

Definition at line 1459 of file SDL_audiocvt.c.

References SDL_AudioStream::dst_sample_frame_size, SDL_AudioStream::queue, SDL_InvalidParamError, SDL_ReadFromDataQueue(), and SDL_SetError.

Referenced by SDL_CaptureAudio(), and SDL_RunAudio().

1460 {
1461  if (!stream) {
1462  return SDL_InvalidParamError("stream");
1463  } else if (!buf) {
1464  return SDL_InvalidParamError("buf");
1465  } else if (len == 0) {
1466  return 0; /* nothing to do. */
1467  } else if ((len % stream->dst_sample_frame_size) != 0) {
1468  return SDL_SetError("Can't request partial sample frames");
1469  }
1470 
1471  return (int) SDL_ReadFromDataQueue(stream->queue, buf, len);
1472 }
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
GLenum GLsizei len
size_t SDL_ReadFromDataQueue(SDL_DataQueue *queue, void *_buf, const size_t _len)
GLenum GLuint GLenum GLsizei const GLchar * buf
#define SDL_SetError
SDL_DataQueue * queue

◆ SDL_AudioStreamPut()

int SDL_AudioStreamPut ( SDL_AudioStream stream,
const void buf,
const Uint32  _buflen 
)

Definition at line 1366 of file SDL_audiocvt.c.

References SDL_AudioCVT::buf, SDL_AudioStream::cvt_after_resampling, SDL_AudioStream::cvt_before_resampling, SDL_AudioStream::dst_rate, EnsureStreamBufferSize(), SDL_AudioCVT::len, SDL_AudioCVT::len_cvt, SDL_AudioCVT::len_mult, SDL_AudioCVT::needed, NULL, SDL_AudioStream::queue, SDL_AudioStream::rate_incr, SDL_AudioStream::resampler_func, SDL_assert, SDL_ceil, SDL_ConvertAudio(), SDL_InvalidParamError, SDL_memcpy, SDL_SetError, SDL_WriteToDataQueue(), SDL_AudioStream::src_rate, and SDL_AudioStream::src_sample_frame_size.

Referenced by SDL_CaptureAudio(), and SDL_RunAudio().

1367 {
1368  int buflen = (int) _buflen;
1369  const void *origbuf = buf;
1370 
1371  /* !!! FIXME: several converters can take advantage of SIMD, but only
1372  !!! FIXME: if the data is aligned to 16 bytes. EnsureStreamBufferSize()
1373  !!! FIXME: guarantees the buffer will align, but the
1374  !!! FIXME: converters will iterate over the data backwards if
1375  !!! FIXME: the output grows, and this means we won't align if buflen
1376  !!! FIXME: isn't a multiple of 16. In these cases, we should chop off
1377  !!! FIXME: a few samples at the end and convert them separately. */
1378 
1379  if (!stream) {
1380  return SDL_InvalidParamError("stream");
1381  } else if (!buf) {
1382  return SDL_InvalidParamError("buf");
1383  } else if (buflen == 0) {
1384  return 0; /* nothing to do. */
1385  } else if ((buflen % stream->src_sample_frame_size) != 0) {
1386  return SDL_SetError("Can't add partial sample frames");
1387  }
1388 
1389  if (stream->cvt_before_resampling.needed) {
1390  const int workbuflen = buflen * stream->cvt_before_resampling.len_mult; /* will be "* 1" if not needed */
1391  Uint8 *workbuf = EnsureStreamBufferSize(stream, workbuflen);
1392  if (workbuf == NULL) {
1393  return -1; /* probably out of memory. */
1394  }
1395  SDL_assert(buf == origbuf);
1396  SDL_memcpy(workbuf, buf, buflen);
1397  stream->cvt_before_resampling.buf = workbuf;
1398  stream->cvt_before_resampling.len = buflen;
1399  if (SDL_ConvertAudio(&stream->cvt_before_resampling) == -1) {
1400  return -1; /* uhoh! */
1401  }
1402  buf = workbuf;
1403  buflen = stream->cvt_before_resampling.len_cvt;
1404  }
1405 
1406  if (stream->dst_rate != stream->src_rate) {
1407  const int workbuflen = buflen * ((int) SDL_ceil(stream->rate_incr));
1408  Uint8 *workbuf = EnsureStreamBufferSize(stream, workbuflen);
1409  if (workbuf == NULL) {
1410  return -1; /* probably out of memory. */
1411  }
1412  /* don't SDL_memcpy(workbuf, buf, buflen) here; our resampler can work inplace or not,
1413  libsamplerate needs buffers to be separate; either way, avoid a copy here if possible. */
1414  if (buf != origbuf) {
1415  buf = workbuf; /* in case we realloc()'d the pointer. */
1416  }
1417  buflen = stream->resampler_func(stream, buf, buflen, workbuf, workbuflen);
1418  buf = EnsureStreamBufferSize(stream, workbuflen);
1419  SDL_assert(buf != NULL); /* shouldn't be growing, just aligning. */
1420  }
1421 
1422  if (stream->cvt_after_resampling.needed) {
1423  const int workbuflen = buflen * stream->cvt_after_resampling.len_mult; /* will be "* 1" if not needed */
1424  Uint8 *workbuf = EnsureStreamBufferSize(stream, workbuflen);
1425  if (workbuf == NULL) {
1426  return -1; /* probably out of memory. */
1427  }
1428  if (buf == origbuf) { /* copy if we haven't before. */
1429  SDL_memcpy(workbuf, origbuf, buflen);
1430  }
1431  stream->cvt_after_resampling.buf = workbuf;
1432  stream->cvt_after_resampling.len = buflen;
1433  if (SDL_ConvertAudio(&stream->cvt_after_resampling) == -1) {
1434  return -1; /* uhoh! */
1435  }
1436  buf = workbuf;
1437  buflen = stream->cvt_after_resampling.len_cvt;
1438  }
1439 
1440  return SDL_WriteToDataQueue(stream->queue, buf, buflen);
1441 }
#define SDL_ceil
SDL_AudioCVT cvt_before_resampling
int SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
Uint8 * buf
Definition: SDL_audio.h:222
SDL_AudioCVT cvt_after_resampling
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
static Uint8 * EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen)
#define SDL_memcpy
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_ResampleAudioStreamFunc resampler_func
int SDL_ConvertAudio(SDL_AudioCVT *cvt)
Definition: SDL_audiocvt.c:530
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_DataQueue * queue

◆ 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 863 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().

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

References ChooseCVTResampler(), SDL_AudioStream::dst_rate, 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(), SDL_SetError, and SDL_AudioStream::src_rate.

Referenced by SDL_BuildAudioCVT().

769 {
771 
772  if (src_rate == dst_rate) {
773  return 0; /* no conversion necessary. */
774  }
775 
776  filter = ChooseCVTResampler(dst_channels);
777  if (filter == NULL) {
778  return SDL_SetError("No conversion available for these rates");
779  }
780 
781  if (SDL_PrepareResampleFilter() < 0) {
782  return -1;
783  }
784 
785  /* Update (cvt) with filter details... */
786  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
787  return -1;
788  }
789 
790  /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator).
791  !!! FIXME in 2.1: We need to store data for this resampler, because the cvt structure doesn't store the original sample rates,
792  !!! FIXME in 2.1: so we steal the ninth and tenth slot. :( */
793  if (cvt->filter_index >= (SDL_AUDIOCVT_MAX_FILTERS-2)) {
794  return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS-2);
795  }
796  cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1] = (SDL_AudioFilter) (size_t) src_rate;
797  cvt->filters[SDL_AUDIOCVT_MAX_FILTERS] = (SDL_AudioFilter) (size_t) dst_rate;
798 
799  if (src_rate < dst_rate) {
800  const double mult = ((double) dst_rate) / ((double) src_rate);
801  cvt->len_mult *= (int) SDL_ceil(mult);
802  cvt->len_ratio *= mult;
803  } else {
804  cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
805  }
806 
807  /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
808  /* the buffer is big enough to hold the destination now, but
809  we need it large enough to hold a separate scratch buffer. */
810  cvt->len_mult *= 2;
811 
812  return 1; /* added a converter. */
813 }
static SDL_AudioFilter ChooseCVTResampler(const int dst_channels)
Definition: SDL_audiocvt.c:752
#define SDL_AUDIOCVT_MAX_FILTERS
Upper limit of filters in SDL_AudioCVT.
Definition: SDL_audio.h:193
#define SDL_ceil
int filter_index
Definition: SDL_audio.h:228
double len_ratio
Definition: SDL_audio.h:226
int SDL_PrepareResampleFilter(void)
Definition: SDL_audiocvt.c:430
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:227
void(* SDL_AudioFilter)(struct SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audio.h:183
#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:591
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 652 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().

653 {
654  int retval = 0; /* 0 == no conversion necessary. */
655 
656  if (!SDL_AUDIO_ISFLOAT(dst_fmt)) {
657  const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
658  const Uint16 src_bitsize = 32;
660  switch (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN) {
661  case AUDIO_S8: filter = SDL_Convert_F32_to_S8; break;
662  case AUDIO_U8: filter = SDL_Convert_F32_to_U8; break;
663  case AUDIO_S16: filter = SDL_Convert_F32_to_S16; break;
664  case AUDIO_U16: filter = SDL_Convert_F32_to_U16; break;
665  case AUDIO_S32: filter = SDL_Convert_F32_to_S32; break;
666  default: SDL_assert(!"Unexpected audio format!"); break;
667  }
668 
669  if (!filter) {
670  return SDL_SetError("No conversion from float to destination format available");
671  }
672 
673  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
674  return -1;
675  }
676  if (src_bitsize < dst_bitsize) {
677  const int mult = (dst_bitsize / src_bitsize);
678  cvt->len_mult *= mult;
679  cvt->len_ratio *= mult;
680  } else if (src_bitsize > dst_bitsize) {
681  cvt->len_ratio /= (src_bitsize / dst_bitsize);
682  }
683  retval = 1; /* added a converter. */
684  }
685 
686  if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
688  return -1;
689  }
690  retval = 1; /* added a converter. */
691  }
692 
693  return retval;
694 }
#define SDL_AUDIO_ISBIGENDIAN(x)
Definition: SDL_audio.h:77
SDL_AudioFilter SDL_Convert_F32_to_S32
double len_ratio
Definition: SDL_audio.h:226
#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:553
#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:183
#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:591
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 605 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().

606 {
607  int retval = 0; /* 0 == no conversion necessary. */
608 
609  if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
611  return -1;
612  }
613  retval = 1; /* added a converter. */
614  }
615 
616  if (!SDL_AUDIO_ISFLOAT(src_fmt)) {
617  const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
618  const Uint16 dst_bitsize = 32;
620 
621  switch (src_fmt & ~SDL_AUDIO_MASK_ENDIAN) {
622  case AUDIO_S8: filter = SDL_Convert_S8_to_F32; break;
623  case AUDIO_U8: filter = SDL_Convert_U8_to_F32; break;
624  case AUDIO_S16: filter = SDL_Convert_S16_to_F32; break;
625  case AUDIO_U16: filter = SDL_Convert_U16_to_F32; break;
626  case AUDIO_S32: filter = SDL_Convert_S32_to_F32; break;
627  default: SDL_assert(!"Unexpected audio format!"); break;
628  }
629 
630  if (!filter) {
631  return SDL_SetError("No conversion from source format to float available");
632  }
633 
634  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
635  return -1;
636  }
637  if (src_bitsize < dst_bitsize) {
638  const int mult = (dst_bitsize / src_bitsize);
639  cvt->len_mult *= mult;
640  cvt->len_ratio *= mult;
641  } else if (src_bitsize > dst_bitsize) {
642  cvt->len_ratio /= (src_bitsize / dst_bitsize);
643  }
644 
645  retval = 1; /* added a converter. */
646  }
647 
648  return retval;
649 }
#define SDL_AUDIO_ISBIGENDIAN(x)
Definition: SDL_audio.h:77
double len_ratio
Definition: SDL_audio.h:226
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:553
#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:183
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:591
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 1268 of file SDL_audiocvt.c.

References SDL_AudioStream::resampler_state, and SDL_free().

Referenced by SDL_NewAudioStream().

1269 {
1270  SDL_free(stream->resampler_state);
1271 }
void * resampler_state
void SDL_free(void *mem)

◆ SDL_Convert51To71()

static void SDL_Convert51To71 ( SDL_AudioCVT cvt,
SDL_AudioFormat  format 
)
static

Definition at line 330 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().

331 {
332  float lf, rf, lb, rb, ls, rs;
333  int i;
334  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
335  float *dst = (float *) (cvt->buf + cvt->len_cvt * 4 / 3);
336 
337  LOG_DEBUG_CONVERT("5.1", "7.1");
339  SDL_assert(cvt->len_cvt % (sizeof(float) * 6) == 0);
340 
341  for (i = cvt->len_cvt / (sizeof(float) * 6); i; --i) {
342  dst -= 8;
343  src -= 6;
344  lf = src[0];
345  rf = src[1];
346  lb = src[4];
347  rb = src[5];
348  ls = (lf + lb) * 0.5f;
349  rs = (rf + rb) * 0.5f;
350  /* !!! FIXME: these four may clip */
351  lf += lf - ls;
352  rf += rf - ls;
353  lb += lb - ls;
354  rb += rb - ls;
355  dst[3] = src[3]; /* LFE */
356  dst[2] = src[2]; /* FC */
357  dst[7] = rs; /* SR */
358  dst[6] = ls; /* SL */
359  dst[5] = rb; /* BR */
360  dst[4] = lb; /* BL */
361  dst[1] = rf; /* FR */
362  dst[0] = lf; /* FL */
363  }
364 
365  cvt->len_cvt = cvt->len_cvt * 4 / 3;
366 
367  if (cvt->filters[++cvt->filter_index]) {
368  cvt->filters[cvt->filter_index] (cvt, format);
369  }
370 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
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:227
#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 176 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().

177 {
178  float *dst = (float *) cvt->buf;
179  const float *src = dst;
180  int i;
181 
182  LOG_DEBUG_CONVERT("5.1", "quad");
184 
185  /* SDL's 4.0 layout: FL+FR+BL+BR */
186  /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */
187  for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 4) {
188  const float front_center_distributed = src[2] * 0.5f;
189  dst[0] = (src[0] + front_center_distributed) / 1.5f; /* FL */
190  dst[1] = (src[1] + front_center_distributed) / 1.5f; /* FR */
191  dst[2] = src[4] / 1.5f; /* BL */
192  dst[3] = src[5] / 1.5f; /* BR */
193  }
194 
195  cvt->len_cvt /= 6;
196  cvt->len_cvt *= 4;
197  if (cvt->filters[++cvt->filter_index]) {
198  cvt->filters[cvt->filter_index] (cvt, format);
199  }
200 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
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:227
#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 98 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().

99 {
100  float *dst = (float *) cvt->buf;
101  const float *src = dst;
102  int i;
103 
104  LOG_DEBUG_CONVERT("5.1", "stereo");
106 
107  /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */
108  for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 2) {
109  const float front_center_distributed = src[2] * 0.5f;
110  dst[0] = (src[0] + front_center_distributed + src[4]) / 2.5f; /* left */
111  dst[1] = (src[1] + front_center_distributed + src[5]) / 2.5f; /* right */
112  }
113 
114  cvt->len_cvt /= 3;
115  if (cvt->filters[++cvt->filter_index]) {
116  cvt->filters[cvt->filter_index] (cvt, format);
117  }
118 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
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:227
#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 146 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().

147 {
148  float *dst = (float *) cvt->buf;
149  const float *src = dst;
150  int i;
151 
152  LOG_DEBUG_CONVERT("7.1", "5.1");
154 
155  for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8, dst += 6) {
156  const float surround_left_distributed = src[6] * 0.5f;
157  const float surround_right_distributed = src[7] * 0.5f;
158  dst[0] = (src[0] + surround_left_distributed) / 1.5f; /* FL */
159  dst[1] = (src[1] + surround_right_distributed) / 1.5f; /* FR */
160  dst[2] = src[2] / 1.5f; /* CC */
161  dst[3] = src[3] / 1.5f; /* LFE */
162  dst[4] = (src[4] + surround_left_distributed) / 1.5f; /* BL */
163  dst[5] = (src[5] + surround_right_distributed) / 1.5f; /* BR */
164  }
165 
166  cvt->len_cvt /= 8;
167  cvt->len_cvt *= 6;
168  if (cvt->filters[++cvt->filter_index]) {
169  cvt->filters[cvt->filter_index] (cvt, format);
170  }
171 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
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:227
#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 553 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().

554 {
555 #if DEBUG_CONVERT
556  printf("Converting byte order\n");
557 #endif
558 
559  switch (SDL_AUDIO_BITSIZE(format)) {
560  #define CASESWAP(b) \
561  case b: { \
562  Uint##b *ptr = (Uint##b *) cvt->buf; \
563  int i; \
564  for (i = cvt->len_cvt / sizeof (*ptr); i; --i, ++ptr) { \
565  *ptr = SDL_Swap##b(*ptr); \
566  } \
567  break; \
568  }
569 
570  CASESWAP(16);
571  CASESWAP(32);
572  CASESWAP(64);
573 
574  #undef CASESWAP
575 
576  default: SDL_assert(!"unhandled byteswap datatype!"); break;
577  }
578 
579  if (cvt->filters[++cvt->filter_index]) {
580  /* flip endian flag for data. */
582  format &= ~SDL_AUDIO_MASK_ENDIAN;
583  } else {
585  }
586  cvt->filters[cvt->filter_index](cvt, format);
587  }
588 }
int filter_index
Definition: SDL_audio.h:228
#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:227
#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 530 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_AudioStreamPut().

531 {
532  /* !!! FIXME: (cvt) should be const; stack-copy it here. */
533  /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
534 
535  /* Make sure there's data to convert */
536  if (cvt->buf == NULL) {
537  return SDL_SetError("No buffer allocated for conversion");
538  }
539 
540  /* Return okay if no conversion is necessary */
541  cvt->len_cvt = cvt->len;
542  if (cvt->filters[0] == NULL) {
543  return 0;
544  }
545 
546  /* Set up the conversion and go! */
547  cvt->filter_index = 0;
548  cvt->filters[0] (cvt, cvt->src_format);
549  return 0;
550 }
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:227
SDL_AudioFormat src_format
Definition: SDL_audio.h:219
#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 205 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().

206 {
207  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
208  float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
209  int i;
210 
211  LOG_DEBUG_CONVERT("mono", "stereo");
213 
214  for (i = cvt->len_cvt / sizeof (float); i; --i) {
215  src--;
216  dst -= 2;
217  dst[0] = dst[1] = *src;
218  }
219 
220  cvt->len_cvt *= 2;
221  if (cvt->filters[++cvt->filter_index]) {
222  cvt->filters[cvt->filter_index] (cvt, format);
223  }
224 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
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:227
#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 263 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().

264 {
265  int i;
266  float lf, rf, lb, rb, ce;
267  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
268  float *dst = (float *) (cvt->buf + cvt->len_cvt * 3 / 2);
269 
270  LOG_DEBUG_CONVERT("quad", "5.1");
272  SDL_assert(cvt->len_cvt % (sizeof(float) * 4) == 0);
273 
274  for (i = cvt->len_cvt / (sizeof(float) * 4); i; --i) {
275  dst -= 6;
276  src -= 4;
277  lf = src[0];
278  rf = src[1];
279  lb = src[2];
280  rb = src[3];
281  ce = (lf + rf) * 0.5f;
282  /* !!! FIXME: FL and FR may clip */
283  dst[0] = lf + (lf - ce); /* FL */
284  dst[1] = rf + (rf - ce); /* FR */
285  dst[2] = ce; /* FC */
286  dst[3] = 0; /* LFE (only meant for special LFE effects) */
287  dst[4] = lb; /* BL */
288  dst[5] = rb; /* BR */
289  }
290 
291  cvt->len_cvt = cvt->len_cvt * 3 / 2;
292  if (cvt->filters[++cvt->filter_index]) {
293  cvt->filters[cvt->filter_index] (cvt, format);
294  }
295 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
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:227
#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 123 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().

124 {
125  float *dst = (float *) cvt->buf;
126  const float *src = dst;
127  int i;
128 
129  LOG_DEBUG_CONVERT("quad", "stereo");
131 
132  for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src += 4, dst += 2) {
133  dst[0] = (src[0] + src[2]) * 0.5f; /* left */
134  dst[1] = (src[1] + src[3]) * 0.5f; /* right */
135  }
136 
137  cvt->len_cvt /= 3;
138  if (cvt->filters[++cvt->filter_index]) {
139  cvt->filters[cvt->filter_index] (cvt, format);
140  }
141 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
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:227
#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 229 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().

230 {
231  int i;
232  float lf, rf, ce;
233  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
234  float *dst = (float *) (cvt->buf + cvt->len_cvt * 3);
235 
236  LOG_DEBUG_CONVERT("stereo", "5.1");
238 
239  for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) {
240  dst -= 6;
241  src -= 2;
242  lf = src[0];
243  rf = src[1];
244  ce = (lf + rf) * 0.5f;
245  /* !!! FIXME: FL and FR may clip */
246  dst[0] = lf + (lf - ce); /* FL */
247  dst[1] = rf + (rf - ce); /* FR */
248  dst[2] = ce; /* FC */
249  dst[3] = 0; /* LFE (only meant for special LFE effects) */
250  dst[4] = lf; /* BL */
251  dst[5] = rf; /* BR */
252  }
253 
254  cvt->len_cvt *= 3;
255  if (cvt->filters[++cvt->filter_index]) {
256  cvt->filters[cvt->filter_index] (cvt, format);
257  }
258 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
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:227
#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 76 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().

77 {
78  float *dst = (float *) cvt->buf;
79  const float *src = dst;
80  int i;
81 
82  LOG_DEBUG_CONVERT("stereo", "mono");
84 
85  for (i = cvt->len_cvt / 8; i; --i, src += 2) {
86  *(dst++) = (src[0] + src[1]) * 0.5f;
87  }
88 
89  cvt->len_cvt /= 2;
90  if (cvt->filters[++cvt->filter_index]) {
91  cvt->filters[cvt->filter_index] (cvt, format);
92  }
93 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
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:227
#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 300 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().

301 {
302  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
303  float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
304  float lf, rf;
305  int i;
306 
307  LOG_DEBUG_CONVERT("stereo", "quad");
309 
310  for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) {
311  dst -= 4;
312  src -= 2;
313  lf = src[0];
314  rf = src[1];
315  dst[0] = lf; /* FL */
316  dst[1] = rf; /* FR */
317  dst[2] = lf; /* BL */
318  dst[3] = rf; /* BR */
319  }
320 
321  cvt->len_cvt *= 2;
322  if (cvt->filters[++cvt->filter_index]) {
323  cvt->filters[cvt->filter_index] (cvt, format);
324  }
325 }
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
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:227
#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)

Definition at line 1483 of file SDL_audiocvt.c.

References SDL_AudioStream::cleanup_resampler_func, SDL_AudioStream::queue, SDL_free(), SDL_FreeDataQueue(), and SDL_AudioStream::work_buffer_base.

Referenced by close_audio_device(), and SDL_NewAudioStream().

1484 {
1485  if (stream) {
1486  if (stream->cleanup_resampler_func) {
1487  stream->cleanup_resampler_func(stream);
1488  }
1489  SDL_FreeDataQueue(stream->queue);
1490  SDL_free(stream->work_buffer_base);
1491  SDL_free(stream);
1492  }
1493 }
void SDL_free(void *mem)
SDL_CleanupAudioStreamResamplerFunc cleanup_resampler_func
SDL_DataQueue * queue
Uint8 * work_buffer_base
void SDL_FreeDataQueue(SDL_DataQueue *queue)
Definition: SDL_dataqueue.c:88

◆ SDL_FreeResampleFilter()

void SDL_FreeResampleFilter ( void  )

Definition at line 459 of file SDL_audiocvt.c.

References NULL, and SDL_free().

Referenced by SDL_AudioQuit().

460 {
465 }
static float * ResamplerFilter
Definition: SDL_audiocvt.c:426
static float * ResamplerFilterDifference
Definition: SDL_audiocvt.c:427
void SDL_free(void *mem)
#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 
)

Definition at line 1274 of file SDL_audiocvt.c.

References AUDIO_F32SYS, SDL_AudioStream::cleanup_resampler_func, SDL_AudioStream::cvt_after_resampling, SDL_AudioStream::cvt_before_resampling, SDL_AudioStream::dst_channels, SDL_AudioStream::dst_format, SDL_AudioStream::dst_rate, SDL_AudioStream::dst_sample_frame_size, SDL_AudioCVT::needed, NULL, SDL_AudioStream::packetlen, SDL_AudioStream::pre_resample_channels, SDL_AudioStream::queue, SDL_AudioStream::rate_incr, SDL_AudioStream::resampler_func, SDL_AudioStream::resampler_state, ResamplerPadding(), SDL_AudioStream::reset_resampler_func, retval, SDL_AUDIO_BITSIZE, SDL_BuildAudioCVT(), SDL_calloc(), SDL_CleanupAudioStreamResampler(), SDL_FALSE, SDL_free(), SDL_FreeAudioStream(), SDL_min, SDL_NewDataQueue(), SDL_OutOfMemory, SDL_PrepareResampleFilter(), SDL_ResampleAudioStream(), SDL_ResetAudioStreamResampler(), SDL_AudioStream::src_channels, SDL_AudioStream::src_format, SDL_AudioStream::src_rate, and SDL_AudioStream::src_sample_frame_size.

Referenced by open_audio_device().

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

◆ SDL_PrepareResampleFilter()

int SDL_PrepareResampleFilter ( void  )

Definition at line 430 of file SDL_audiocvt.c.

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

Referenced by SDL_BuildAudioResampleCVT(), and SDL_NewAudioStream().

431 {
433  if (!ResamplerFilter) {
434  /* if dB > 50, beta=(0.1102 * (dB - 8.7)), according to Matlab. */
435  const double dB = 80.0;
436  const double beta = 0.1102 * (dB - 8.7);
437  const size_t alloclen = RESAMPLER_FILTER_SIZE * sizeof (float);
438 
439  ResamplerFilter = (float *) SDL_malloc(alloclen);
440  if (!ResamplerFilter) {
442  return SDL_OutOfMemory();
443  }
444 
445  ResamplerFilterDifference = (float *) SDL_malloc(alloclen);
450  return SDL_OutOfMemory();
451  }
453  }
455  return 0;
456 }
#define SDL_AtomicLock
static SDL_SpinLock ResampleFilterSpinlock
Definition: SDL_audiocvt.c:425
static float * ResamplerFilter
Definition: SDL_audiocvt.c:426
static void kaiser_and_sinc(float *table, float *diffs, const int tablelen, const double beta)
Definition: SDL_audiocvt.c:404
static float * ResamplerFilterDifference
Definition: SDL_audiocvt.c:427
#define SDL_AtomicUnlock
void SDL_free(void *mem)
#define RESAMPLER_FILTER_SIZE
Definition: SDL_audiocvt.c:378
#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,
float *  lpadding,
float *  rpadding,
const float *  inbuf,
const int  inbuflen,
float *  outbuf,
const int  outbuflen 
)
static

Definition at line 475 of file SDL_audiocvt.c.

References i, j, RESAMPLER_FILTER_SIZE, RESAMPLER_SAMPLES_PER_ZERO_CROSSING, and ResamplerPadding().

Referenced by SDL_ResampleAudioStream(), and SDL_ResampleCVT().

478 {
479  const float outtimeincr = 1.0f / ((float) outrate);
480  const float ratio = ((float) outrate) / ((float) inrate);
481  const int paddinglen = ResamplerPadding(inrate, outrate);
482  const int framelen = chans * (int)sizeof (float);
483  const int inframes = inbuflen / framelen;
484  const int wantedoutframes = (int) ((inbuflen / framelen) * ratio); /* outbuflen isn't total to write, it's total available. */
485  const int maxoutframes = outbuflen / framelen;
486  const int outframes = (wantedoutframes < maxoutframes) ? wantedoutframes : maxoutframes;
487  float *dst = outbuf;
488  float outtime = 0.0f;
489  int i, j, chan;
490 
491  for (i = 0; i < outframes; i++) {
492  const int srcindex = (int) (outtime * inrate);
493  const float finrate = (float) inrate;
494  const float intime = ((float) srcindex) / finrate;
495  const float innexttime = ((float) (srcindex + 1)) / finrate;
496 
497  const float interpolation1 = 1.0f - (innexttime - outtime) / (innexttime - intime);
498  const int filterindex1 = (int) (interpolation1 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
499  const float interpolation2 = 1.0f - interpolation1;
500  const int filterindex2 = interpolation2 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING;
501 
502  for (chan = 0; chan < chans; chan++) {
503  float outsample = 0.0f;
504 
505  /* do this twice to calculate the sample, once for the "left wing" and then same for the right. */
506  /* !!! FIXME: do both wings in one loop */
507  for (j = 0; (filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) {
508  const int srcframe = srcindex - j;
509  /* !!! FIXME: we can bubble this conditional out of here by doing a pre loop. */
510  const float insample = (srcframe < 0) ? lpadding[((paddinglen + srcframe) * chans) + chan] : inbuf[(srcframe * chans) + chan];
511  outsample += (insample * (ResamplerFilter[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation1 * ResamplerFilterDifference[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
512  }
513 
514  for (j = 0; (filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) {
515  const int srcframe = srcindex + 1 + j;
516  /* !!! FIXME: we can bubble this conditional out of here by doing a post loop. */
517  const float insample = (srcframe >= inframes) ? rpadding[((srcframe - inframes) * chans) + chan] : inbuf[(srcframe * chans) + chan];
518  outsample += (insample * (ResamplerFilter[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation2 * ResamplerFilterDifference[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
519  }
520  *(dst++) = outsample;
521  }
522 
523  outtime += outtimeincr;
524  }
525 
526  return outframes * chans * sizeof (float);
527 }
static int ResamplerPadding(const int inrate, const int outrate)
Definition: SDL_audiocvt.c:468
#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING
Definition: SDL_audiocvt.c:377
GLenum GLenum dst
static float * ResamplerFilter
Definition: SDL_audiocvt.c:426
static float * ResamplerFilterDifference
Definition: SDL_audiocvt.c:427
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:378
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 1214 of file SDL_audiocvt.c.

References SDL_AudioStream::dst_rate, EnsureStreamBufferSize(), NULL, SDL_AudioStream::pre_resample_channels, SDL_AudioStream::resampler_state, ResamplerPadding(), retval, SDL_memcpy, SDL_memset, SDL_OutOfMemory, SDL_ResampleAudio(), SDL_stack_alloc, SDL_stack_free, and SDL_AudioStream::src_rate.

Referenced by SDL_NewAudioStream().

1215 {
1216  const float *inbuf = (const float *) _inbuf;
1217  float *outbuf = (float *) _outbuf;
1218  const int chans = (int) stream->pre_resample_channels;
1219  const int inrate = stream->src_rate;
1220  const int outrate = stream->dst_rate;
1221  const int paddingsamples = ResamplerPadding(inrate, outrate) * chans;
1222  const int paddingbytes = paddingsamples * sizeof (float);
1223  float *lpadding = (float *) stream->resampler_state;
1224  float *rpadding;
1225  int retval;
1226 
1227  if (inbuf == ((const float *) outbuf)) { /* !!! FIXME can't work in-place (for now!). */
1228  Uint8 *ptr = EnsureStreamBufferSize(stream, inbuflen + outbuflen);
1229  if (ptr == NULL) {
1230  SDL_OutOfMemory();
1231  return 0;
1232  }
1233  SDL_memcpy(ptr + outbuflen, ptr, inbuflen);
1234  inbuf = (const float *) (ptr + outbuflen);
1235  outbuf = (float *) ptr;
1236  }
1237 
1238  /* !!! FIXME: streaming current resamples on Put, because of probably good reasons I can't remember right now, but if we resample on Get, we'd be able to access legit right padding values. */
1239  rpadding = SDL_stack_alloc(float, paddingsamples);
1240  if (!rpadding) {
1241  SDL_OutOfMemory();
1242  return 0;
1243  }
1244  SDL_memset(rpadding, '\0', paddingbytes);
1245 
1246  retval = SDL_ResampleAudio(chans, inrate, outrate, lpadding, rpadding, inbuf, inbuflen, outbuf, outbuflen);
1247 
1248  SDL_stack_free(rpadding);
1249 
1250  /* update our left padding with end of current input, for next run. */
1251  SDL_memcpy(lpadding, ((const Uint8 *) inbuf) + (inbuflen - paddingbytes), paddingbytes);
1252 
1253  return retval;
1254 }
static int ResamplerPadding(const int inrate, const int outrate)
Definition: SDL_audiocvt.c:468
void * resampler_state
static int SDL_ResampleAudio(const int chans, const int inrate, const int outrate, float *lpadding, float *rpadding, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
Definition: SDL_audiocvt.c:475
static Uint8 * EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen)
SDL_bool retval
#define SDL_memcpy
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
Uint8 pre_resample_channels
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
#define SDL_memset

◆ SDL_ResampleCVT()

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

Definition at line 697 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_memcpy, SDL_memset, SDL_OutOfMemory, SDL_ResampleAudio(), SDL_stack_alloc, and SDL_stack_free.

698 {
699  /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator).
700  !!! FIXME in 2.1: We need to store data for this resampler, because the cvt structure doesn't store the original sample rates,
701  !!! FIXME in 2.1: so we steal the ninth and tenth slot. :( */
702  const int inrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1];
703  const int outrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS];
704  const float *src = (const float *) cvt->buf;
705  const int srclen = cvt->len_cvt;
706  /*float *dst = (float *) cvt->buf;
707  const int dstlen = (cvt->len * cvt->len_mult);*/
708  /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
709  float *dst = (float *) (cvt->buf + srclen);
710  const int dstlen = (cvt->len * cvt->len_mult) - srclen;
711  const int paddingsamples = (ResamplerPadding(inrate, outrate) * chans);
712  float *padding;
713 
715 
716  /* we keep no streaming state here, so pad with silence on both ends. */
717  padding = SDL_stack_alloc(float, paddingsamples);
718  if (!padding) {
719  SDL_OutOfMemory();
720  return;
721  }
722  SDL_memset(padding, '\0', paddingsamples * sizeof (float));
723 
724  cvt->len_cvt = SDL_ResampleAudio(chans, inrate, outrate, padding, padding, src, srclen, dst, dstlen);
725 
726  SDL_stack_free(padding);
727 
728  SDL_memcpy(cvt->buf, dst, cvt->len_cvt); /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
729 
730  if (cvt->filters[++cvt->filter_index]) {
731  cvt->filters[cvt->filter_index](cvt, format);
732  }
733 }
static int ResamplerPadding(const int inrate, const int outrate)
Definition: SDL_audiocvt.c:468
#define SDL_AUDIOCVT_MAX_FILTERS
Upper limit of filters in SDL_AudioCVT.
Definition: SDL_audio.h:193
GLenum GLenum dst
Uint8 * buf
Definition: SDL_audio.h:222
int filter_index
Definition: SDL_audio.h:228
static int SDL_ResampleAudio(const int chans, const int inrate, const int outrate, float *lpadding, float *rpadding, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
Definition: SDL_audiocvt.c:475
GLenum src
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
#define SDL_memcpy
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:227
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
#define SDL_memset

◆ SDL_ResetAudioStreamResampler()

static void SDL_ResetAudioStreamResampler ( SDL_AudioStream stream)
static

Definition at line 1257 of file SDL_audiocvt.c.

References SDL_AudioStream::dst_rate, SDL_AudioStream::pre_resample_channels, SDL_AudioStream::resampler_state, ResamplerPadding(), SDL_memset, and SDL_AudioStream::src_rate.

Referenced by SDL_NewAudioStream().

1258 {
1259  /* set all the left padding to silence. */
1260  const int inrate = stream->src_rate;
1261  const int outrate = stream->dst_rate;
1262  const int chans = (int) stream->pre_resample_channels;
1263  const int len = ResamplerPadding(inrate, outrate) * chans;
1264  SDL_memset(stream->resampler_state, '\0', len * sizeof (float));
1265 }
static int ResamplerPadding(const int inrate, const int outrate)
Definition: SDL_audiocvt.c:468
void * resampler_state
GLenum GLsizei len
Uint8 pre_resample_channels
#define SDL_memset

◆ SDL_SupportedAudioFormat()

static SDL_bool SDL_SupportedAudioFormat ( const SDL_AudioFormat  fmt)
static

Definition at line 816 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().

817 {
818  switch (fmt) {
819  case AUDIO_U8:
820  case AUDIO_S8:
821  case AUDIO_U16LSB:
822  case AUDIO_S16LSB:
823  case AUDIO_U16MSB:
824  case AUDIO_S16MSB:
825  case AUDIO_S32LSB:
826  case AUDIO_S32MSB:
827  case AUDIO_F32LSB:
828  case AUDIO_F32MSB:
829  return SDL_TRUE; /* supported. */
830 
831  default:
832  break;
833  }
834 
835  return SDL_FALSE; /* unsupported. */
836 }
#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 839 of file SDL_audiocvt.c.

References SDL_FALSE, and SDL_TRUE.

Referenced by SDL_BuildAudioCVT().

840 {
841  switch (channels) {
842  case 1: /* mono */
843  case 2: /* stereo */
844  case 4: /* quad */
845  case 6: /* 5.1 */
846  case 8: /* 7.1 */
847  return SDL_TRUE; /* supported. */
848 
849  default:
850  break;
851  }
852 
853  return SDL_FALSE; /* unsupported. */
854 }

Variable Documentation

◆ ResampleFilterSpinlock

SDL_SpinLock ResampleFilterSpinlock = 0
static

Definition at line 425 of file SDL_audiocvt.c.

◆ ResamplerFilter

float* ResamplerFilter = NULL
static

Definition at line 426 of file SDL_audiocvt.c.

◆ ResamplerFilterDifference

float* ResamplerFilterDifference = NULL
static

Definition at line 427 of file SDL_audiocvt.c.