SDL  2.0
SDL_audiocvt.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22 
23 /* Functions for audio drivers to perform runtime conversion of audio format */
24 
25 #include "SDL.h"
26 #include "SDL_audio.h"
27 #include "SDL_audio_c.h"
28 
29 #include "SDL_loadso.h"
30 #include "SDL_assert.h"
31 #include "../SDL_dataqueue.h"
32 #include "SDL_cpuinfo.h"
33 
34 #ifdef __SSE3__
35 #define HAVE_SSE3_INTRINSICS 1
36 #endif
37 
38 #if HAVE_SSE3_INTRINSICS
39 /* Convert from stereo to mono. Average left and right. */
40 static void SDLCALL
41 SDL_ConvertStereoToMono_SSE3(SDL_AudioCVT * cvt, SDL_AudioFormat format)
42 {
43  float *dst = (float *) cvt->buf;
44  const float *src = dst;
45  int i = cvt->len_cvt / 8;
46 
47  LOG_DEBUG_CONVERT("stereo", "mono (using SSE3)");
48  SDL_assert(format == AUDIO_F32SYS);
49 
50  /* We can only do this if dst is aligned to 16 bytes; since src is the
51  same pointer and it moves by 2, it can't be forcibly aligned. */
52  if ((((size_t) dst) & 15) == 0) {
53  /* Aligned! Do SSE blocks as long as we have 16 bytes available. */
54  const __m128 divby2 = _mm_set1_ps(0.5f);
55  while (i >= 4) { /* 4 * float32 */
56  _mm_store_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_load_ps(src), _mm_load_ps(src+4)), divby2));
57  i -= 4; src += 8; dst += 4;
58  }
59  }
60 
61  /* Finish off any leftovers with scalar operations. */
62  while (i) {
63  *dst = (src[0] + src[1]) * 0.5f;
64  dst++; i--; src += 2;
65  }
66 
67  cvt->len_cvt /= 2;
68  if (cvt->filters[++cvt->filter_index]) {
69  cvt->filters[cvt->filter_index] (cvt, format);
70  }
71 }
72 #endif
73 
74 /* Convert from stereo to mono. Average left and right. */
75 static void SDLCALL
77 {
78  float *dst = (float *) cvt->buf;
79  const float *src = dst;
80  int i;
81 
82  LOG_DEBUG_CONVERT("stereo", "mono");
83  SDL_assert(format == AUDIO_F32SYS);
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 }
94 
95 
96 /* Convert from 5.1 to stereo. Average left and right, distribute center, discard LFE. */
97 static void SDLCALL
99 {
100  float *dst = (float *) cvt->buf;
101  const float *src = dst;
102  int i;
103 
104  LOG_DEBUG_CONVERT("5.1", "stereo");
105  SDL_assert(format == AUDIO_F32SYS);
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 }
119 
120 
121 /* Convert from quad to stereo. Average left and right. */
122 static void SDLCALL
124 {
125  float *dst = (float *) cvt->buf;
126  const float *src = dst;
127  int i;
128 
129  LOG_DEBUG_CONVERT("quad", "stereo");
130  SDL_assert(format == AUDIO_F32SYS);
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 }
142 
143 
144 /* Convert from 7.1 to 5.1. Distribute sides across front and back. */
145 static void SDLCALL
147 {
148  float *dst = (float *) cvt->buf;
149  const float *src = dst;
150  int i;
151 
152  LOG_DEBUG_CONVERT("7.1", "5.1");
153  SDL_assert(format == AUDIO_F32SYS);
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 }
172 
173 
174 /* Convert from 5.1 to quad. Distribute center across front, discard LFE. */
175 static void SDLCALL
177 {
178  float *dst = (float *) cvt->buf;
179  const float *src = dst;
180  int i;
181 
182  LOG_DEBUG_CONVERT("5.1", "quad");
183  SDL_assert(format == AUDIO_F32SYS);
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 }
201 
202 
203 /* Upmix mono to stereo (by duplication) */
204 static void SDLCALL
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");
212  SDL_assert(format == AUDIO_F32SYS);
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 }
225 
226 
227 /* Upmix stereo to a pseudo-5.1 stream */
228 static void SDLCALL
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");
237  SDL_assert(format == AUDIO_F32SYS);
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 }
259 
260 
261 /* Upmix quad to a pseudo-5.1 stream */
262 static void SDLCALL
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");
271  SDL_assert(format == AUDIO_F32SYS);
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 }
296 
297 
298 /* Upmix stereo to a pseudo-4.0 stream (by duplication) */
299 static void SDLCALL
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");
308  SDL_assert(format == AUDIO_F32SYS);
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 }
326 
327 
328 /* Upmix 5.1 to 7.1 */
329 static void SDLCALL
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");
338  SDL_assert(format == AUDIO_F32SYS);
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 }
371 
372 /* SDL's resampler uses a "bandlimited interpolation" algorithm:
373  https://ccrma.stanford.edu/~jos/resample/ */
374 
375 #define RESAMPLER_ZERO_CROSSINGS 5
376 #define RESAMPLER_BITS_PER_SAMPLE 16
377 #define RESAMPLER_SAMPLES_PER_ZERO_CROSSING (1 << ((RESAMPLER_BITS_PER_SAMPLE / 2) + 1))
378 #define RESAMPLER_FILTER_SIZE ((RESAMPLER_SAMPLES_PER_ZERO_CROSSING * RESAMPLER_ZERO_CROSSINGS) + 1)
379 
380 /* This is a "modified" bessel function, so you can't use POSIX j0() */
381 static double
382 bessel(const double x)
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 }
401 
402 /* build kaiser table with cardinal sine applied to it, and array of differences between elements. */
403 static void
404 kaiser_and_sinc(float *table, float *diffs, const int tablelen, const double beta)
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 }
423 
424 
426 static float *ResamplerFilter = NULL;
428 
429 int
431 {
432  SDL_AtomicLock(&ResampleFilterSpinlock);
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) {
441  SDL_AtomicUnlock(&ResampleFilterSpinlock);
442  return SDL_OutOfMemory();
443  }
444 
445  ResamplerFilterDifference = (float *) SDL_malloc(alloclen);
446  if (!ResamplerFilterDifference) {
447  SDL_free(ResamplerFilter);
448  ResamplerFilter = NULL;
449  SDL_AtomicUnlock(&ResampleFilterSpinlock);
450  return SDL_OutOfMemory();
451  }
452  kaiser_and_sinc(ResamplerFilter, ResamplerFilterDifference, RESAMPLER_FILTER_SIZE, beta);
453  }
454  SDL_AtomicUnlock(&ResampleFilterSpinlock);
455  return 0;
456 }
457 
458 void
460 {
461  SDL_free(ResamplerFilter);
462  SDL_free(ResamplerFilterDifference);
463  ResamplerFilter = NULL;
464  ResamplerFilterDifference = NULL;
465 }
466 
467 static int
468 ResamplerPadding(const int inrate, const int outrate)
469 {
470  return (inrate > outrate) ? (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate))) : RESAMPLER_SAMPLES_PER_ZERO_CROSSING;
471 }
472 
473 /* lpadding and rpadding are expected to be buffers of (ResamplePadding(inrate, outrate) * chans * sizeof (float)) bytes. */
474 static int
475 SDL_ResampleAudio(const int chans, const int inrate, const int outrate,
476  float *lpadding, float *rpadding, const float *inbuf,
477  const int inbuflen, float *outbuf, const int outbuflen)
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 }
528 
529 int
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 }
551 
552 static void SDLCALL
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. */
581  if (format & SDL_AUDIO_MASK_ENDIAN) {
582  format &= ~SDL_AUDIO_MASK_ENDIAN;
583  } else {
584  format |= SDL_AUDIO_MASK_ENDIAN;
585  }
586  cvt->filters[cvt->filter_index](cvt, format);
587  }
588 }
589 
590 static int
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 }
603 
604 static int
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 }
650 
651 static int
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 }
695 
696 static void
697 SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format)
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 
714  SDL_assert(format == AUDIO_F32SYS);
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 }
734 
735 /* !!! FIXME: We only have this macro salsa because SDL_AudioCVT doesn't
736  !!! FIXME: store channel info, so we have to have function entry
737  !!! FIXME: points for each supported channel count and multiple
738  !!! FIXME: vs arbitrary. When we rev the ABI, clean this up. */
739 #define RESAMPLER_FUNCS(chans) \
740  static void SDLCALL \
741  SDL_ResampleCVT_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
742  SDL_ResampleCVT(cvt, chans, format); \
743  }
749 #undef RESAMPLER_FUNCS
750 
751 static SDL_AudioFilter
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 }
765 
766 static int
768  const int src_rate, const int dst_rate)
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  }
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 }
814 
815 static SDL_bool
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 }
837 
838 static SDL_bool
839 SDL_SupportedChannelCount(const int channels)
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 }
855 
856 
857 /* Creates a set of audio filters to convert from one format to another.
858  Returns 0 if no conversion is needed, 1 if the audio filter is set up,
859  or -1 if an error like invalid parameter, unsupported format, etc. occurred.
860 */
861 
862 int
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 }
1069 
1070 typedef int (*SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen);
1073 
1075 {
1079  Uint8 *work_buffer_base; /* maybe unaligned pointer from SDL_realloc(). */
1089  double rate_incr;
1096 };
1097 
1098 static Uint8 *
1099 EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen)
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 }
1120 
1121 #ifdef HAVE_LIBSAMPLERATE_H
1122 static int
1123 SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
1124 {
1125  const float *inbuf = (const float *) _inbuf;
1126  float *outbuf = (float *) _outbuf;
1127  const int framelen = sizeof(float) * stream->pre_resample_channels;
1128  SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
1129  SRC_DATA data;
1130  int result;
1131 
1132  if (inbuf == ((const float *) outbuf)) { /* libsamplerate can't work in-place. */
1133  Uint8 *ptr = EnsureStreamBufferSize(stream, inbuflen + outbuflen);
1134  if (ptr == NULL) {
1135  SDL_OutOfMemory();
1136  return 0;
1137  }
1138  SDL_memcpy(ptr + outbuflen, ptr, inbuflen);
1139  inbuf = (const float *) (ptr + outbuflen);
1140  outbuf = (float *) ptr;
1141  }
1142 
1143  data.data_in = (float *)inbuf; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */
1144  data.input_frames = inbuflen / framelen;
1145  data.input_frames_used = 0;
1146 
1147  data.data_out = outbuf;
1148  data.output_frames = outbuflen / framelen;
1149 
1150  data.end_of_input = 0;
1151  data.src_ratio = stream->rate_incr;
1152 
1153  result = SRC_src_process(state, &data);
1154  if (result != 0) {
1155  SDL_SetError("src_process() failed: %s", SRC_src_strerror(result));
1156  return 0;
1157  }
1158 
1159  /* If this fails, we need to store them off somewhere */
1160  SDL_assert(data.input_frames_used == data.input_frames);
1161 
1162  return data.output_frames_gen * (sizeof(float) * stream->pre_resample_channels);
1163 }
1164 
1165 static void
1166 SDL_ResetAudioStreamResampler_SRC(SDL_AudioStream *stream)
1167 {
1168  SRC_src_reset((SRC_STATE *)stream->resampler_state);
1169 }
1170 
1171 static void
1172 SDL_CleanupAudioStreamResampler_SRC(SDL_AudioStream *stream)
1173 {
1174  SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
1175  if (state) {
1176  SRC_src_delete(state);
1177  }
1178 
1179  stream->resampler_state = NULL;
1180  stream->resampler_func = NULL;
1181  stream->reset_resampler_func = NULL;
1182  stream->cleanup_resampler_func = NULL;
1183 }
1184 
1185 static SDL_bool
1186 SetupLibSampleRateResampling(SDL_AudioStream *stream)
1187 {
1188  int result = 0;
1189  SRC_STATE *state = NULL;
1190 
1191  if (SRC_available) {
1192  state = SRC_src_new(SRC_converter, stream->pre_resample_channels, &result);
1193  if (!state) {
1194  SDL_SetError("src_new() failed: %s", SRC_src_strerror(result));
1195  }
1196  }
1197 
1198  if (!state) {
1199  SDL_CleanupAudioStreamResampler_SRC(stream);
1200  return SDL_FALSE;
1201  }
1202 
1203  stream->resampler_state = state;
1204  stream->resampler_func = SDL_ResampleAudioStream_SRC;
1205  stream->reset_resampler_func = SDL_ResetAudioStreamResampler_SRC;
1206  stream->cleanup_resampler_func = SDL_CleanupAudioStreamResampler_SRC;
1207 
1208  return SDL_TRUE;
1209 }
1210 #endif /* HAVE_LIBSAMPLERATE_H */
1211 
1212 
1213 static int
1214 SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
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 }
1255 
1256 static void
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 }
1266 
1267 static void
1269 {
1270  SDL_free(stream->resampler_state);
1271 }
1272 
1275  const Uint8 src_channels,
1276  const int src_rate,
1278  const Uint8 dst_channels,
1279  const int dst_rate)
1280 {
1281  const int packetlen = 4096; /* !!! FIXME: good enough for now. */
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;
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 }
1364 
1365 int
1366 SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _buflen)
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 }
1442 
1443 void
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 }
1455 
1456 
1457 /* get converted/resampled data from the stream */
1458 int
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 }
1473 
1474 /* number of converted/resampled bytes available */
1475 int
1477 {
1478  return stream ? (int) SDL_CountDataQueue(stream->queue) : 0;
1479 }
1480 
1481 /* dispose of a stream */
1482 void
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 }
1494 
1495 /* vi: set ts=4 sw=4 expandtab: */
1496 
static SDL_AudioFilter ChooseCVTResampler(const int dst_channels)
Definition: SDL_audiocvt.c:752
static int ResamplerPadding(const int inrate, const int outrate)
Definition: SDL_audiocvt.c:468
int SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, const Uint32 len)
#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING
Definition: SDL_audiocvt.c:377
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
int SDL_AudioStreamAvailable(SDL_AudioStream *stream)
void SDL_FreeResampleFilter(void)
Definition: SDL_audiocvt.c:459
void(* SDL_CleanupAudioStreamResamplerFunc)(SDL_AudioStream *stream)
#define SDL_AUDIOCVT_MAX_FILTERS
Upper limit of filters in SDL_AudioCVT.
Definition: SDL_audio.h:193
#define SDL_min(x, y)
Definition: SDL_stdinc.h:359
static void SDL_Convert71To51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:146
#define AUDIO_S32MSB
Definition: SDL_audio.h:104
#define SDL_ceil
GLenum GLsizei GLenum GLenum const void * table
int SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _buflen)
SDL_AudioCVT cvt_before_resampling
GLuint64EXT * result
#define SDL_sinf
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
int SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
GLenum GLenum dst
#define SDL_AtomicLock
#define SDL_AUDIO_ISBIGENDIAN(x)
Definition: SDL_audio.h:77
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
void SDL_ChooseAudioConverters(void)
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
Uint8 * buf
Definition: SDL_audio.h:222
SDL_AudioCVT cvt_after_resampling
void * resampler_state
SDL_AudioFormat src_format
SDL_AudioFilter SDL_Convert_F32_to_S32
int filter_index
Definition: SDL_audio.h:228
static void SDL_Convert51ToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:98
struct xkb_state * state
static SDL_bool SDL_SupportedAudioFormat(const SDL_AudioFormat fmt)
Definition: SDL_audiocvt.c:816
double len_ratio
Definition: SDL_audio.h:226
SDL_AudioFilter SDL_Convert_S16_to_F32
SDL_AudioFilter SDL_Convert_U16_to_F32
SDL_DataQueue * SDL_NewDataQueue(const size_t _packetlen, const size_t initialslack)
Definition: SDL_dataqueue.c:58
#define CASESWAP(b)
static void SDL_ConvertStereoToQuad(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:300
GLfloat f
#define SDL_LIL_ENDIAN
Definition: SDL_endian.h:37
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
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
#define SDL_HasSSE3
GLintptr offset
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
static SDL_SpinLock ResampleFilterSpinlock
Definition: SDL_audiocvt.c:425
static float * ResamplerFilter
Definition: SDL_audiocvt.c:426
void SDL_FreeAudioStream(SDL_AudioStream *stream)
static void SDL_Convert51ToQuad(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:176
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:169
#define SDL_AUDIO_MASK_ENDIAN
Definition: SDL_audio.h:73
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
#define SDL_realloc
static int SDL_BuildAudioTypeCVTToFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat src_fmt)
Definition: SDL_audiocvt.c:605
GLenum src
#define SDL_zerop(x)
Definition: SDL_stdinc.h:370
static void SDL_Convert_Byteswap(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:553
static void kaiser_and_sinc(float *table, float *diffs, const int tablelen, const double beta)
Definition: SDL_audiocvt.c:404
static Uint8 * EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen)
GLenum GLsizei len
static float * ResamplerFilterDifference
Definition: SDL_audiocvt.c:427
A structure to hold a set of audio conversion filters and buffers.
Definition: SDL_audio.h:216
#define AUDIO_F32MSB
Definition: SDL_audio.h:113
#define SDL_AtomicUnlock
static double bessel(const double x)
Definition: SDL_audiocvt.c:382
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
#define SDL_AUDIO_ISFLOAT(x)
Definition: SDL_audio.h:76
unsigned int size_t
SDL_bool retval
#define AUDIO_U8
Definition: SDL_audio.h:89
SDL_AudioFormat dst_format
static void SDL_Convert51To71(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:330
static void SDL_ResetAudioStreamResampler(SDL_AudioStream *stream)
#define SDL_memcpy
static int SDL_BuildAudioResampleCVT(SDL_AudioCVT *cvt, const int dst_channels, const int src_rate, const int dst_rate)
Definition: SDL_audiocvt.c:767
void * SDL_calloc(size_t nmemb, size_t size)
int SDL_PrepareResampleFilter(void)
Definition: SDL_audiocvt.c:430
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:227
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
GLuint GLuint stream
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:153
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:338
void SDL_free(void *mem)
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
#define AUDIO_F32LSB
Definition: SDL_audio.h:112
SDL_ResampleAudioStreamFunc resampler_func
void(* SDL_ResetAudioStreamResamplerFunc)(SDL_AudioStream *stream)
#define AUDIO_S32
Definition: SDL_audio.h:105
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
int SDL_ConvertAudio(SDL_AudioCVT *cvt)
Definition: SDL_audiocvt.c:530
#define SDL_pow
static void SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format)
Definition: SDL_audiocvt.c:697
SDL_AudioFilter SDL_Convert_F32_to_S8
SDL_CleanupAudioStreamResamplerFunc cleanup_resampler_func
size_t SDL_ReadFromDataQueue(SDL_DataQueue *queue, void *_buf, const size_t _len)
static void SDL_ConvertQuadToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:123
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
#define SDL_zero(x)
Definition: SDL_stdinc.h:369
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)
#define RESAMPLER_FUNCS(chans)
Definition: SDL_audiocvt.c:739
SDL_AudioFormat src_format
Definition: SDL_audio.h:219
GLenum GLuint GLenum GLsizei const GLchar * buf
static int SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
#define RESAMPLER_FILTER_SIZE
Definition: SDL_audiocvt.c:378
SDL_ResetAudioStreamResamplerFunc reset_resampler_func
SDL_AudioFilter SDL_Convert_F32_to_U8
void(* SDL_AudioFilter)(struct SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audio.h:183
SDL_AudioFilter SDL_Convert_S8_to_F32
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
static void SDL_ConvertQuadTo51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:263
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_AudioFilter SDL_Convert_U8_to_F32
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
static SDL_bool SDL_SupportedChannelCount(const int channels)
Definition: SDL_audiocvt.c:839
#define SDL_SetError
void SDL_AudioStreamClear(SDL_AudioStream *stream)
void SDL_ClearDataQueue(SDL_DataQueue *queue, const size_t slack)
Definition: SDL_dataqueue.c:98
SDL_AudioFormat dst_format
Definition: SDL_audio.h:220
Uint8 pre_resample_channels
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
SDL_AudioFilter SDL_Convert_F32_to_U16
SDL_DataQueue * queue
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 void
static void SDL_ConvertMonoToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:205
double rate_incr
Definition: SDL_audio.h:221
#define AUDIO_S16
Definition: SDL_audio.h:96
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
Uint8 * work_buffer_base
size_t SDL_CountDataQueue(SDL_DataQueue *queue)
static void SDL_CleanupAudioStreamResampler(SDL_AudioStream *stream)
#define SDL_sqrt
static int SDL_AddAudioCVTFilter(SDL_AudioCVT *cvt, const SDL_AudioFilter filter)
Definition: SDL_audiocvt.c:591
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:161
static int SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt)
Definition: SDL_audiocvt.c:652
#define SDL_malloc
static void SDL_ConvertStereoTo51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:229
int SDL_SpinLock
Definition: SDL_atomic.h:89
void SDL_FreeDataQueue(SDL_DataQueue *queue)
Definition: SDL_dataqueue.c:88
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:339
#define AUDIO_U16
Definition: SDL_audio.h:95
SDL_AudioFilter SDL_Convert_S32_to_F32
#define AUDIO_S8
Definition: SDL_audio.h:90
#define SDLCALL
Definition: SDL_internal.h:45
#define SDL_BYTEORDER
SDL_AudioFilter SDL_Convert_F32_to_S16
#define SDL_memset
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
#define AUDIO_U16MSB
Definition: SDL_audio.h:93
int(* SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen)