SDL  2.0
SDL_audiocvt.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2019 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 /* FIXME: Channel weights when converting from more channels to fewer may need to be adjusted, see https://msdn.microsoft.com/en-us/library/windows/desktop/ff819070(v=vs.85).aspx
26 */
27 
28 #include "SDL.h"
29 #include "SDL_audio.h"
30 #include "SDL_audio_c.h"
31 
32 #include "SDL_loadso.h"
33 #include "SDL_assert.h"
34 #include "../SDL_dataqueue.h"
35 #include "SDL_cpuinfo.h"
36 
37 #define DEBUG_AUDIOSTREAM 0
38 
39 #ifdef __SSE3__
40 #define HAVE_SSE3_INTRINSICS 1
41 #endif
42 
43 #if HAVE_SSE3_INTRINSICS
44 /* Convert from stereo to mono. Average left and right. */
45 static void SDLCALL
46 SDL_ConvertStereoToMono_SSE3(SDL_AudioCVT * cvt, SDL_AudioFormat format)
47 {
48  float *dst = (float *) cvt->buf;
49  const float *src = dst;
50  int i = cvt->len_cvt / 8;
51 
52  LOG_DEBUG_CONVERT("stereo", "mono (using SSE3)");
54 
55  /* We can only do this if dst is aligned to 16 bytes; since src is the
56  same pointer and it moves by 2, it can't be forcibly aligned. */
57  if ((((size_t) dst) & 15) == 0) {
58  /* Aligned! Do SSE blocks as long as we have 16 bytes available. */
59  const __m128 divby2 = _mm_set1_ps(0.5f);
60  while (i >= 4) { /* 4 * float32 */
61  _mm_store_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_load_ps(src), _mm_load_ps(src+4)), divby2));
62  i -= 4; src += 8; dst += 4;
63  }
64  }
65 
66  /* Finish off any leftovers with scalar operations. */
67  while (i) {
68  *dst = (src[0] + src[1]) * 0.5f;
69  dst++; i--; src += 2;
70  }
71 
72  cvt->len_cvt /= 2;
73  if (cvt->filters[++cvt->filter_index]) {
74  cvt->filters[cvt->filter_index] (cvt, format);
75  }
76 }
77 #endif
78 
79 /* Convert from stereo to mono. Average left and right. */
80 static void SDLCALL
82 {
83  float *dst = (float *) cvt->buf;
84  const float *src = dst;
85  int i;
86 
87  LOG_DEBUG_CONVERT("stereo", "mono");
89 
90  for (i = cvt->len_cvt / 8; i; --i, src += 2) {
91  *(dst++) = (src[0] + src[1]) * 0.5f;
92  }
93 
94  cvt->len_cvt /= 2;
95  if (cvt->filters[++cvt->filter_index]) {
96  cvt->filters[cvt->filter_index] (cvt, format);
97  }
98 }
99 
100 
101 /* Convert from 5.1 to stereo. Average left and right, distribute center, discard LFE. */
102 static void SDLCALL
104 {
105  float *dst = (float *) cvt->buf;
106  const float *src = dst;
107  int i;
108 
109  LOG_DEBUG_CONVERT("5.1", "stereo");
111 
112  /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */
113  for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 2) {
114  const float front_center_distributed = src[2] * 0.5f;
115  dst[0] = (src[0] + front_center_distributed + src[4]) / 2.5f; /* left */
116  dst[1] = (src[1] + front_center_distributed + src[5]) / 2.5f; /* right */
117  }
118 
119  cvt->len_cvt /= 3;
120  if (cvt->filters[++cvt->filter_index]) {
121  cvt->filters[cvt->filter_index] (cvt, format);
122  }
123 }
124 
125 
126 /* Convert from quad to stereo. Average left and right. */
127 static void SDLCALL
129 {
130  float *dst = (float *) cvt->buf;
131  const float *src = dst;
132  int i;
133 
134  LOG_DEBUG_CONVERT("quad", "stereo");
136 
137  for (i = cvt->len_cvt / (sizeof (float) * 4); i; --i, src += 4, dst += 2) {
138  dst[0] = (src[0] + src[2]) * 0.5f; /* left */
139  dst[1] = (src[1] + src[3]) * 0.5f; /* right */
140  }
141 
142  cvt->len_cvt /= 2;
143  if (cvt->filters[++cvt->filter_index]) {
144  cvt->filters[cvt->filter_index] (cvt, format);
145  }
146 }
147 
148 
149 /* Convert from 7.1 to 5.1. Distribute sides across front and back. */
150 static void SDLCALL
152 {
153  float *dst = (float *) cvt->buf;
154  const float *src = dst;
155  int i;
156 
157  LOG_DEBUG_CONVERT("7.1", "5.1");
159 
160  for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8, dst += 6) {
161  const float surround_left_distributed = src[6] * 0.5f;
162  const float surround_right_distributed = src[7] * 0.5f;
163  dst[0] = (src[0] + surround_left_distributed) / 1.5f; /* FL */
164  dst[1] = (src[1] + surround_right_distributed) / 1.5f; /* FR */
165  dst[2] = src[2] / 1.5f; /* CC */
166  dst[3] = src[3] / 1.5f; /* LFE */
167  dst[4] = (src[4] + surround_left_distributed) / 1.5f; /* BL */
168  dst[5] = (src[5] + surround_right_distributed) / 1.5f; /* BR */
169  }
170 
171  cvt->len_cvt /= 8;
172  cvt->len_cvt *= 6;
173  if (cvt->filters[++cvt->filter_index]) {
174  cvt->filters[cvt->filter_index] (cvt, format);
175  }
176 }
177 
178 
179 /* Convert from 5.1 to quad. Distribute center across front, discard LFE. */
180 static void SDLCALL
182 {
183  float *dst = (float *) cvt->buf;
184  const float *src = dst;
185  int i;
186 
187  LOG_DEBUG_CONVERT("5.1", "quad");
189 
190  /* SDL's 4.0 layout: FL+FR+BL+BR */
191  /* SDL's 5.1 layout: FL+FR+FC+LFE+BL+BR */
192  for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 4) {
193  const float front_center_distributed = src[2] * 0.5f;
194  dst[0] = (src[0] + front_center_distributed) / 1.5f; /* FL */
195  dst[1] = (src[1] + front_center_distributed) / 1.5f; /* FR */
196  dst[2] = src[4] / 1.5f; /* BL */
197  dst[3] = src[5] / 1.5f; /* BR */
198  }
199 
200  cvt->len_cvt /= 6;
201  cvt->len_cvt *= 4;
202  if (cvt->filters[++cvt->filter_index]) {
203  cvt->filters[cvt->filter_index] (cvt, format);
204  }
205 }
206 
207 
208 /* Upmix mono to stereo (by duplication) */
209 static void SDLCALL
211 {
212  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
213  float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
214  int i;
215 
216  LOG_DEBUG_CONVERT("mono", "stereo");
218 
219  for (i = cvt->len_cvt / sizeof (float); i; --i) {
220  src--;
221  dst -= 2;
222  dst[0] = dst[1] = *src;
223  }
224 
225  cvt->len_cvt *= 2;
226  if (cvt->filters[++cvt->filter_index]) {
227  cvt->filters[cvt->filter_index] (cvt, format);
228  }
229 }
230 
231 
232 /* Upmix stereo to a pseudo-5.1 stream */
233 static void SDLCALL
235 {
236  int i;
237  float lf, rf, ce;
238  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
239  float *dst = (float *) (cvt->buf + cvt->len_cvt * 3);
240 
241  LOG_DEBUG_CONVERT("stereo", "5.1");
243 
244  for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) {
245  dst -= 6;
246  src -= 2;
247  lf = src[0];
248  rf = src[1];
249  ce = (lf + rf) * 0.5f;
250  /* !!! FIXME: FL and FR may clip */
251  dst[0] = lf + (lf - ce); /* FL */
252  dst[1] = rf + (rf - ce); /* FR */
253  dst[2] = ce; /* FC */
254  dst[3] = 0; /* LFE (only meant for special LFE effects) */
255  dst[4] = lf; /* BL */
256  dst[5] = rf; /* BR */
257  }
258 
259  cvt->len_cvt *= 3;
260  if (cvt->filters[++cvt->filter_index]) {
261  cvt->filters[cvt->filter_index] (cvt, format);
262  }
263 }
264 
265 
266 /* Upmix quad to a pseudo-5.1 stream */
267 static void SDLCALL
269 {
270  int i;
271  float lf, rf, lb, rb, ce;
272  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
273  float *dst = (float *) (cvt->buf + cvt->len_cvt * 3 / 2);
274 
275  LOG_DEBUG_CONVERT("quad", "5.1");
277  SDL_assert(cvt->len_cvt % (sizeof(float) * 4) == 0);
278 
279  for (i = cvt->len_cvt / (sizeof(float) * 4); i; --i) {
280  dst -= 6;
281  src -= 4;
282  lf = src[0];
283  rf = src[1];
284  lb = src[2];
285  rb = src[3];
286  ce = (lf + rf) * 0.5f;
287  /* !!! FIXME: FL and FR may clip */
288  dst[0] = lf + (lf - ce); /* FL */
289  dst[1] = rf + (rf - ce); /* FR */
290  dst[2] = ce; /* FC */
291  dst[3] = 0; /* LFE (only meant for special LFE effects) */
292  dst[4] = lb; /* BL */
293  dst[5] = rb; /* BR */
294  }
295 
296  cvt->len_cvt = cvt->len_cvt * 3 / 2;
297  if (cvt->filters[++cvt->filter_index]) {
298  cvt->filters[cvt->filter_index] (cvt, format);
299  }
300 }
301 
302 
303 /* Upmix stereo to a pseudo-4.0 stream (by duplication) */
304 static void SDLCALL
306 {
307  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
308  float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
309  float lf, rf;
310  int i;
311 
312  LOG_DEBUG_CONVERT("stereo", "quad");
314 
315  for (i = cvt->len_cvt / (sizeof(float) * 2); i; --i) {
316  dst -= 4;
317  src -= 2;
318  lf = src[0];
319  rf = src[1];
320  dst[0] = lf; /* FL */
321  dst[1] = rf; /* FR */
322  dst[2] = lf; /* BL */
323  dst[3] = rf; /* BR */
324  }
325 
326  cvt->len_cvt *= 2;
327  if (cvt->filters[++cvt->filter_index]) {
328  cvt->filters[cvt->filter_index] (cvt, format);
329  }
330 }
331 
332 
333 /* Upmix 5.1 to 7.1 */
334 static void SDLCALL
336 {
337  float lf, rf, lb, rb, ls, rs;
338  int i;
339  const float *src = (const float *) (cvt->buf + cvt->len_cvt);
340  float *dst = (float *) (cvt->buf + cvt->len_cvt * 4 / 3);
341 
342  LOG_DEBUG_CONVERT("5.1", "7.1");
344  SDL_assert(cvt->len_cvt % (sizeof(float) * 6) == 0);
345 
346  for (i = cvt->len_cvt / (sizeof(float) * 6); i; --i) {
347  dst -= 8;
348  src -= 6;
349  lf = src[0];
350  rf = src[1];
351  lb = src[4];
352  rb = src[5];
353  ls = (lf + lb) * 0.5f;
354  rs = (rf + rb) * 0.5f;
355  /* !!! FIXME: these four may clip */
356  lf += lf - ls;
357  rf += rf - ls;
358  lb += lb - ls;
359  rb += rb - ls;
360  dst[3] = src[3]; /* LFE */
361  dst[2] = src[2]; /* FC */
362  dst[7] = rs; /* SR */
363  dst[6] = ls; /* SL */
364  dst[5] = rb; /* BR */
365  dst[4] = lb; /* BL */
366  dst[1] = rf; /* FR */
367  dst[0] = lf; /* FL */
368  }
369 
370  cvt->len_cvt = cvt->len_cvt * 4 / 3;
371 
372  if (cvt->filters[++cvt->filter_index]) {
373  cvt->filters[cvt->filter_index] (cvt, format);
374  }
375 }
376 
377 /* SDL's resampler uses a "bandlimited interpolation" algorithm:
378  https://ccrma.stanford.edu/~jos/resample/ */
379 
380 #define RESAMPLER_ZERO_CROSSINGS 5
381 #define RESAMPLER_BITS_PER_SAMPLE 16
382 #define RESAMPLER_SAMPLES_PER_ZERO_CROSSING (1 << ((RESAMPLER_BITS_PER_SAMPLE / 2) + 1))
383 #define RESAMPLER_FILTER_SIZE ((RESAMPLER_SAMPLES_PER_ZERO_CROSSING * RESAMPLER_ZERO_CROSSINGS) + 1)
384 
385 /* This is a "modified" bessel function, so you can't use POSIX j0() */
386 static double
387 bessel(const double x)
388 {
389  const double xdiv2 = x / 2.0;
390  double i0 = 1.0f;
391  double f = 1.0f;
392  int i = 1;
393 
394  while (SDL_TRUE) {
395  const double diff = SDL_pow(xdiv2, i * 2) / SDL_pow(f, 2);
396  if (diff < 1.0e-21f) {
397  break;
398  }
399  i0 += diff;
400  i++;
401  f *= (double) i;
402  }
403 
404  return i0;
405 }
406 
407 /* build kaiser table with cardinal sine applied to it, and array of differences between elements. */
408 static void
409 kaiser_and_sinc(float *table, float *diffs, const int tablelen, const double beta)
410 {
411  const int lenm1 = tablelen - 1;
412  const int lenm1div2 = lenm1 / 2;
413  int i;
414 
415  table[0] = 1.0f;
416  for (i = 1; i < tablelen; i++) {
417  const double kaiser = bessel(beta * SDL_sqrt(1.0 - SDL_pow(((i - lenm1) / 2.0) / lenm1div2, 2.0))) / bessel(beta);
418  table[tablelen - i] = (float) kaiser;
419  }
420 
421  for (i = 1; i < tablelen; i++) {
422  const float x = (((float) i) / ((float) RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) * ((float) M_PI);
423  table[i] *= SDL_sinf(x) / x;
424  diffs[i - 1] = table[i] - table[i - 1];
425  }
426  diffs[lenm1] = 0.0f;
427 }
428 
429 
431 static float *ResamplerFilter = NULL;
433 
434 int
436 {
438  if (!ResamplerFilter) {
439  /* if dB > 50, beta=(0.1102 * (dB - 8.7)), according to Matlab. */
440  const double dB = 80.0;
441  const double beta = 0.1102 * (dB - 8.7);
442  const size_t alloclen = RESAMPLER_FILTER_SIZE * sizeof (float);
443 
444  ResamplerFilter = (float *) SDL_malloc(alloclen);
445  if (!ResamplerFilter) {
447  return SDL_OutOfMemory();
448  }
449 
450  ResamplerFilterDifference = (float *) SDL_malloc(alloclen);
455  return SDL_OutOfMemory();
456  }
458  }
460  return 0;
461 }
462 
463 void
465 {
470 }
471 
472 static int
473 ResamplerPadding(const int inrate, const int outrate)
474 {
475  if (inrate == outrate) {
476  return 0;
477  } else if (inrate > outrate) {
478  return (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate)));
479  }
481 }
482 
483 /* lpadding and rpadding are expected to be buffers of (ResamplePadding(inrate, outrate) * chans * sizeof (float)) bytes. */
484 static int
485 SDL_ResampleAudio(const int chans, const int inrate, const int outrate,
486  const float *lpadding, const float *rpadding,
487  const float *inbuf, const int inbuflen,
488  float *outbuf, const int outbuflen)
489 {
490  const double finrate = (double) inrate;
491  const double outtimeincr = 1.0 / ((float) outrate);
492  const double ratio = ((float) outrate) / ((float) inrate);
493  const int paddinglen = ResamplerPadding(inrate, outrate);
494  const int framelen = chans * (int)sizeof (float);
495  const int inframes = inbuflen / framelen;
496  const int wantedoutframes = (int) ((inbuflen / framelen) * ratio); /* outbuflen isn't total to write, it's total available. */
497  const int maxoutframes = outbuflen / framelen;
498  const int outframes = SDL_min(wantedoutframes, maxoutframes);
499  float *dst = outbuf;
500  double outtime = 0.0;
501  int i, j, chan;
502 
503  for (i = 0; i < outframes; i++) {
504  const int srcindex = (int) (outtime * inrate);
505  const double intime = ((double) srcindex) / finrate;
506  const double innexttime = ((double) (srcindex + 1)) / finrate;
507  const double interpolation1 = 1.0 - ((innexttime - outtime) / (innexttime - intime));
508  const int filterindex1 = (int) (interpolation1 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
509  const double interpolation2 = 1.0 - interpolation1;
510  const int filterindex2 = (int) (interpolation2 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
511 
512  for (chan = 0; chan < chans; chan++) {
513  float outsample = 0.0f;
514 
515  /* do this twice to calculate the sample, once for the "left wing" and then same for the right. */
516  /* !!! FIXME: do both wings in one loop */
517  for (j = 0; (filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) {
518  const int srcframe = srcindex - j;
519  /* !!! FIXME: we can bubble this conditional out of here by doing a pre loop. */
520  const float insample = (srcframe < 0) ? lpadding[((paddinglen + srcframe) * chans) + chan] : inbuf[(srcframe * chans) + chan];
521  outsample += (float)(insample * (ResamplerFilter[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation1 * ResamplerFilterDifference[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
522  }
523 
524  for (j = 0; (filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) {
525  const int srcframe = srcindex + 1 + j;
526  /* !!! FIXME: we can bubble this conditional out of here by doing a post loop. */
527  const float insample = (srcframe >= inframes) ? rpadding[((srcframe - inframes) * chans) + chan] : inbuf[(srcframe * chans) + chan];
528  outsample += (float)(insample * (ResamplerFilter[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation2 * ResamplerFilterDifference[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
529  }
530  *(dst++) = outsample;
531  }
532 
533  outtime += outtimeincr;
534  }
535 
536  return outframes * chans * sizeof (float);
537 }
538 
539 int
541 {
542  /* !!! FIXME: (cvt) should be const; stack-copy it here. */
543  /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
544 
545  /* Make sure there's data to convert */
546  if (cvt->buf == NULL) {
547  return SDL_SetError("No buffer allocated for conversion");
548  }
549 
550  /* Return okay if no conversion is necessary */
551  cvt->len_cvt = cvt->len;
552  if (cvt->filters[0] == NULL) {
553  return 0;
554  }
555 
556  /* Set up the conversion and go! */
557  cvt->filter_index = 0;
558  cvt->filters[0] (cvt, cvt->src_format);
559  return 0;
560 }
561 
562 static void SDLCALL
564 {
565 #if DEBUG_CONVERT
566  printf("Converting byte order\n");
567 #endif
568 
569  switch (SDL_AUDIO_BITSIZE(format)) {
570  #define CASESWAP(b) \
571  case b: { \
572  Uint##b *ptr = (Uint##b *) cvt->buf; \
573  int i; \
574  for (i = cvt->len_cvt / sizeof (*ptr); i; --i, ++ptr) { \
575  *ptr = SDL_Swap##b(*ptr); \
576  } \
577  break; \
578  }
579 
580  CASESWAP(16);
581  CASESWAP(32);
582  CASESWAP(64);
583 
584  #undef CASESWAP
585 
586  default: SDL_assert(!"unhandled byteswap datatype!"); break;
587  }
588 
589  if (cvt->filters[++cvt->filter_index]) {
590  /* flip endian flag for data. */
593  } else {
595  }
596  cvt->filters[cvt->filter_index](cvt, format);
597  }
598 }
599 
600 static int
602 {
604  return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS);
605  }
606  if (filter == NULL) {
607  return SDL_SetError("Audio filter pointer is NULL");
608  }
609  cvt->filters[cvt->filter_index++] = filter;
610  cvt->filters[cvt->filter_index] = NULL; /* Moving terminator */
611  return 0;
612 }
613 
614 static int
616 {
617  int retval = 0; /* 0 == no conversion necessary. */
618 
619  if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
621  return -1;
622  }
623  retval = 1; /* added a converter. */
624  }
625 
626  if (!SDL_AUDIO_ISFLOAT(src_fmt)) {
627  const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
628  const Uint16 dst_bitsize = 32;
630 
631  switch (src_fmt & ~SDL_AUDIO_MASK_ENDIAN) {
632  case AUDIO_S8: filter = SDL_Convert_S8_to_F32; break;
633  case AUDIO_U8: filter = SDL_Convert_U8_to_F32; break;
634  case AUDIO_S16: filter = SDL_Convert_S16_to_F32; break;
635  case AUDIO_U16: filter = SDL_Convert_U16_to_F32; break;
636  case AUDIO_S32: filter = SDL_Convert_S32_to_F32; break;
637  default: SDL_assert(!"Unexpected audio format!"); break;
638  }
639 
640  if (!filter) {
641  return SDL_SetError("No conversion from source format to float available");
642  }
643 
644  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
645  return -1;
646  }
647  if (src_bitsize < dst_bitsize) {
648  const int mult = (dst_bitsize / src_bitsize);
649  cvt->len_mult *= mult;
650  cvt->len_ratio *= mult;
651  } else if (src_bitsize > dst_bitsize) {
652  cvt->len_ratio /= (src_bitsize / dst_bitsize);
653  }
654 
655  retval = 1; /* added a converter. */
656  }
657 
658  return retval;
659 }
660 
661 static int
663 {
664  int retval = 0; /* 0 == no conversion necessary. */
665 
666  if (!SDL_AUDIO_ISFLOAT(dst_fmt)) {
667  const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
668  const Uint16 src_bitsize = 32;
670  switch (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN) {
671  case AUDIO_S8: filter = SDL_Convert_F32_to_S8; break;
672  case AUDIO_U8: filter = SDL_Convert_F32_to_U8; break;
673  case AUDIO_S16: filter = SDL_Convert_F32_to_S16; break;
674  case AUDIO_U16: filter = SDL_Convert_F32_to_U16; break;
675  case AUDIO_S32: filter = SDL_Convert_F32_to_S32; break;
676  default: SDL_assert(!"Unexpected audio format!"); break;
677  }
678 
679  if (!filter) {
680  return SDL_SetError("No conversion from float to destination format available");
681  }
682 
683  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
684  return -1;
685  }
686  if (src_bitsize < dst_bitsize) {
687  const int mult = (dst_bitsize / src_bitsize);
688  cvt->len_mult *= mult;
689  cvt->len_ratio *= mult;
690  } else if (src_bitsize > dst_bitsize) {
691  cvt->len_ratio /= (src_bitsize / dst_bitsize);
692  }
693  retval = 1; /* added a converter. */
694  }
695 
696  if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
698  return -1;
699  }
700  retval = 1; /* added a converter. */
701  }
702 
703  return retval;
704 }
705 
706 static void
707 SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format)
708 {
709  /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator).
710  !!! FIXME in 2.1: We need to store data for this resampler, because the cvt structure doesn't store the original sample rates,
711  !!! FIXME in 2.1: so we steal the ninth and tenth slot. :( */
712  const int inrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1];
713  const int outrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS];
714  const float *src = (const float *) cvt->buf;
715  const int srclen = cvt->len_cvt;
716  /*float *dst = (float *) cvt->buf;
717  const int dstlen = (cvt->len * cvt->len_mult);*/
718  /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
719  float *dst = (float *) (cvt->buf + srclen);
720  const int dstlen = (cvt->len * cvt->len_mult) - srclen;
721  const int requestedpadding = ResamplerPadding(inrate, outrate);
722  int paddingsamples;
723  float *padding;
724 
725  if (requestedpadding < SDL_MAX_SINT32 / chans) {
726  paddingsamples = requestedpadding * chans;
727  } else {
728  paddingsamples = 0;
729  }
731 
732  /* we keep no streaming state here, so pad with silence on both ends. */
733  padding = (float *) SDL_calloc(paddingsamples ? paddingsamples : 1, sizeof (float));
734  if (!padding) {
735  SDL_OutOfMemory();
736  return;
737  }
738 
739  cvt->len_cvt = SDL_ResampleAudio(chans, inrate, outrate, padding, padding, src, srclen, dst, dstlen);
740 
741  SDL_free(padding);
742 
743  SDL_memmove(cvt->buf, dst, cvt->len_cvt); /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
744 
745  if (cvt->filters[++cvt->filter_index]) {
746  cvt->filters[cvt->filter_index](cvt, format);
747  }
748 }
749 
750 /* !!! FIXME: We only have this macro salsa because SDL_AudioCVT doesn't
751  !!! FIXME: store channel info, so we have to have function entry
752  !!! FIXME: points for each supported channel count and multiple
753  !!! FIXME: vs arbitrary. When we rev the ABI, clean this up. */
754 #define RESAMPLER_FUNCS(chans) \
755  static void SDLCALL \
756  SDL_ResampleCVT_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
757  SDL_ResampleCVT(cvt, chans, format); \
758  }
764 #undef RESAMPLER_FUNCS
765 
766 static SDL_AudioFilter
767 ChooseCVTResampler(const int dst_channels)
768 {
769  switch (dst_channels) {
770  case 1: return SDL_ResampleCVT_c1;
771  case 2: return SDL_ResampleCVT_c2;
772  case 4: return SDL_ResampleCVT_c4;
773  case 6: return SDL_ResampleCVT_c6;
774  case 8: return SDL_ResampleCVT_c8;
775  default: break;
776  }
777 
778  return NULL;
779 }
780 
781 static int
782 SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, const int dst_channels,
783  const int src_rate, const int dst_rate)
784 {
786 
787  if (src_rate == dst_rate) {
788  return 0; /* no conversion necessary. */
789  }
790 
791  filter = ChooseCVTResampler(dst_channels);
792  if (filter == NULL) {
793  return SDL_SetError("No conversion available for these rates");
794  }
795 
796  if (SDL_PrepareResampleFilter() < 0) {
797  return -1;
798  }
799 
800  /* Update (cvt) with filter details... */
801  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
802  return -1;
803  }
804 
805  /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator).
806  !!! FIXME in 2.1: We need to store data for this resampler, because the cvt structure doesn't store the original sample rates,
807  !!! FIXME in 2.1: so we steal the ninth and tenth slot. :( */
808  if (cvt->filter_index >= (SDL_AUDIOCVT_MAX_FILTERS-2)) {
809  return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS-2);
810  }
811  cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1] = (SDL_AudioFilter) (size_t) src_rate;
812  cvt->filters[SDL_AUDIOCVT_MAX_FILTERS] = (SDL_AudioFilter) (size_t) dst_rate;
813 
814  if (src_rate < dst_rate) {
815  const double mult = ((double) dst_rate) / ((double) src_rate);
816  cvt->len_mult *= (int) SDL_ceil(mult);
817  cvt->len_ratio *= mult;
818  } else {
819  cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
820  }
821 
822  /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
823  /* the buffer is big enough to hold the destination now, but
824  we need it large enough to hold a separate scratch buffer. */
825  cvt->len_mult *= 2;
826 
827  return 1; /* added a converter. */
828 }
829 
830 static SDL_bool
832 {
833  switch (fmt) {
834  case AUDIO_U8:
835  case AUDIO_S8:
836  case AUDIO_U16LSB:
837  case AUDIO_S16LSB:
838  case AUDIO_U16MSB:
839  case AUDIO_S16MSB:
840  case AUDIO_S32LSB:
841  case AUDIO_S32MSB:
842  case AUDIO_F32LSB:
843  case AUDIO_F32MSB:
844  return SDL_TRUE; /* supported. */
845 
846  default:
847  break;
848  }
849 
850  return SDL_FALSE; /* unsupported. */
851 }
852 
853 static SDL_bool
854 SDL_SupportedChannelCount(const int channels)
855 {
856  switch (channels) {
857  case 1: /* mono */
858  case 2: /* stereo */
859  case 4: /* quad */
860  case 6: /* 5.1 */
861  case 8: /* 7.1 */
862  return SDL_TRUE; /* supported. */
863 
864  default:
865  break;
866  }
867 
868  return SDL_FALSE; /* unsupported. */
869 }
870 
871 
872 /* Creates a set of audio filters to convert from one format to another.
873  Returns 0 if no conversion is needed, 1 if the audio filter is set up,
874  or -1 if an error like invalid parameter, unsupported format, etc. occurred.
875 */
876 
877 int
879  SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
880  SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
881 {
882  /* Sanity check target pointer */
883  if (cvt == NULL) {
884  return SDL_InvalidParamError("cvt");
885  }
886 
887  /* Make sure we zero out the audio conversion before error checking */
888  SDL_zerop(cvt);
889 
890  if (!SDL_SupportedAudioFormat(src_fmt)) {
891  return SDL_SetError("Invalid source format");
892  } else if (!SDL_SupportedAudioFormat(dst_fmt)) {
893  return SDL_SetError("Invalid destination format");
894  } else if (!SDL_SupportedChannelCount(src_channels)) {
895  return SDL_SetError("Invalid source channels");
896  } else if (!SDL_SupportedChannelCount(dst_channels)) {
897  return SDL_SetError("Invalid destination channels");
898  } else if (src_rate <= 0) {
899  return SDL_SetError("Source rate is equal to or less than zero");
900  } else if (dst_rate <= 0) {
901  return SDL_SetError("Destination rate is equal to or less than zero");
902  } else if (src_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
903  return SDL_SetError("Source rate is too high");
904  } else if (dst_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
905  return SDL_SetError("Destination rate is too high");
906  }
907 
908 #if DEBUG_CONVERT
909  printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
910  src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
911 #endif
912 
913  /* Start off with no conversion necessary */
914  cvt->src_format = src_fmt;
915  cvt->dst_format = dst_fmt;
916  cvt->needed = 0;
917  cvt->filter_index = 0;
918  SDL_zero(cvt->filters);
919  cvt->len_mult = 1;
920  cvt->len_ratio = 1.0;
921  cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
922 
923  /* Make sure we've chosen audio conversion functions (MMX, scalar, etc.) */
925 
926  /* Type conversion goes like this now:
927  - byteswap to CPU native format first if necessary.
928  - convert to native Float32 if necessary.
929  - resample and change channel count if necessary.
930  - convert back to native format.
931  - byteswap back to foreign format if necessary.
932 
933  The expectation is we can process data faster in float32
934  (possibly with SIMD), and making several passes over the same
935  buffer is likely to be CPU cache-friendly, avoiding the
936  biggest performance hit in modern times. Previously we had
937  (script-generated) custom converters for every data type and
938  it was a bloat on SDL compile times and final library size. */
939 
940  /* see if we can skip float conversion entirely. */
941  if (src_rate == dst_rate && src_channels == dst_channels) {
942  if (src_fmt == dst_fmt) {
943  return 0;
944  }
945 
946  /* just a byteswap needed? */
947  if ((src_fmt & ~SDL_AUDIO_MASK_ENDIAN) == (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN)) {
949  return -1;
950  }
951  cvt->needed = 1;
952  return 1;
953  }
954  }
955 
956  /* Convert data types, if necessary. Updates (cvt). */
957  if (SDL_BuildAudioTypeCVTToFloat(cvt, src_fmt) < 0) {
958  return -1; /* shouldn't happen, but just in case... */
959  }
960 
961  /* Channel conversion */
962  if (src_channels < dst_channels) {
963  /* Upmixing */
964  /* Mono -> Stereo [-> ...] */
965  if ((src_channels == 1) && (dst_channels > 1)) {
967  return -1;
968  }
969  cvt->len_mult *= 2;
970  src_channels = 2;
971  cvt->len_ratio *= 2;
972  }
973  /* [Mono ->] Stereo -> 5.1 [-> 7.1] */
974  if ((src_channels == 2) && (dst_channels >= 6)) {
976  return -1;
977  }
978  src_channels = 6;
979  cvt->len_mult *= 3;
980  cvt->len_ratio *= 3;
981  }
982  /* Quad -> 5.1 [-> 7.1] */
983  if ((src_channels == 4) && (dst_channels >= 6)) {
985  return -1;
986  }
987  src_channels = 6;
988  cvt->len_mult = (cvt->len_mult * 3 + 1) / 2;
989  cvt->len_ratio *= 1.5;
990  }
991  /* [[Mono ->] Stereo ->] 5.1 -> 7.1 */
992  if ((src_channels == 6) && (dst_channels == 8)) {
994  return -1;
995  }
996  src_channels = 8;
997  cvt->len_mult = (cvt->len_mult * 4 + 2) / 3;
998  /* Should be numerically exact with every valid input to this
999  function */
1000  cvt->len_ratio = cvt->len_ratio * 4 / 3;
1001  }
1002  /* [Mono ->] Stereo -> Quad */
1003  if ((src_channels == 2) && (dst_channels == 4)) {
1005  return -1;
1006  }
1007  src_channels = 4;
1008  cvt->len_mult *= 2;
1009  cvt->len_ratio *= 2;
1010  }
1011  } else if (src_channels > dst_channels) {
1012  /* Downmixing */
1013  /* 7.1 -> 5.1 [-> Stereo [-> Mono]] */
1014  /* 7.1 -> 5.1 [-> Quad] */
1015  if ((src_channels == 8) && (dst_channels <= 6)) {
1016  if (SDL_AddAudioCVTFilter(cvt, SDL_Convert71To51) < 0) {
1017  return -1;
1018  }
1019  src_channels = 6;
1020  cvt->len_ratio *= 0.75;
1021  }
1022  /* [7.1 ->] 5.1 -> Stereo [-> Mono] */
1023  if ((src_channels == 6) && (dst_channels <= 2)) {
1025  return -1;
1026  }
1027  src_channels = 2;
1028  cvt->len_ratio /= 3;
1029  }
1030  /* 5.1 -> Quad */
1031  if ((src_channels == 6) && (dst_channels == 4)) {
1033  return -1;
1034  }
1035  src_channels = 4;
1036  cvt->len_ratio = cvt->len_ratio * 2 / 3;
1037  }
1038  /* Quad -> Stereo [-> Mono] */
1039  if ((src_channels == 4) && (dst_channels <= 2)) {
1041  return -1;
1042  }
1043  src_channels = 2;
1044  cvt->len_ratio /= 2;
1045  }
1046  /* [... ->] Stereo -> Mono */
1047  if ((src_channels == 2) && (dst_channels == 1)) {
1049 
1050  #if HAVE_SSE3_INTRINSICS
1051  if (SDL_HasSSE3()) {
1052  filter = SDL_ConvertStereoToMono_SSE3;
1053  }
1054  #endif
1055 
1056  if (!filter) {
1058  }
1059 
1060  if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
1061  return -1;
1062  }
1063 
1064  src_channels = 1;
1065  cvt->len_ratio /= 2;
1066  }
1067  }
1068 
1069  if (src_channels != dst_channels) {
1070  /* All combinations of supported channel counts should have been
1071  handled by now, but let's be defensive */
1072  return SDL_SetError("Invalid channel combination");
1073  }
1074 
1075  /* Do rate conversion, if necessary. Updates (cvt). */
1076  if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) < 0) {
1077  return -1; /* shouldn't happen, but just in case... */
1078  }
1079 
1080  /* Move to final data type. */
1081  if (SDL_BuildAudioTypeCVTFromFloat(cvt, dst_fmt) < 0) {
1082  return -1; /* shouldn't happen, but just in case... */
1083  }
1084 
1085  cvt->needed = (cvt->filter_index != 0);
1086  return (cvt->needed);
1087 }
1088 
1089 typedef int (*SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen);
1090 typedef void (*SDL_ResetAudioStreamResamplerFunc)(SDL_AudioStream *stream);
1091 typedef void (*SDL_CleanupAudioStreamResamplerFunc)(SDL_AudioStream *stream);
1092 
1094 {
1102  Uint8 *work_buffer_base; /* maybe unaligned pointer from SDL_realloc(). */
1112  double rate_incr;
1121 };
1122 
1123 static Uint8 *
1124 EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen)
1125 {
1126  Uint8 *ptr;
1127  size_t offset;
1128 
1129  if (stream->work_buffer_len >= newlen) {
1130  ptr = stream->work_buffer_base;
1131  } else {
1132  ptr = (Uint8 *) SDL_realloc(stream->work_buffer_base, newlen + 32);
1133  if (!ptr) {
1134  SDL_OutOfMemory();
1135  return NULL;
1136  }
1137  /* Make sure we're aligned to 16 bytes for SIMD code. */
1138  stream->work_buffer_base = ptr;
1139  stream->work_buffer_len = newlen;
1140  }
1141 
1142  offset = ((size_t) ptr) & 15;
1143  return offset ? ptr + (16 - offset) : ptr;
1144 }
1145 
1146 #ifdef HAVE_LIBSAMPLERATE_H
1147 static int
1148 SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
1149 {
1150  const float *inbuf = (const float *) _inbuf;
1151  float *outbuf = (float *) _outbuf;
1152  const int framelen = sizeof(float) * stream->pre_resample_channels;
1153  SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
1154  SRC_DATA data;
1155  int result;
1156 
1157  SDL_assert(inbuf != ((const float *) outbuf)); /* SDL_AudioStreamPut() shouldn't allow in-place resamples. */
1158 
1159  data.data_in = (float *)inbuf; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */
1160  data.input_frames = inbuflen / framelen;
1161  data.input_frames_used = 0;
1162 
1163  data.data_out = outbuf;
1164  data.output_frames = outbuflen / framelen;
1165 
1166  data.end_of_input = 0;
1167  data.src_ratio = stream->rate_incr;
1168 
1169  result = SRC_src_process(state, &data);
1170  if (result != 0) {
1171  SDL_SetError("src_process() failed: %s", SRC_src_strerror(result));
1172  return 0;
1173  }
1174 
1175  /* If this fails, we need to store them off somewhere */
1176  SDL_assert(data.input_frames_used == data.input_frames);
1177 
1178  return data.output_frames_gen * (sizeof(float) * stream->pre_resample_channels);
1179 }
1180 
1181 static void
1182 SDL_ResetAudioStreamResampler_SRC(SDL_AudioStream *stream)
1183 {
1184  SRC_src_reset((SRC_STATE *)stream->resampler_state);
1185 }
1186 
1187 static void
1188 SDL_CleanupAudioStreamResampler_SRC(SDL_AudioStream *stream)
1189 {
1190  SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
1191  if (state) {
1192  SRC_src_delete(state);
1193  }
1194 
1195  stream->resampler_state = NULL;
1196  stream->resampler_func = NULL;
1197  stream->reset_resampler_func = NULL;
1198  stream->cleanup_resampler_func = NULL;
1199 }
1200 
1201 static SDL_bool
1202 SetupLibSampleRateResampling(SDL_AudioStream *stream)
1203 {
1204  int result = 0;
1205  SRC_STATE *state = NULL;
1206 
1207  if (SRC_available) {
1208  state = SRC_src_new(SRC_converter, stream->pre_resample_channels, &result);
1209  if (!state) {
1210  SDL_SetError("src_new() failed: %s", SRC_src_strerror(result));
1211  }
1212  }
1213 
1214  if (!state) {
1215  SDL_CleanupAudioStreamResampler_SRC(stream);
1216  return SDL_FALSE;
1217  }
1218 
1219  stream->resampler_state = state;
1220  stream->resampler_func = SDL_ResampleAudioStream_SRC;
1221  stream->reset_resampler_func = SDL_ResetAudioStreamResampler_SRC;
1222  stream->cleanup_resampler_func = SDL_CleanupAudioStreamResampler_SRC;
1223 
1224  return SDL_TRUE;
1225 }
1226 #endif /* HAVE_LIBSAMPLERATE_H */
1227 
1228 
1229 static int
1230 SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
1231 {
1232  const Uint8 *inbufend = ((const Uint8 *) _inbuf) + inbuflen;
1233  const float *inbuf = (const float *) _inbuf;
1234  float *outbuf = (float *) _outbuf;
1235  const int chans = (int) stream->pre_resample_channels;
1236  const int inrate = stream->src_rate;
1237  const int outrate = stream->dst_rate;
1238  const int paddingsamples = stream->resampler_padding_samples;
1239  const int paddingbytes = paddingsamples * sizeof (float);
1240  float *lpadding = (float *) stream->resampler_state;
1241  const float *rpadding = (const float *) inbufend; /* we set this up so there are valid padding samples at the end of the input buffer. */
1242  const int cpy = SDL_min(inbuflen, paddingbytes);
1243  int retval;
1244 
1245  SDL_assert(inbuf != ((const float *) outbuf)); /* SDL_AudioStreamPut() shouldn't allow in-place resamples. */
1246 
1247  retval = SDL_ResampleAudio(chans, inrate, outrate, lpadding, rpadding, inbuf, inbuflen, outbuf, outbuflen);
1248 
1249  /* update our left padding with end of current input, for next run. */
1250  SDL_memcpy((lpadding + paddingsamples) - (cpy / sizeof (float)), inbufend - cpy, cpy);
1251  return retval;
1252 }
1253 
1254 static void
1256 {
1257  /* set all the padding to silence. */
1258  const int len = stream->resampler_padding_samples;
1259  SDL_memset(stream->resampler_state, '\0', len * sizeof (float));
1260 }
1261 
1262 static void
1264 {
1265  SDL_free(stream->resampler_state);
1266 }
1267 
1268 SDL_AudioStream *
1270  const Uint8 src_channels,
1271  const int src_rate,
1272  const SDL_AudioFormat dst_format,
1273  const Uint8 dst_channels,
1274  const int dst_rate)
1275 {
1276  const int packetlen = 4096; /* !!! FIXME: good enough for now. */
1277  Uint8 pre_resample_channels;
1278  SDL_AudioStream *retval;
1279 
1280  retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream));
1281  if (!retval) {
1282  return NULL;
1283  }
1284 
1285  /* If increasing channels, do it after resampling, since we'd just
1286  do more work to resample duplicate channels. If we're decreasing, do
1287  it first so we resample the interpolated data instead of interpolating
1288  the resampled data (!!! FIXME: decide if that works in practice, though!). */
1289  pre_resample_channels = SDL_min(src_channels, dst_channels);
1290 
1291  retval->first_run = SDL_TRUE;
1292  retval->src_sample_frame_size = (SDL_AUDIO_BITSIZE(src_format) / 8) * src_channels;
1293  retval->src_format = src_format;
1294  retval->src_channels = src_channels;
1295  retval->src_rate = src_rate;
1296  retval->dst_sample_frame_size = (SDL_AUDIO_BITSIZE(dst_format) / 8) * dst_channels;
1297  retval->dst_format = dst_format;
1298  retval->dst_channels = dst_channels;
1299  retval->dst_rate = dst_rate;
1300  retval->pre_resample_channels = pre_resample_channels;
1301  retval->packetlen = packetlen;
1302  retval->rate_incr = ((double) dst_rate) / ((double) src_rate);
1303  retval->resampler_padding_samples = ResamplerPadding(retval->src_rate, retval->dst_rate) * pre_resample_channels;
1304  retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples ? retval->resampler_padding_samples : 1, sizeof (float));
1305 
1306  if (retval->resampler_padding == NULL) {
1308  SDL_OutOfMemory();
1309  return NULL;
1310  }
1311 
1312  retval->staging_buffer_size = ((retval->resampler_padding_samples / retval->pre_resample_channels) * retval->src_sample_frame_size);
1313  if (retval->staging_buffer_size > 0) {
1314  retval->staging_buffer = (Uint8 *) SDL_malloc(retval->staging_buffer_size);
1315  if (retval->staging_buffer == NULL) {
1317  SDL_OutOfMemory();
1318  return NULL;
1319  }
1320  }
1321 
1322  /* Not resampling? It's an easy conversion (and maybe not even that!) */
1323  if (src_rate == dst_rate) {
1324  retval->cvt_before_resampling.needed = SDL_FALSE;
1325  if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, src_format, src_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) {
1327  return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */
1328  }
1329  } else {
1330  /* Don't resample at first. Just get us to Float32 format. */
1331  /* !!! FIXME: convert to int32 on devices without hardware float. */
1332  if (SDL_BuildAudioCVT(&retval->cvt_before_resampling, src_format, src_channels, src_rate, AUDIO_F32SYS, pre_resample_channels, src_rate) < 0) {
1334  return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */
1335  }
1336 
1337 #ifdef HAVE_LIBSAMPLERATE_H
1338  SetupLibSampleRateResampling(retval);
1339 #endif
1340 
1341  if (!retval->resampler_func) {
1342  retval->resampler_state = SDL_calloc(retval->resampler_padding_samples, sizeof (float));
1343  if (!retval->resampler_state) {
1345  SDL_OutOfMemory();
1346  return NULL;
1347  }
1348 
1349  if (SDL_PrepareResampleFilter() < 0) {
1350  SDL_free(retval->resampler_state);
1351  retval->resampler_state = NULL;
1353  return NULL;
1354  }
1355 
1356  retval->resampler_func = SDL_ResampleAudioStream;
1357  retval->reset_resampler_func = SDL_ResetAudioStreamResampler;
1358  retval->cleanup_resampler_func = SDL_CleanupAudioStreamResampler;
1359  }
1360 
1361  /* Convert us to the final format after resampling. */
1362  if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, AUDIO_F32SYS, pre_resample_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) {
1364  return NULL; /* SDL_BuildAudioCVT should have called SDL_SetError. */
1365  }
1366  }
1367 
1368  retval->queue = SDL_NewDataQueue(packetlen, packetlen * 2);
1369  if (!retval->queue) {
1371  return NULL; /* SDL_NewDataQueue should have called SDL_SetError. */
1372  }
1373 
1374  return retval;
1375 }
1376 
1377 static int
1378 SDL_AudioStreamPutInternal(SDL_AudioStream *stream, const void *buf, int len, int *maxputbytes)
1379 {
1380  int buflen = len;
1381  int workbuflen;
1382  Uint8 *workbuf;
1383  Uint8 *resamplebuf = NULL;
1384  int resamplebuflen = 0;
1385  int neededpaddingbytes;
1386  int paddingbytes;
1387 
1388  /* !!! FIXME: several converters can take advantage of SIMD, but only
1389  !!! FIXME: if the data is aligned to 16 bytes. EnsureStreamBufferSize()
1390  !!! FIXME: guarantees the buffer will align, but the
1391  !!! FIXME: converters will iterate over the data backwards if
1392  !!! FIXME: the output grows, and this means we won't align if buflen
1393  !!! FIXME: isn't a multiple of 16. In these cases, we should chop off
1394  !!! FIXME: a few samples at the end and convert them separately. */
1395 
1396  /* no padding prepended on first run. */
1397  neededpaddingbytes = stream->resampler_padding_samples * sizeof (float);
1398  paddingbytes = stream->first_run ? 0 : neededpaddingbytes;
1399  stream->first_run = SDL_FALSE;
1400 
1401  /* Make sure the work buffer can hold all the data we need at once... */
1402  workbuflen = buflen;
1403  if (stream->cvt_before_resampling.needed) {
1404  workbuflen *= stream->cvt_before_resampling.len_mult;
1405  }
1406 
1407  if (stream->dst_rate != stream->src_rate) {
1408  /* resamples can't happen in place, so make space for second buf. */
1409  const int framesize = stream->pre_resample_channels * sizeof (float);
1410  const int frames = workbuflen / framesize;
1411  resamplebuflen = ((int) SDL_ceil(frames * stream->rate_incr)) * framesize;
1412  #if DEBUG_AUDIOSTREAM
1413  printf("AUDIOSTREAM: will resample %d bytes to %d (ratio=%.6f)\n", workbuflen, resamplebuflen, stream->rate_incr);
1414  #endif
1415  workbuflen += resamplebuflen;
1416  }
1417 
1418  if (stream->cvt_after_resampling.needed) {
1419  /* !!! FIXME: buffer might be big enough already? */
1420  workbuflen *= stream->cvt_after_resampling.len_mult;
1421  }
1422 
1423  workbuflen += neededpaddingbytes;
1424 
1425  #if DEBUG_AUDIOSTREAM
1426  printf("AUDIOSTREAM: Putting %d bytes of preconverted audio, need %d byte work buffer\n", buflen, workbuflen);
1427  #endif
1428 
1429  workbuf = EnsureStreamBufferSize(stream, workbuflen);
1430  if (!workbuf) {
1431  return -1; /* probably out of memory. */
1432  }
1433 
1434  resamplebuf = workbuf; /* default if not resampling. */
1435 
1436  SDL_memcpy(workbuf + paddingbytes, buf, buflen);
1437 
1438  if (stream->cvt_before_resampling.needed) {
1439  stream->cvt_before_resampling.buf = workbuf + paddingbytes;
1440  stream->cvt_before_resampling.len = buflen;
1441  if (SDL_ConvertAudio(&stream->cvt_before_resampling) == -1) {
1442  return -1; /* uhoh! */
1443  }
1444  buflen = stream->cvt_before_resampling.len_cvt;
1445 
1446  #if DEBUG_AUDIOSTREAM
1447  printf("AUDIOSTREAM: After initial conversion we have %d bytes\n", buflen);
1448  #endif
1449  }
1450 
1451  if (stream->dst_rate != stream->src_rate) {
1452  /* save off some samples at the end; they are used for padding now so
1453  the resampler is coherent and then used at the start of the next
1454  put operation. Prepend last put operation's padding, too. */
1455 
1456  /* prepend prior put's padding. :P */
1457  if (paddingbytes) {
1458  SDL_memcpy(workbuf, stream->resampler_padding, paddingbytes);
1459  buflen += paddingbytes;
1460  }
1461 
1462  /* save off the data at the end for the next run. */
1463  SDL_memcpy(stream->resampler_padding, workbuf + (buflen - neededpaddingbytes), neededpaddingbytes);
1464 
1465  resamplebuf = workbuf + buflen; /* skip to second piece of workbuf. */
1466  SDL_assert(buflen >= neededpaddingbytes);
1467  if (buflen > neededpaddingbytes) {
1468  buflen = stream->resampler_func(stream, workbuf, buflen - neededpaddingbytes, resamplebuf, resamplebuflen);
1469  } else {
1470  buflen = 0;
1471  }
1472 
1473  #if DEBUG_AUDIOSTREAM
1474  printf("AUDIOSTREAM: After resampling we have %d bytes\n", buflen);
1475  #endif
1476  }
1477 
1478  if (stream->cvt_after_resampling.needed && (buflen > 0)) {
1479  stream->cvt_after_resampling.buf = resamplebuf;
1480  stream->cvt_after_resampling.len = buflen;
1481  if (SDL_ConvertAudio(&stream->cvt_after_resampling) == -1) {
1482  return -1; /* uhoh! */
1483  }
1484  buflen = stream->cvt_after_resampling.len_cvt;
1485 
1486  #if DEBUG_AUDIOSTREAM
1487  printf("AUDIOSTREAM: After final conversion we have %d bytes\n", buflen);
1488  #endif
1489  }
1490 
1491  #if DEBUG_AUDIOSTREAM
1492  printf("AUDIOSTREAM: Final output is %d bytes\n", buflen);
1493  #endif
1494 
1495  if (maxputbytes) {
1496  const int maxbytes = *maxputbytes;
1497  if (buflen > maxbytes)
1498  buflen = maxbytes;
1499  *maxputbytes -= buflen;
1500  }
1501 
1502  /* resamplebuf holds the final output, even if we didn't resample. */
1503  return buflen ? SDL_WriteToDataQueue(stream->queue, resamplebuf, buflen) : 0;
1504 }
1505 
1506 int
1507 SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len)
1508 {
1509  /* !!! FIXME: several converters can take advantage of SIMD, but only
1510  !!! FIXME: if the data is aligned to 16 bytes. EnsureStreamBufferSize()
1511  !!! FIXME: guarantees the buffer will align, but the
1512  !!! FIXME: converters will iterate over the data backwards if
1513  !!! FIXME: the output grows, and this means we won't align if buflen
1514  !!! FIXME: isn't a multiple of 16. In these cases, we should chop off
1515  !!! FIXME: a few samples at the end and convert them separately. */
1516 
1517  #if DEBUG_AUDIOSTREAM
1518  printf("AUDIOSTREAM: wants to put %d preconverted bytes\n", buflen);
1519  #endif
1520 
1521  if (!stream) {
1522  return SDL_InvalidParamError("stream");
1523  } else if (!buf) {
1524  return SDL_InvalidParamError("buf");
1525  } else if (len == 0) {
1526  return 0; /* nothing to do. */
1527  } else if ((len % stream->src_sample_frame_size) != 0) {
1528  return SDL_SetError("Can't add partial sample frames");
1529  }
1530 
1531  if (!stream->cvt_before_resampling.needed &&
1532  (stream->dst_rate == stream->src_rate) &&
1533  !stream->cvt_after_resampling.needed) {
1534  #if DEBUG_AUDIOSTREAM
1535  printf("AUDIOSTREAM: no conversion needed at all, queueing %d bytes.\n", len);
1536  #endif
1537  return SDL_WriteToDataQueue(stream->queue, buf, len);
1538  }
1539 
1540  while (len > 0) {
1541  int amount;
1542 
1543  /* If we don't have a staging buffer or we're given enough data that
1544  we don't need to store it for later, skip the staging process.
1545  */
1546  if (!stream->staging_buffer_filled && len >= stream->staging_buffer_size) {
1548  }
1549 
1550  /* If there's not enough data to fill the staging buffer, just save it */
1551  if ((stream->staging_buffer_filled + len) < stream->staging_buffer_size) {
1552  SDL_memcpy(stream->staging_buffer + stream->staging_buffer_filled, buf, len);
1553  stream->staging_buffer_filled += len;
1554  return 0;
1555  }
1556 
1557  /* Fill the staging buffer, process it, and continue */
1558  amount = (stream->staging_buffer_size - stream->staging_buffer_filled);
1559  SDL_assert(amount > 0);
1560  SDL_memcpy(stream->staging_buffer + stream->staging_buffer_filled, buf, amount);
1561  stream->staging_buffer_filled = 0;
1562  if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, NULL) < 0) {
1563  return -1;
1564  }
1565  buf = (void *)((Uint8 *)buf + amount);
1566  len -= amount;
1567  }
1568  return 0;
1569 }
1570 
1571 int SDL_AudioStreamFlush(SDL_AudioStream *stream)
1572 {
1573  if (!stream) {
1574  return SDL_InvalidParamError("stream");
1575  }
1576 
1577  #if DEBUG_AUDIOSTREAM
1578  printf("AUDIOSTREAM: flushing! staging_buffer_filled=%d bytes\n", stream->staging_buffer_filled);
1579  #endif
1580 
1581  /* shouldn't use a staging buffer if we're not resampling. */
1582  SDL_assert((stream->dst_rate != stream->src_rate) || (stream->staging_buffer_filled == 0));
1583 
1584  if (stream->staging_buffer_filled > 0) {
1585  /* push the staging buffer + silence. We need to flush out not just
1586  the staging buffer, but the piece that the stream was saving off
1587  for right-side resampler padding. */
1588  const SDL_bool first_run = stream->first_run;
1589  const int filled = stream->staging_buffer_filled;
1590  int actual_input_frames = filled / stream->src_sample_frame_size;
1591  if (!first_run)
1592  actual_input_frames += stream->resampler_padding_samples / stream->pre_resample_channels;
1593 
1594  if (actual_input_frames > 0) { /* don't bother if nothing to flush. */
1595  /* This is how many bytes we're expecting without silence appended. */
1596  int flush_remaining = ((int) SDL_ceil(actual_input_frames * stream->rate_incr)) * stream->dst_sample_frame_size;
1597 
1598  #if DEBUG_AUDIOSTREAM
1599  printf("AUDIOSTREAM: flushing with padding to get max %d bytes!\n", flush_remaining);
1600  #endif
1601 
1602  SDL_memset(stream->staging_buffer + filled, '\0', stream->staging_buffer_size - filled);
1603  if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, &flush_remaining) < 0) {
1604  return -1;
1605  }
1606 
1607  /* we have flushed out (or initially filled) the pending right-side
1608  resampler padding, but we need to push more silence to guarantee
1609  the staging buffer is fully flushed out, too. */
1610  SDL_memset(stream->staging_buffer, '\0', filled);
1611  if (SDL_AudioStreamPutInternal(stream, stream->staging_buffer, stream->staging_buffer_size, &flush_remaining) < 0) {
1612  return -1;
1613  }
1614  }
1615  }
1616 
1617  stream->staging_buffer_filled = 0;
1618  stream->first_run = SDL_TRUE;
1619 
1620  return 0;
1621 }
1622 
1623 /* get converted/resampled data from the stream */
1624 int
1625 SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len)
1626 {
1627  #if DEBUG_AUDIOSTREAM
1628  printf("AUDIOSTREAM: want to get %d converted bytes\n", len);
1629  #endif
1630 
1631  if (!stream) {
1632  return SDL_InvalidParamError("stream");
1633  } else if (!buf) {
1634  return SDL_InvalidParamError("buf");
1635  } else if (len <= 0) {
1636  return 0; /* nothing to do. */
1637  } else if ((len % stream->dst_sample_frame_size) != 0) {
1638  return SDL_SetError("Can't request partial sample frames");
1639  }
1640 
1641  return (int) SDL_ReadFromDataQueue(stream->queue, buf, len);
1642 }
1643 
1644 /* number of converted/resampled bytes available */
1645 int
1647 {
1648  return stream ? (int) SDL_CountDataQueue(stream->queue) : 0;
1649 }
1650 
1651 void
1652 SDL_AudioStreamClear(SDL_AudioStream *stream)
1653 {
1654  if (!stream) {
1655  SDL_InvalidParamError("stream");
1656  } else {
1657  SDL_ClearDataQueue(stream->queue, stream->packetlen * 2);
1658  if (stream->reset_resampler_func) {
1659  stream->reset_resampler_func(stream);
1660  }
1661  stream->first_run = SDL_TRUE;
1662  stream->staging_buffer_filled = 0;
1663  }
1664 }
1665 
1666 /* dispose of a stream */
1667 void
1668 SDL_FreeAudioStream(SDL_AudioStream *stream)
1669 {
1670  if (stream) {
1671  if (stream->cleanup_resampler_func) {
1672  stream->cleanup_resampler_func(stream);
1673  }
1674  SDL_FreeDataQueue(stream->queue);
1675  SDL_free(stream->staging_buffer);
1676  SDL_free(stream->work_buffer_base);
1677  SDL_free(stream->resampler_padding);
1678  SDL_free(stream);
1679  }
1680 }
1681 
1682 /* vi: set ts=4 sw=4 expandtab: */
1683 
SDL.h
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_AUDIOCVT_MAX_FILTERS
#define SDL_AUDIOCVT_MAX_FILTERS
Upper limit of filters in SDL_AudioCVT.
Definition: SDL_audio.h:203
SDL_AudioCVT::rate_incr
double rate_incr
Definition: SDL_audio.h:231
SDL_NewDataQueue
SDL_DataQueue * SDL_NewDataQueue(const size_t _packetlen, const size_t initialslack)
Definition: SDL_dataqueue.c:58
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1571
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:386
SDL_ConvertAudio
int SDL_ConvertAudio(SDL_AudioCVT *cvt)
Definition: SDL_audiocvt.c:540
SDL_AudioCVT::len_ratio
double len_ratio
Definition: SDL_audio.h:236
SDL_ConvertStereoToMono
static void SDL_ConvertStereoToMono(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:81
SDL_sinf
#define SDL_sinf
Definition: SDL_dynapi_overrides.h:436
RESAMPLER_SAMPLES_PER_ZERO_CROSSING
#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING
Definition: SDL_audiocvt.c:382
SDL_audio_c.h
SDL_CountDataQueue
size_t SDL_CountDataQueue(SDL_DataQueue *queue)
Definition: SDL_dataqueue.c:294
_SDL_AudioStream::dst_rate
int dst_rate
Definition: SDL_audiocvt.c:1111
_SDL_AudioStream::dst_channels
Uint8 dst_channels
Definition: SDL_audiocvt.c:1110
offset
GLintptr offset
Definition: SDL_opengl_glext.h:538
SDL_ChooseAudioConverters
void SDL_ChooseAudioConverters(void)
Definition: SDL_audiotypecvt.c:1386
ResamplerFilter
static float * ResamplerFilter
Definition: SDL_audiocvt.c:431
AUDIO_U16LSB
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
SDL_AudioStreamAvailable
int SDL_AudioStreamAvailable(SDL_AudioStream *stream)
Definition: SDL_audiocvt.c:1646
_SDL_AudioStream::cvt_after_resampling
SDL_AudioCVT cvt_after_resampling
Definition: SDL_audiocvt.c:1096
SDL_Convert_F32_to_U16
SDL_AudioFilter SDL_Convert_F32_to_U16
Definition: SDL_audiotypecvt.c:60
SDL_ConvertMonoToStereo
static void SDL_ConvertMonoToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:210
RESAMPLER_FILTER_SIZE
#define RESAMPLER_FILTER_SIZE
Definition: SDL_audiocvt.c:383
SDL_ceil
#define SDL_ceil
Definition: SDL_dynapi_overrides.h:426
NULL
#define NULL
Definition: begin_code.h:167
_SDL_AudioStream::work_buffer_len
int work_buffer_len
Definition: SDL_audiocvt.c:1103
AUDIO_S32MSB
#define AUDIO_S32MSB
Definition: SDL_audio.h:104
SDL_Convert_S16_to_F32
SDL_AudioFilter SDL_Convert_S16_to_F32
Definition: SDL_audiotypecvt.c:54
SDL_ResetAudioStreamResampler
static void SDL_ResetAudioStreamResampler(SDL_AudioStream *stream)
Definition: SDL_audiocvt.c:1255
ResamplerFilterDifference
static float * ResamplerFilterDifference
Definition: SDL_audiocvt.c:432
_SDL_AudioStream::src_sample_frame_size
int src_sample_frame_size
Definition: SDL_audiocvt.c:1104
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
_SDL_AudioStream::src_rate
int src_rate
Definition: SDL_audiocvt.c:1107
SDL_AUDIO_ISBIGENDIAN
#define SDL_AUDIO_ISBIGENDIAN(x)
Definition: SDL_audio.h:77
SDL_FreeDataQueue
void SDL_FreeDataQueue(SDL_DataQueue *queue)
Definition: SDL_dataqueue.c:88
SDL_AudioCVT::buf
Uint8 * buf
Definition: SDL_audio.h:232
SDL_AtomicLock
#define SDL_AtomicLock
Definition: SDL_dynapi_overrides.h:64
SDL_ConvertStereoTo51
static void SDL_ConvertStereoTo51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:234
SDL_ResetAudioStreamResamplerFunc
void(* SDL_ResetAudioStreamResamplerFunc)(SDL_AudioStream *stream)
Definition: SDL_audiocvt.c:1090
SDLCALL
#define SDLCALL
Definition: SDL_internal.h:49
SDL_ResampleCVT
static void SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format)
Definition: SDL_audiocvt.c:707
SDL_AudioCVT::dst_format
SDL_AudioFormat dst_format
Definition: SDL_audio.h:230
stream
GLuint GLuint stream
Definition: SDL_opengl_glext.h:1776
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
SDL_AudioCVT::needed
int needed
Definition: SDL_audio.h:228
SDL_InvalidParamError
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
SDL_ResampleAudioStream
static int SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
Definition: SDL_audiocvt.c:1230
_SDL_AudioStream::pre_resample_channels
Uint8 pre_resample_channels
Definition: SDL_audiocvt.c:1113
RESAMPLER_FUNCS
#define RESAMPLER_FUNCS(chans)
Definition: SDL_audiocvt.c:754
SDL_WriteToDataQueue
int SDL_WriteToDataQueue(SDL_DataQueue *queue, const void *_data, const size_t _len)
Definition: SDL_dataqueue.c:175
SDL_BuildAudioTypeCVTToFloat
static int SDL_BuildAudioTypeCVTToFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat src_fmt)
Definition: SDL_audiocvt.c:615
SDL_ResampleAudio
static int SDL_ResampleAudio(const int chans, const int inrate, const int outrate, const float *lpadding, const float *rpadding, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
Definition: SDL_audiocvt.c:485
bessel
static double bessel(const double x)
Definition: SDL_audiocvt.c:387
SDL_Convert71To51
static void SDL_Convert71To51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:151
SDL_Convert_S8_to_F32
SDL_AudioFilter SDL_Convert_S8_to_F32
Definition: SDL_audiotypecvt.c:52
SDL_Convert_S32_to_F32
SDL_AudioFilter SDL_Convert_S32_to_F32
Definition: SDL_audiotypecvt.c:56
_SDL_AudioStream::cleanup_resampler_func
SDL_CleanupAudioStreamResamplerFunc cleanup_resampler_func
Definition: SDL_audiocvt.c:1120
SDL_AudioFormat
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9432
SDL_HasSSE3
#define SDL_HasSSE3
Definition: SDL_dynapi_overrides.h:109
SDL_AudioCVT::len_mult
int len_mult
Definition: SDL_audio.h:235
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1973
SDL_AUDIO_MASK_ENDIAN
#define SDL_AUDIO_MASK_ENDIAN
Definition: SDL_audio.h:73
SDL_AUDIO_ISFLOAT
#define SDL_AUDIO_ISFLOAT(x)
Definition: SDL_audio.h:76
SDL_FreeAudioStream
void SDL_FreeAudioStream(SDL_AudioStream *stream)
Definition: SDL_audiocvt.c:1668
filter
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: SDL_opengl_glext.h:1184
_SDL_AudioStream::first_run
SDL_bool first_run
Definition: SDL_audiocvt.c:1098
_SDL_AudioStream::src_format
SDL_AudioFormat src_format
Definition: SDL_audiocvt.c:1105
dst
GLenum GLenum dst
Definition: SDL_opengl_glext.h:1737
AUDIO_U8
#define AUDIO_U8
Definition: SDL_audio.h:89
SDL_AudioCVT::filter_index
int filter_index
Definition: SDL_audio.h:238
SDL_SupportedChannelCount
static SDL_bool SDL_SupportedChannelCount(const int channels)
Definition: SDL_audiocvt.c:854
_SDL_AudioStream::resampler_padding
float * resampler_padding
Definition: SDL_audiocvt.c:1116
len
GLenum GLsizei len
Definition: SDL_opengl_glext.h:2926
buf
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: SDL_opengl_glext.h:2480
SDL_LIL_ENDIAN
#define SDL_LIL_ENDIAN
Definition: SDL_endian.h:37
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179
_SDL_AudioStream::queue
SDL_DataQueue * queue
Definition: SDL_audiocvt.c:1097
SDL_AtomicUnlock
#define SDL_AtomicUnlock
Definition: SDL_dynapi_overrides.h:65
LOG_DEBUG_CONVERT
#define LOG_DEBUG_CONVERT(from, to)
Definition: SDL_audio_c.h:34
AUDIO_F32MSB
#define AUDIO_F32MSB
Definition: SDL_audio.h:113
SDL_ResampleAudioStreamFunc
int(* SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen)
Definition: SDL_audiocvt.c:1089
SDL_audio.h
retval
SDL_bool retval
Definition: testgamecontroller.c:65
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1573
SDL_Convert_U8_to_F32
SDL_AudioFilter SDL_Convert_U8_to_F32
Definition: SDL_audiotypecvt.c:53
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
f
GLfloat f
Definition: SDL_opengl_glext.h:1870
AUDIO_S32
#define AUDIO_S32
Definition: SDL_audio.h:105
SDL_FreeResampleFilter
void SDL_FreeResampleFilter(void)
Definition: SDL_audiocvt.c:464
_SDL_AudioStream::cvt_before_resampling
SDL_AudioCVT cvt_before_resampling
Definition: SDL_audiocvt.c:1095
SDL_cpuinfo.h
SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_BuildAudioCVT
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:878
SDL_Convert51ToStereo
static void SDL_Convert51ToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:103
_SDL_AudioStream::resampler_state
void * resampler_state
Definition: SDL_audiocvt.c:1117
AUDIO_F32SYS
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
_SDL_AudioStream::rate_incr
double rate_incr
Definition: SDL_audiocvt.c:1112
SDL_AddAudioCVTFilter
static int SDL_AddAudioCVTFilter(SDL_AudioCVT *cvt, const SDL_AudioFilter filter)
Definition: SDL_audiocvt.c:601
SDL_Convert_F32_to_S8
SDL_AudioFilter SDL_Convert_F32_to_S8
Definition: SDL_audiotypecvt.c:57
SDL_assert.h
kaiser_and_sinc
static void kaiser_and_sinc(float *table, float *diffs, const int tablelen, const double beta)
Definition: SDL_audiocvt.c:409
SDL_min
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
SDL_memmove
#define SDL_memmove
Definition: SDL_dynapi_overrides.h:388
SDL_AUDIO_BITSIZE
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
AUDIO_F32LSB
#define AUDIO_F32LSB
Definition: SDL_audio.h:112
SDL_pow
#define SDL_pow
Definition: SDL_dynapi_overrides.h:433
SDL_Convert51ToQuad
static void SDL_Convert51ToQuad(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:181
_SDL_AudioStream::staging_buffer_size
int staging_buffer_size
Definition: SDL_audiocvt.c:1100
ChooseCVTResampler
static SDL_AudioFilter ChooseCVTResampler(const int dst_channels)
Definition: SDL_audiocvt.c:767
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
AUDIO_S32LSB
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
_SDL_AudioStream::dst_format
SDL_AudioFormat dst_format
Definition: SDL_audiocvt.c:1109
SDL_SpinLock
int SDL_SpinLock
Definition: SDL_atomic.h:89
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
_SDL_AudioStream::reset_resampler_func
SDL_ResetAudioStreamResamplerFunc reset_resampler_func
Definition: SDL_audiocvt.c:1119
SDL_CleanupAudioStreamResamplerFunc
void(* SDL_CleanupAudioStreamResamplerFunc)(SDL_AudioStream *stream)
Definition: SDL_audiocvt.c:1091
SDL_ReadFromDataQueue
size_t SDL_ReadFromDataQueue(SDL_DataQueue *queue, void *_buf, const size_t _len)
Definition: SDL_dataqueue.c:254
SDL_Convert_F32_to_S16
SDL_AudioFilter SDL_Convert_F32_to_S16
Definition: SDL_audiotypecvt.c:59
SDL_BuildAudioTypeCVTFromFloat
static int SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt)
Definition: SDL_audiocvt.c:662
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
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: SDL_audiocvt.c:1269
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
SDL_PrepareResampleFilter
int SDL_PrepareResampleFilter(void)
Definition: SDL_audiocvt.c:435
SDL_AudioFilter
void(* SDL_AudioFilter)(struct SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audio.h:193
src
GLenum src
Definition: SDL_opengl_glext.h:1737
frames
static Uint32 frames
Definition: testsprite2.c:40
SDL_AudioCVT::len
int len
Definition: SDL_audio.h:233
_SDL_AudioStream::src_channels
Uint8 src_channels
Definition: SDL_audiocvt.c:1106
_SDL_AudioStream
Definition: SDL_audiocvt.c:1093
SDL_sqrt
#define SDL_sqrt
Definition: SDL_dynapi_overrides.h:437
AUDIO_S16
#define AUDIO_S16
Definition: SDL_audio.h:96
SDL_Convert_U16_to_F32
SDL_AudioFilter SDL_Convert_U16_to_F32
Definition: SDL_audiotypecvt.c:55
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_ClearDataQueue
void SDL_ClearDataQueue(SDL_DataQueue *queue, const size_t slack)
Definition: SDL_dataqueue.c:98
j
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
SDL_AudioStreamPut
int SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len)
Definition: SDL_audiocvt.c:1507
SDL_AudioStreamGet
int SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len)
Definition: SDL_audiocvt.c:1625
SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_MAX_SINT32
#define SDL_MAX_SINT32
A signed 32-bit integer type.
Definition: SDL_stdinc.h:195
EnsureStreamBufferSize
static Uint8 * EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen)
Definition: SDL_audiocvt.c:1124
e
const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char const char const SDL_SCANF_FORMAT_STRING 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
Definition: SDL_dynapi_procs.h:117
_SDL_AudioStream::resampler_func
SDL_ResampleAudioStreamFunc resampler_func
Definition: SDL_audiocvt.c:1118
_SDL_AudioStream::resampler_padding_samples
int resampler_padding_samples
Definition: SDL_audiocvt.c:1115
SDL_CleanupAudioStreamResampler
static void SDL_CleanupAudioStreamResampler(SDL_AudioStream *stream)
Definition: SDL_audiocvt.c:1263
AUDIO_S16MSB
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
SDL_AudioCVT::filters
SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS+1]
Definition: SDL_audio.h:237
SDL_AudioCVT::src_format
SDL_AudioFormat src_format
Definition: SDL_audio.h:229
AUDIO_S16LSB
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
SDL_AudioStreamClear
void SDL_AudioStreamClear(SDL_AudioStream *stream)
Definition: SDL_audiocvt.c:1652
SDL_SupportedAudioFormat
static SDL_bool SDL_SupportedAudioFormat(const SDL_AudioFormat fmt)
Definition: SDL_audiocvt.c:831
AUDIO_S8
#define AUDIO_S8
Definition: SDL_audio.h:90
SDL_AudioStreamFlush
int SDL_AudioStreamFlush(SDL_AudioStream *stream)
Definition: SDL_audiocvt.c:1571
SDL_ConvertQuadToStereo
static void SDL_ConvertQuadToStereo(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:128
DEBUG_AUDIOSTREAM
#define DEBUG_AUDIOSTREAM
Definition: SDL_audiocvt.c:37
SDL_BuildAudioResampleCVT
static int SDL_BuildAudioResampleCVT(SDL_AudioCVT *cvt, const int dst_channels, const int src_rate, const int dst_rate)
Definition: SDL_audiocvt.c:782
SDL_AudioCVT::len_cvt
int len_cvt
Definition: SDL_audio.h:234
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
_SDL_AudioStream::staging_buffer
Uint8 * staging_buffer
Definition: SDL_audiocvt.c:1099
SDL_ConvertStereoToQuad
static void SDL_ConvertStereoToQuad(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:305
SDL_Convert_F32_to_U8
SDL_AudioFilter SDL_Convert_F32_to_U8
Definition: SDL_audiotypecvt.c:58
SDL_Convert_Byteswap
static void SDL_Convert_Byteswap(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:563
void
const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char int const SDL_PRINTF_FORMAT_STRING char const char const SDL_SCANF_FORMAT_STRING char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
Definition: SDL_dynapi_procs.h:89
SDL_BYTEORDER
#define SDL_BYTEORDER
Definition: SDL_config_pandora.h:37
SDL_DataQueue
Definition: SDL_dataqueue.c:35
_SDL_AudioStream::staging_buffer_filled
int staging_buffer_filled
Definition: SDL_audiocvt.c:1101
SDL_AudioCVT
A structure to hold a set of audio conversion filters and buffers.
Definition: SDL_audio.h:226
ResamplerPadding
static int ResamplerPadding(const int inrate, const int outrate)
Definition: SDL_audiocvt.c:473
CASESWAP
#define CASESWAP(b)
size_t
unsigned int size_t
Definition: SDL_config_windows.h:68
SDL_loadso.h
state
struct xkb_state * state
Definition: SDL_waylandsym.h:113
AUDIO_U16MSB
#define AUDIO_U16MSB
Definition: SDL_audio.h:93
SDL_Convert_F32_to_S32
SDL_AudioFilter SDL_Convert_F32_to_S32
Definition: SDL_audiotypecvt.c:61
i
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_AudioStreamPutInternal
static int SDL_AudioStreamPutInternal(SDL_AudioStream *stream, const void *buf, int len, int *maxputbytes)
Definition: SDL_audiocvt.c:1378
table
GLenum GLsizei GLenum GLenum const void * table
Definition: SDL_opengl_glext.h:3118
AUDIO_U16
#define AUDIO_U16
Definition: SDL_audio.h:95
ResampleFilterSpinlock
static SDL_SpinLock ResampleFilterSpinlock
Definition: SDL_audiocvt.c:430
_SDL_AudioStream::work_buffer_base
Uint8 * work_buffer_base
Definition: SDL_audiocvt.c:1102
SDL_ConvertQuadTo51
static void SDL_ConvertQuadTo51(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:268
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
_SDL_AudioStream::packetlen
int packetlen
Definition: SDL_audiocvt.c:1114
_SDL_AudioStream::dst_sample_frame_size
int dst_sample_frame_size
Definition: SDL_audiocvt.c:1108
SDL_Convert51To71
static void SDL_Convert51To71(SDL_AudioCVT *cvt, SDL_AudioFormat format)
Definition: SDL_audiocvt.c:335