src/audio/SDL_audiocvt.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 11 Oct 2017 11:51:14 -0400
changeset 11595 091789122901
parent 11594 61c151bcd76a
child 11596 9d8ea0382c52
permissions -rw-r--r--
audio: Moved the resampler state up to double precision.

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