src/audio/SDL_audiocvt.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 11 Oct 2017 02:03:05 -0400
changeset 11591 c79a9f64ddb2
parent 11590 ca6aa7f5488d
child 11592 61260a51fc60
permissions -rw-r--r--
audio: Make sure audio stream resampling doesn't overflow buffers.
     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 float outtimeincr = 1.0f / ((float) outrate);
   488     const float ratio = ((float) outrate) / ((float) inrate);
   489     const int paddinglen = ResamplerPadding(inrate, outrate);
   490     const int framelen = chans * (int)sizeof (float);
   491     const int inframes = inbuflen / framelen;
   492     const int wantedoutframes = (int) ((inbuflen / framelen) * ratio);  /* outbuflen isn't total to write, it's total available. */
   493     const int maxoutframes = outbuflen / framelen;
   494     const int outframes = SDL_min(wantedoutframes, maxoutframes);
   495     float *dst = outbuf;
   496     float outtime = 0.0f;
   497     int i, j, chan;
   498 
   499     for (i = 0; i < outframes; i++) {
   500         const int srcindex = (int) (outtime * inrate);
   501         const float finrate = (float) inrate;
   502         const float intime = ((float) srcindex) / finrate;
   503         const float innexttime = ((float) (srcindex + 1)) / finrate;
   504 
   505         const float interpolation1 = 1.0f - (innexttime - outtime) / (innexttime - intime);
   506         const int filterindex1 = (int) (interpolation1 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
   507         const float interpolation2 = 1.0f - interpolation1;
   508         const int filterindex2 = (int) (interpolation2 * RESAMPLER_SAMPLES_PER_ZERO_CROSSING);
   509 
   510         for (chan = 0; chan < chans; chan++) {
   511             float outsample = 0.0f;
   512 
   513             /* do this twice to calculate the sample, once for the "left wing" and then same for the right. */
   514             /* !!! FIXME: do both wings in one loop */
   515             for (j = 0; (filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) {
   516                 const int srcframe = srcindex - j;
   517                 /* !!! FIXME: we can bubble this conditional out of here by doing a pre loop. */
   518                 const float insample = (srcframe < 0) ? lpadding[((paddinglen + srcframe) * chans) + chan] : inbuf[(srcframe * chans) + chan];
   519                 outsample += (insample * (ResamplerFilter[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation1 * ResamplerFilterDifference[filterindex1 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
   520             }
   521 
   522             for (j = 0; (filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) < RESAMPLER_FILTER_SIZE; j++) {
   523                 const int srcframe = srcindex + 1 + j;
   524                 /* !!! FIXME: we can bubble this conditional out of here by doing a post loop. */
   525                 const float insample = (srcframe >= inframes) ? rpadding[((srcframe - inframes) * chans) + chan] : inbuf[(srcframe * chans) + chan];
   526                 outsample += (insample * (ResamplerFilter[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)] + (interpolation2 * ResamplerFilterDifference[filterindex2 + (j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING)])));
   527             }
   528             *(dst++) = outsample;
   529         }
   530 
   531         outtime += outtimeincr;
   532     }
   533 
   534     return outframes * chans * sizeof (float);
   535 }
   536 
   537 int
   538 SDL_ConvertAudio(SDL_AudioCVT * cvt)
   539 {
   540     /* !!! FIXME: (cvt) should be const; stack-copy it here. */
   541     /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
   542 
   543     /* Make sure there's data to convert */
   544     if (cvt->buf == NULL) {
   545         return SDL_SetError("No buffer allocated for conversion");
   546     }
   547 
   548     /* Return okay if no conversion is necessary */
   549     cvt->len_cvt = cvt->len;
   550     if (cvt->filters[0] == NULL) {
   551         return 0;
   552     }
   553 
   554     /* Set up the conversion and go! */
   555     cvt->filter_index = 0;
   556     cvt->filters[0] (cvt, cvt->src_format);
   557     return 0;
   558 }
   559 
   560 static void SDLCALL
   561 SDL_Convert_Byteswap(SDL_AudioCVT *cvt, SDL_AudioFormat format)
   562 {
   563 #if DEBUG_CONVERT
   564     printf("Converting byte order\n");
   565 #endif
   566 
   567     switch (SDL_AUDIO_BITSIZE(format)) {
   568         #define CASESWAP(b) \
   569             case b: { \
   570                 Uint##b *ptr = (Uint##b *) cvt->buf; \
   571                 int i; \
   572                 for (i = cvt->len_cvt / sizeof (*ptr); i; --i, ++ptr) { \
   573                     *ptr = SDL_Swap##b(*ptr); \
   574                 } \
   575                 break; \
   576             }
   577 
   578         CASESWAP(16);
   579         CASESWAP(32);
   580         CASESWAP(64);
   581 
   582         #undef CASESWAP
   583 
   584         default: SDL_assert(!"unhandled byteswap datatype!"); break;
   585     }
   586 
   587     if (cvt->filters[++cvt->filter_index]) {
   588         /* flip endian flag for data. */
   589         if (format & SDL_AUDIO_MASK_ENDIAN) {
   590             format &= ~SDL_AUDIO_MASK_ENDIAN;
   591         } else {
   592             format |= SDL_AUDIO_MASK_ENDIAN;
   593         }
   594         cvt->filters[cvt->filter_index](cvt, format);
   595     }
   596 }
   597 
   598 static int
   599 SDL_AddAudioCVTFilter(SDL_AudioCVT *cvt, const SDL_AudioFilter filter)
   600 {
   601     if (cvt->filter_index >= SDL_AUDIOCVT_MAX_FILTERS) {
   602         return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS);
   603     }
   604     if (filter == NULL) {
   605         return SDL_SetError("Audio filter pointer is NULL");
   606     }
   607     cvt->filters[cvt->filter_index++] = filter;
   608     cvt->filters[cvt->filter_index] = NULL; /* Moving terminator */
   609     return 0;
   610 }
   611 
   612 static int
   613 SDL_BuildAudioTypeCVTToFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat src_fmt)
   614 {
   615     int retval = 0;  /* 0 == no conversion necessary. */
   616 
   617     if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
   618         if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) {
   619             return -1;
   620         }
   621         retval = 1;  /* added a converter. */
   622     }
   623 
   624     if (!SDL_AUDIO_ISFLOAT(src_fmt)) {
   625         const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
   626         const Uint16 dst_bitsize = 32;
   627         SDL_AudioFilter filter = NULL;
   628 
   629         switch (src_fmt & ~SDL_AUDIO_MASK_ENDIAN) {
   630             case AUDIO_S8: filter = SDL_Convert_S8_to_F32; break;
   631             case AUDIO_U8: filter = SDL_Convert_U8_to_F32; break;
   632             case AUDIO_S16: filter = SDL_Convert_S16_to_F32; break;
   633             case AUDIO_U16: filter = SDL_Convert_U16_to_F32; break;
   634             case AUDIO_S32: filter = SDL_Convert_S32_to_F32; break;
   635             default: SDL_assert(!"Unexpected audio format!"); break;
   636         }
   637 
   638         if (!filter) {
   639             return SDL_SetError("No conversion from source format to float available");
   640         }
   641 
   642         if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
   643             return -1;
   644         }
   645         if (src_bitsize < dst_bitsize) {
   646             const int mult = (dst_bitsize / src_bitsize);
   647             cvt->len_mult *= mult;
   648             cvt->len_ratio *= mult;
   649         } else if (src_bitsize > dst_bitsize) {
   650             cvt->len_ratio /= (src_bitsize / dst_bitsize);
   651         }
   652 
   653         retval = 1;  /* added a converter. */
   654     }
   655 
   656     return retval;
   657 }
   658 
   659 static int
   660 SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt)
   661 {
   662     int retval = 0;  /* 0 == no conversion necessary. */
   663 
   664     if (!SDL_AUDIO_ISFLOAT(dst_fmt)) {
   665         const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
   666         const Uint16 src_bitsize = 32;
   667         SDL_AudioFilter filter = NULL;
   668         switch (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN) {
   669             case AUDIO_S8: filter = SDL_Convert_F32_to_S8; break;
   670             case AUDIO_U8: filter = SDL_Convert_F32_to_U8; break;
   671             case AUDIO_S16: filter = SDL_Convert_F32_to_S16; break;
   672             case AUDIO_U16: filter = SDL_Convert_F32_to_U16; break;
   673             case AUDIO_S32: filter = SDL_Convert_F32_to_S32; break;
   674             default: SDL_assert(!"Unexpected audio format!"); break;
   675         }
   676 
   677         if (!filter) {
   678             return SDL_SetError("No conversion from float to destination format available");
   679         }
   680 
   681         if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
   682             return -1;
   683         }
   684         if (src_bitsize < dst_bitsize) {
   685             const int mult = (dst_bitsize / src_bitsize);
   686             cvt->len_mult *= mult;
   687             cvt->len_ratio *= mult;
   688         } else if (src_bitsize > dst_bitsize) {
   689             cvt->len_ratio /= (src_bitsize / dst_bitsize);
   690         }
   691         retval = 1;  /* added a converter. */
   692     }
   693 
   694     if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
   695         if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) {
   696             return -1;
   697         }
   698         retval = 1;  /* added a converter. */
   699     }
   700 
   701     return retval;
   702 }
   703 
   704 static void
   705 SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format)
   706 {
   707     /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator).
   708        !!! FIXME in 2.1:   We need to store data for this resampler, because the cvt structure doesn't store the original sample rates,
   709        !!! FIXME in 2.1:   so we steal the ninth and tenth slot.  :( */
   710     const int inrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1];
   711     const int outrate = (int) (size_t) cvt->filters[SDL_AUDIOCVT_MAX_FILTERS];
   712     const float *src = (const float *) cvt->buf;
   713     const int srclen = cvt->len_cvt;
   714     /*float *dst = (float *) cvt->buf;
   715     const int dstlen = (cvt->len * cvt->len_mult);*/
   716     /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
   717     float *dst = (float *) (cvt->buf + srclen);
   718     const int dstlen = (cvt->len * cvt->len_mult) - srclen;
   719     const int paddingsamples = (ResamplerPadding(inrate, outrate) * chans);
   720     float *padding;
   721 
   722     SDL_assert(format == AUDIO_F32SYS);
   723 
   724     /* we keep no streaming state here, so pad with silence on both ends. */
   725     padding = (float *) SDL_calloc(paddingsamples, sizeof (float));
   726     if (!padding) {
   727         SDL_OutOfMemory();
   728         return;
   729     }
   730 
   731     cvt->len_cvt = SDL_ResampleAudio(chans, inrate, outrate, padding, padding, src, srclen, dst, dstlen);
   732 
   733     SDL_free(padding);
   734 
   735     SDL_memmove(cvt->buf, dst, cvt->len_cvt);  /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
   736 
   737     if (cvt->filters[++cvt->filter_index]) {
   738         cvt->filters[cvt->filter_index](cvt, format);
   739     }
   740 }
   741 
   742 /* !!! FIXME: We only have this macro salsa because SDL_AudioCVT doesn't
   743    !!! FIXME:  store channel info, so we have to have function entry
   744    !!! FIXME:  points for each supported channel count and multiple
   745    !!! FIXME:  vs arbitrary. When we rev the ABI, clean this up. */
   746 #define RESAMPLER_FUNCS(chans) \
   747     static void SDLCALL \
   748     SDL_ResampleCVT_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
   749         SDL_ResampleCVT(cvt, chans, format); \
   750     }
   751 RESAMPLER_FUNCS(1)
   752 RESAMPLER_FUNCS(2)
   753 RESAMPLER_FUNCS(4)
   754 RESAMPLER_FUNCS(6)
   755 RESAMPLER_FUNCS(8)
   756 #undef RESAMPLER_FUNCS
   757 
   758 static SDL_AudioFilter
   759 ChooseCVTResampler(const int dst_channels)
   760 {
   761     switch (dst_channels) {
   762         case 1: return SDL_ResampleCVT_c1;
   763         case 2: return SDL_ResampleCVT_c2;
   764         case 4: return SDL_ResampleCVT_c4;
   765         case 6: return SDL_ResampleCVT_c6;
   766         case 8: return SDL_ResampleCVT_c8;
   767         default: break;
   768     }
   769 
   770     return NULL;
   771 }
   772 
   773 static int
   774 SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, const int dst_channels,
   775                           const int src_rate, const int dst_rate)
   776 {
   777     SDL_AudioFilter filter;
   778 
   779     if (src_rate == dst_rate) {
   780         return 0;  /* no conversion necessary. */
   781     }
   782 
   783     filter = ChooseCVTResampler(dst_channels);
   784     if (filter == NULL) {
   785         return SDL_SetError("No conversion available for these rates");
   786     }
   787 
   788     if (SDL_PrepareResampleFilter() < 0) {
   789         return -1;
   790     }
   791 
   792     /* Update (cvt) with filter details... */
   793     if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
   794         return -1;
   795     }
   796 
   797     /* !!! FIXME in 2.1: there are ten slots in the filter list, and the theoretical maximum we use is six (seven with NULL terminator).
   798        !!! FIXME in 2.1:   We need to store data for this resampler, because the cvt structure doesn't store the original sample rates,
   799        !!! FIXME in 2.1:   so we steal the ninth and tenth slot.  :( */
   800     if (cvt->filter_index >= (SDL_AUDIOCVT_MAX_FILTERS-2)) {
   801         return SDL_SetError("Too many filters needed for conversion, exceeded maximum of %d", SDL_AUDIOCVT_MAX_FILTERS-2);
   802     }
   803     cvt->filters[SDL_AUDIOCVT_MAX_FILTERS-1] = (SDL_AudioFilter) (size_t) src_rate;
   804     cvt->filters[SDL_AUDIOCVT_MAX_FILTERS] = (SDL_AudioFilter) (size_t) dst_rate;
   805 
   806     if (src_rate < dst_rate) {
   807         const double mult = ((double) dst_rate) / ((double) src_rate);
   808         cvt->len_mult *= (int) SDL_ceil(mult);
   809         cvt->len_ratio *= mult;
   810     } else {
   811         cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
   812     }
   813 
   814     /* !!! FIXME: remove this if we can get the resampler to work in-place again. */
   815     /* the buffer is big enough to hold the destination now, but
   816        we need it large enough to hold a separate scratch buffer. */
   817     cvt->len_mult *= 2;
   818 
   819     return 1;               /* added a converter. */
   820 }
   821 
   822 static SDL_bool
   823 SDL_SupportedAudioFormat(const SDL_AudioFormat fmt)
   824 {
   825     switch (fmt) {
   826         case AUDIO_U8:
   827         case AUDIO_S8:
   828         case AUDIO_U16LSB:
   829         case AUDIO_S16LSB:
   830         case AUDIO_U16MSB:
   831         case AUDIO_S16MSB:
   832         case AUDIO_S32LSB:
   833         case AUDIO_S32MSB:
   834         case AUDIO_F32LSB:
   835         case AUDIO_F32MSB:
   836             return SDL_TRUE;  /* supported. */
   837 
   838         default:
   839             break;
   840     }
   841 
   842     return SDL_FALSE;  /* unsupported. */
   843 }
   844 
   845 static SDL_bool
   846 SDL_SupportedChannelCount(const int channels)
   847 {
   848     switch (channels) {
   849         case 1:  /* mono */
   850         case 2:  /* stereo */
   851         case 4:  /* quad */
   852         case 6:  /* 5.1 */
   853         case 8:  /* 7.1 */
   854           return SDL_TRUE;  /* supported. */
   855 
   856         default:
   857             break;
   858     }
   859 
   860     return SDL_FALSE;  /* unsupported. */
   861 }
   862 
   863 
   864 /* Creates a set of audio filters to convert from one format to another.
   865    Returns 0 if no conversion is needed, 1 if the audio filter is set up,
   866    or -1 if an error like invalid parameter, unsupported format, etc. occurred.
   867 */
   868 
   869 int
   870 SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
   871                   SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
   872                   SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
   873 {
   874     /* Sanity check target pointer */
   875     if (cvt == NULL) {
   876         return SDL_InvalidParamError("cvt");
   877     }
   878 
   879     /* Make sure we zero out the audio conversion before error checking */
   880     SDL_zerop(cvt);
   881 
   882     if (!SDL_SupportedAudioFormat(src_fmt)) {
   883         return SDL_SetError("Invalid source format");
   884     } else if (!SDL_SupportedAudioFormat(dst_fmt)) {
   885         return SDL_SetError("Invalid destination format");
   886     } else if (!SDL_SupportedChannelCount(src_channels)) {
   887         return SDL_SetError("Invalid source channels");
   888     } else if (!SDL_SupportedChannelCount(dst_channels)) {
   889         return SDL_SetError("Invalid destination channels");
   890     } else if (src_rate == 0) {
   891         return SDL_SetError("Source rate is zero");
   892     } else if (dst_rate == 0) {
   893         return SDL_SetError("Destination rate is zero");
   894     }
   895 
   896 #if DEBUG_CONVERT
   897     printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
   898            src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
   899 #endif
   900 
   901     /* Start off with no conversion necessary */
   902     cvt->src_format = src_fmt;
   903     cvt->dst_format = dst_fmt;
   904     cvt->needed = 0;
   905     cvt->filter_index = 0;
   906     SDL_zero(cvt->filters);
   907     cvt->len_mult = 1;
   908     cvt->len_ratio = 1.0;
   909     cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
   910 
   911     /* Make sure we've chosen audio conversion functions (MMX, scalar, etc.) */
   912     SDL_ChooseAudioConverters();
   913 
   914     /* Type conversion goes like this now:
   915         - byteswap to CPU native format first if necessary.
   916         - convert to native Float32 if necessary.
   917         - resample and change channel count if necessary.
   918         - convert back to native format.
   919         - byteswap back to foreign format if necessary.
   920 
   921        The expectation is we can process data faster in float32
   922        (possibly with SIMD), and making several passes over the same
   923        buffer is likely to be CPU cache-friendly, avoiding the
   924        biggest performance hit in modern times. Previously we had
   925        (script-generated) custom converters for every data type and
   926        it was a bloat on SDL compile times and final library size. */
   927 
   928     /* see if we can skip float conversion entirely. */
   929     if (src_rate == dst_rate && src_channels == dst_channels) {
   930         if (src_fmt == dst_fmt) {
   931             return 0;
   932         }
   933 
   934         /* just a byteswap needed? */
   935         if ((src_fmt & ~SDL_AUDIO_MASK_ENDIAN) == (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN)) {
   936             if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) {
   937                 return -1;
   938             }
   939             cvt->needed = 1;
   940             return 1;
   941         }
   942     }
   943 
   944     /* Convert data types, if necessary. Updates (cvt). */
   945     if (SDL_BuildAudioTypeCVTToFloat(cvt, src_fmt) < 0) {
   946         return -1;              /* shouldn't happen, but just in case... */
   947     }
   948 
   949     /* Channel conversion */
   950     if (src_channels < dst_channels) {
   951         /* Upmixing */
   952         /* Mono -> Stereo [-> ...] */
   953         if ((src_channels == 1) && (dst_channels > 1)) {
   954             if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertMonoToStereo) < 0) {
   955                 return -1;
   956             }
   957             cvt->len_mult *= 2;
   958             src_channels = 2;
   959             cvt->len_ratio *= 2;
   960         }
   961         /* [Mono ->] Stereo -> 5.1 [-> 7.1] */
   962         if ((src_channels == 2) && (dst_channels >= 6)) {
   963             if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertStereoTo51) < 0) {
   964                 return -1;
   965             }
   966             src_channels = 6;
   967             cvt->len_mult *= 3;
   968             cvt->len_ratio *= 3;
   969         }
   970         /* Quad -> 5.1 [-> 7.1] */
   971         if ((src_channels == 4) && (dst_channels >= 6)) {
   972             if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertQuadTo51) < 0) {
   973                 return -1;
   974             }
   975             src_channels = 6;
   976             cvt->len_mult = (cvt->len_mult * 3 + 1) / 2;
   977             cvt->len_ratio *= 1.5;
   978         }
   979         /* [[Mono ->] Stereo ->] 5.1 -> 7.1 */
   980         if ((src_channels == 6) && (dst_channels == 8)) {
   981             if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51To71) < 0) {
   982                 return -1;
   983             }
   984             src_channels = 8;
   985             cvt->len_mult = (cvt->len_mult * 4 + 2) / 3;
   986             /* Should be numerically exact with every valid input to this
   987                function */
   988             cvt->len_ratio = cvt->len_ratio * 4 / 3;
   989         }
   990         /* [Mono ->] Stereo -> Quad */
   991         if ((src_channels == 2) && (dst_channels == 4)) {
   992             if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertStereoToQuad) < 0) {
   993                 return -1;
   994             }
   995             src_channels = 4;
   996             cvt->len_mult *= 2;
   997             cvt->len_ratio *= 2;
   998         }
   999     } else if (src_channels > dst_channels) {
  1000         /* Downmixing */
  1001         /* 7.1 -> 5.1 [-> Stereo [-> Mono]] */
  1002         /* 7.1 -> 5.1 [-> Quad] */
  1003         if ((src_channels == 8) && (dst_channels <= 6)) {
  1004             if (SDL_AddAudioCVTFilter(cvt, SDL_Convert71To51) < 0) {
  1005                 return -1;
  1006             }
  1007             src_channels = 6;
  1008             cvt->len_ratio *= 0.75;
  1009         }
  1010         /* [7.1 ->] 5.1 -> Stereo [-> Mono] */
  1011         if ((src_channels == 6) && (dst_channels <= 2)) {
  1012             if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51ToStereo) < 0) {
  1013                 return -1;
  1014             }
  1015             src_channels = 2;
  1016             cvt->len_ratio /= 3;
  1017         }
  1018         /* 5.1 -> Quad */
  1019         if ((src_channels == 6) && (dst_channels == 4)) {
  1020             if (SDL_AddAudioCVTFilter(cvt, SDL_Convert51ToQuad) < 0) {
  1021                 return -1;
  1022             }
  1023             src_channels = 4;
  1024             cvt->len_ratio = cvt->len_ratio * 2 / 3;
  1025         }
  1026         /* Quad -> Stereo [-> Mono] */
  1027         if ((src_channels == 4) && (dst_channels <= 2)) {
  1028             if (SDL_AddAudioCVTFilter(cvt, SDL_ConvertQuadToStereo) < 0) {
  1029                 return -1;
  1030             }
  1031             src_channels = 2;
  1032             cvt->len_ratio /= 2;
  1033         }
  1034         /* [... ->] Stereo -> Mono */
  1035         if ((src_channels == 2) && (dst_channels == 1)) {
  1036             SDL_AudioFilter filter = NULL;
  1037 
  1038             #if HAVE_SSE3_INTRINSICS
  1039             if (SDL_HasSSE3()) {
  1040                 filter = SDL_ConvertStereoToMono_SSE3;
  1041             }
  1042             #endif
  1043 
  1044             if (!filter) {
  1045                 filter = SDL_ConvertStereoToMono;
  1046             }
  1047 
  1048             if (SDL_AddAudioCVTFilter(cvt, filter) < 0) {
  1049                 return -1;
  1050             }
  1051 
  1052             src_channels = 1;
  1053             cvt->len_ratio /= 2;
  1054         }
  1055     }
  1056 
  1057     if (src_channels != dst_channels) {
  1058         /* All combinations of supported channel counts should have been
  1059            handled by now, but let's be defensive */
  1060       return SDL_SetError("Invalid channel combination");
  1061     }
  1062     
  1063     /* Do rate conversion, if necessary. Updates (cvt). */
  1064     if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) < 0) {
  1065         return -1;              /* shouldn't happen, but just in case... */
  1066     }
  1067 
  1068     /* Move to final data type. */
  1069     if (SDL_BuildAudioTypeCVTFromFloat(cvt, dst_fmt) < 0) {
  1070         return -1;              /* shouldn't happen, but just in case... */
  1071     }
  1072 
  1073     cvt->needed = (cvt->filter_index != 0);
  1074     return (cvt->needed);
  1075 }
  1076 
  1077 typedef int (*SDL_ResampleAudioStreamFunc)(SDL_AudioStream *stream, const void *inbuf, const int inbuflen, void *outbuf, const int outbuflen);
  1078 typedef void (*SDL_ResetAudioStreamResamplerFunc)(SDL_AudioStream *stream);
  1079 typedef void (*SDL_CleanupAudioStreamResamplerFunc)(SDL_AudioStream *stream);
  1080 
  1081 struct SDL_AudioStream
  1082 {
  1083     SDL_AudioCVT cvt_before_resampling;
  1084     SDL_AudioCVT cvt_after_resampling;
  1085     SDL_DataQueue *queue;
  1086     SDL_bool first_run;
  1087     Uint8 *work_buffer_base;  /* maybe unaligned pointer from SDL_realloc(). */
  1088     int work_buffer_len;
  1089     int src_sample_frame_size;
  1090     SDL_AudioFormat src_format;
  1091     Uint8 src_channels;
  1092     int src_rate;
  1093     int dst_sample_frame_size;
  1094     SDL_AudioFormat dst_format;
  1095     Uint8 dst_channels;
  1096     int dst_rate;
  1097     double rate_incr;
  1098     Uint8 pre_resample_channels;
  1099     int packetlen;
  1100     int resampler_padding_samples;
  1101     float *resampler_padding;
  1102     void *resampler_state;
  1103     SDL_ResampleAudioStreamFunc resampler_func;
  1104     SDL_ResetAudioStreamResamplerFunc reset_resampler_func;
  1105     SDL_CleanupAudioStreamResamplerFunc cleanup_resampler_func;
  1106 };
  1107 
  1108 static Uint8 *
  1109 EnsureStreamBufferSize(SDL_AudioStream *stream, const int newlen)
  1110 {
  1111     Uint8 *ptr;
  1112     size_t offset;
  1113 
  1114     if (stream->work_buffer_len >= newlen) {
  1115         ptr = stream->work_buffer_base;
  1116     } else {
  1117         ptr = (Uint8 *) SDL_realloc(stream->work_buffer_base, newlen + 32);
  1118         if (!ptr) {
  1119             SDL_OutOfMemory();
  1120             return NULL;
  1121         }
  1122         /* Make sure we're aligned to 16 bytes for SIMD code. */
  1123         stream->work_buffer_base = ptr;
  1124         stream->work_buffer_len = newlen;
  1125     }
  1126 
  1127     offset = ((size_t) ptr) & 15;
  1128     return offset ? ptr + (16 - offset) : ptr;
  1129 }
  1130 
  1131 #ifdef HAVE_LIBSAMPLERATE_H
  1132 static int
  1133 SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
  1134 {
  1135     const float *inbuf = (const float *) _inbuf;
  1136     float *outbuf = (float *) _outbuf;
  1137     const int framelen = sizeof(float) * stream->pre_resample_channels;
  1138     SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
  1139     SRC_DATA data;
  1140     int result;
  1141 
  1142     SDL_assert(inbuf != ((const float *) outbuf));  /* SDL_AudioStreamPut() shouldn't allow in-place resamples. */
  1143 
  1144     data.data_in = (float *)inbuf; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */
  1145     data.input_frames = inbuflen / framelen;
  1146     data.input_frames_used = 0;
  1147 
  1148     data.data_out = outbuf;
  1149     data.output_frames = outbuflen / framelen;
  1150 
  1151     data.end_of_input = 0;
  1152     data.src_ratio = stream->rate_incr;
  1153 
  1154     result = SRC_src_process(state, &data);
  1155     if (result != 0) {
  1156         SDL_SetError("src_process() failed: %s", SRC_src_strerror(result));
  1157         return 0;
  1158     }
  1159 
  1160     /* If this fails, we need to store them off somewhere */
  1161     SDL_assert(data.input_frames_used == data.input_frames);
  1162 
  1163     return data.output_frames_gen * (sizeof(float) * stream->pre_resample_channels);
  1164 }
  1165 
  1166 static void
  1167 SDL_ResetAudioStreamResampler_SRC(SDL_AudioStream *stream)
  1168 {
  1169     SRC_src_reset((SRC_STATE *)stream->resampler_state);
  1170 }
  1171 
  1172 static void
  1173 SDL_CleanupAudioStreamResampler_SRC(SDL_AudioStream *stream)
  1174 {
  1175     SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
  1176     if (state) {
  1177         SRC_src_delete(state);
  1178     }
  1179 
  1180     stream->resampler_state = NULL;
  1181     stream->resampler_func = NULL;
  1182     stream->reset_resampler_func = NULL;
  1183     stream->cleanup_resampler_func = NULL;
  1184 }
  1185 
  1186 static SDL_bool
  1187 SetupLibSampleRateResampling(SDL_AudioStream *stream)
  1188 {
  1189     int result = 0;
  1190     SRC_STATE *state = NULL;
  1191 
  1192     if (SRC_available) {
  1193         state = SRC_src_new(SRC_converter, stream->pre_resample_channels, &result);
  1194         if (!state) {
  1195             SDL_SetError("src_new() failed: %s", SRC_src_strerror(result));
  1196         }
  1197     }
  1198 
  1199     if (!state) {
  1200         SDL_CleanupAudioStreamResampler_SRC(stream);
  1201         return SDL_FALSE;
  1202     }
  1203 
  1204     stream->resampler_state = state;
  1205     stream->resampler_func = SDL_ResampleAudioStream_SRC;
  1206     stream->reset_resampler_func = SDL_ResetAudioStreamResampler_SRC;
  1207     stream->cleanup_resampler_func = SDL_CleanupAudioStreamResampler_SRC;
  1208 
  1209     return SDL_TRUE;
  1210 }
  1211 #endif /* HAVE_LIBSAMPLERATE_H */
  1212 
  1213 
  1214 static int
  1215 SDL_ResampleAudioStream(SDL_AudioStream *stream, const void *_inbuf, const int inbuflen, void *_outbuf, const int outbuflen)
  1216 {
  1217     const Uint8 *inbufend = ((const Uint8 *) _inbuf) + inbuflen;
  1218     const float *inbuf = (const float *) _inbuf;
  1219     float *outbuf = (float *) _outbuf;
  1220     const int chans = (int) stream->pre_resample_channels;
  1221     const int inrate = stream->src_rate;
  1222     const int outrate = stream->dst_rate;
  1223     const int paddingsamples = stream->resampler_padding_samples;
  1224     const int paddingbytes = paddingsamples * sizeof (float);
  1225     float *lpadding = (float *) stream->resampler_state;
  1226     const float *rpadding = (const float *) inbufend; /* we set this up so there are valid padding samples at the end of the input buffer. */
  1227     const int cpy = SDL_min(inbuflen, paddingbytes);
  1228     int retval;
  1229 
  1230     SDL_assert(inbuf != ((const float *) outbuf));  /* SDL_AudioStreamPut() shouldn't allow in-place resamples. */
  1231 
  1232     retval = SDL_ResampleAudio(chans, inrate, outrate, lpadding, rpadding, inbuf, inbuflen, outbuf, outbuflen);
  1233 
  1234     /* update our left padding with end of current input, for next run. */
  1235     SDL_memcpy((lpadding + paddingsamples) - (cpy / sizeof (float)), inbufend - cpy, cpy);
  1236     return retval;
  1237 }
  1238 
  1239 static void
  1240 SDL_ResetAudioStreamResampler(SDL_AudioStream *stream)
  1241 {
  1242     /* set all the padding to silence. */
  1243     const int len = stream->resampler_padding_samples;
  1244     SDL_memset(stream->resampler_state, '\0', len * sizeof (float));
  1245 }
  1246 
  1247 static void
  1248 SDL_CleanupAudioStreamResampler(SDL_AudioStream *stream)
  1249 {
  1250     SDL_free(stream->resampler_state);
  1251 }
  1252 
  1253 SDL_AudioStream *
  1254 SDL_NewAudioStream(const SDL_AudioFormat src_format,
  1255                    const Uint8 src_channels,
  1256                    const int src_rate,
  1257                    const SDL_AudioFormat dst_format,
  1258                    const Uint8 dst_channels,
  1259                    const int dst_rate)
  1260 {
  1261     const int packetlen = 4096;  /* !!! FIXME: good enough for now. */
  1262     Uint8 pre_resample_channels;
  1263     SDL_AudioStream *retval;
  1264 
  1265     retval = (SDL_AudioStream *) SDL_calloc(1, sizeof (SDL_AudioStream));
  1266     if (!retval) {
  1267         return NULL;
  1268     }
  1269 
  1270     /* If increasing channels, do it after resampling, since we'd just
  1271        do more work to resample duplicate channels. If we're decreasing, do
  1272        it first so we resample the interpolated data instead of interpolating
  1273        the resampled data (!!! FIXME: decide if that works in practice, though!). */
  1274     pre_resample_channels = SDL_min(src_channels, dst_channels);
  1275 
  1276     retval->first_run = SDL_TRUE;
  1277     retval->src_sample_frame_size = (SDL_AUDIO_BITSIZE(src_format) / 8) * src_channels;
  1278     retval->src_format = src_format;
  1279     retval->src_channels = src_channels;
  1280     retval->src_rate = src_rate;
  1281     retval->dst_sample_frame_size = (SDL_AUDIO_BITSIZE(dst_format) / 8) * dst_channels;
  1282     retval->dst_format = dst_format;
  1283     retval->dst_channels = dst_channels;
  1284     retval->dst_rate = dst_rate;
  1285     retval->pre_resample_channels = pre_resample_channels;
  1286     retval->packetlen = packetlen;
  1287     retval->rate_incr = ((double) dst_rate) / ((double) src_rate);
  1288     retval->resampler_padding_samples = ResamplerPadding(retval->src_rate, retval->dst_rate) * pre_resample_channels;
  1289     retval->resampler_padding = (float *) SDL_calloc(retval->resampler_padding_samples, sizeof (float));
  1290 
  1291     if (retval->resampler_padding == NULL) {
  1292         SDL_FreeAudioStream(retval);
  1293         SDL_OutOfMemory();
  1294         return NULL;
  1295     }
  1296 
  1297     /* Not resampling? It's an easy conversion (and maybe not even that!). */
  1298     if (src_rate == dst_rate) {
  1299         retval->cvt_before_resampling.needed = SDL_FALSE;
  1300         if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, src_format, src_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) {
  1301             SDL_FreeAudioStream(retval);
  1302             return NULL;  /* SDL_BuildAudioCVT should have called SDL_SetError. */
  1303         }
  1304     } else {
  1305         /* Don't resample at first. Just get us to Float32 format. */
  1306         /* !!! FIXME: convert to int32 on devices without hardware float. */
  1307         if (SDL_BuildAudioCVT(&retval->cvt_before_resampling, src_format, src_channels, src_rate, AUDIO_F32SYS, pre_resample_channels, src_rate) < 0) {
  1308             SDL_FreeAudioStream(retval);
  1309             return NULL;  /* SDL_BuildAudioCVT should have called SDL_SetError. */
  1310         }
  1311 
  1312 #ifdef HAVE_LIBSAMPLERATE_H
  1313         SetupLibSampleRateResampling(retval);
  1314 #endif
  1315 
  1316         if (!retval->resampler_func) {
  1317             retval->resampler_state = SDL_calloc(retval->resampler_padding_samples, sizeof (float));
  1318             if (!retval->resampler_state) {
  1319                 SDL_FreeAudioStream(retval);
  1320                 SDL_OutOfMemory();
  1321                 return NULL;
  1322             }
  1323 
  1324             if (SDL_PrepareResampleFilter() < 0) {
  1325                 SDL_free(retval->resampler_state);
  1326                 retval->resampler_state = NULL;
  1327                 SDL_FreeAudioStream(retval);
  1328                 return NULL;
  1329             }
  1330 
  1331             retval->resampler_func = SDL_ResampleAudioStream;
  1332             retval->reset_resampler_func = SDL_ResetAudioStreamResampler;
  1333             retval->cleanup_resampler_func = SDL_CleanupAudioStreamResampler;
  1334         }
  1335 
  1336         /* Convert us to the final format after resampling. */
  1337         if (SDL_BuildAudioCVT(&retval->cvt_after_resampling, AUDIO_F32SYS, pre_resample_channels, dst_rate, dst_format, dst_channels, dst_rate) < 0) {
  1338             SDL_FreeAudioStream(retval);
  1339             return NULL;  /* SDL_BuildAudioCVT should have called SDL_SetError. */
  1340         }
  1341     }
  1342 
  1343     retval->queue = SDL_NewDataQueue(packetlen, packetlen * 2);
  1344     if (!retval->queue) {
  1345         SDL_FreeAudioStream(retval);
  1346         return NULL;  /* SDL_NewDataQueue should have called SDL_SetError. */
  1347     }
  1348 
  1349     return retval;
  1350 }
  1351 
  1352 int
  1353 SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, const Uint32 _buflen)
  1354 {
  1355     int buflen = (int) _buflen;
  1356     int workbuflen;
  1357     Uint8 *workbuf;
  1358     Uint8 *resamplebuf = NULL;
  1359     int resamplebuflen = 0;
  1360     int neededpaddingbytes;
  1361     int paddingbytes;
  1362 
  1363     /* !!! FIXME: several converters can take advantage of SIMD, but only
  1364        !!! FIXME:  if the data is aligned to 16 bytes. EnsureStreamBufferSize()
  1365        !!! FIXME:  guarantees the buffer will align, but the
  1366        !!! FIXME:  converters will iterate over the data backwards if
  1367        !!! FIXME:  the output grows, and this means we won't align if buflen
  1368        !!! FIXME:  isn't a multiple of 16. In these cases, we should chop off
  1369        !!! FIXME:  a few samples at the end and convert them separately. */
  1370 
  1371     #if DEBUG_AUDIOSTREAM
  1372     printf("AUDIOSTREAM: wants to put %d preconverted bytes\n", buflen);
  1373     #endif
  1374 
  1375     if (!stream) {
  1376         return SDL_InvalidParamError("stream");
  1377     } else if (!buf) {
  1378         return SDL_InvalidParamError("buf");
  1379     } else if (buflen == 0) {
  1380         return 0;  /* nothing to do. */
  1381     } else if ((buflen % stream->src_sample_frame_size) != 0) {
  1382         return SDL_SetError("Can't add partial sample frames");
  1383     } else if (buflen < ((stream->resampler_padding_samples / stream->pre_resample_channels) * stream->src_sample_frame_size)) {
  1384         return SDL_SetError("Need to put a larger buffer");
  1385     }
  1386 
  1387     /* no padding prepended on first run. */
  1388     neededpaddingbytes = stream->resampler_padding_samples * sizeof (float);
  1389     paddingbytes = stream->first_run ? 0 : neededpaddingbytes;
  1390     stream->first_run = SDL_FALSE;
  1391 
  1392     if (!stream->cvt_before_resampling.needed &&
  1393         (stream->dst_rate == stream->src_rate) &&
  1394         !stream->cvt_after_resampling.needed) {
  1395         #if DEBUG_AUDIOSTREAM
  1396         printf("AUDIOSTREAM: no conversion needed at all, queueing %d bytes.\n", buflen);
  1397         #endif
  1398         return SDL_WriteToDataQueue(stream->queue, buf, buflen);
  1399     }
  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     /* resamplebuf holds the final output, even if we didn't resample. */
  1496     return buflen ? SDL_WriteToDataQueue(stream->queue, resamplebuf, buflen) : 0;
  1497 }
  1498 
  1499 void
  1500 SDL_AudioStreamClear(SDL_AudioStream *stream)
  1501 {
  1502     if (!stream) {
  1503         SDL_InvalidParamError("stream");
  1504     } else {
  1505         SDL_ClearDataQueue(stream->queue, stream->packetlen * 2);
  1506         if (stream->reset_resampler_func) {
  1507             stream->reset_resampler_func(stream);
  1508         }
  1509         stream->first_run = SDL_TRUE;
  1510     }
  1511 }
  1512 
  1513 
  1514 /* get converted/resampled data from the stream */
  1515 int
  1516 SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, const Uint32 len)
  1517 {
  1518     #if DEBUG_AUDIOSTREAM
  1519     printf("AUDIOSTREAM: want to get %u converted bytes\n", (unsigned int) len);
  1520     #endif
  1521 
  1522     if (!stream) {
  1523         return SDL_InvalidParamError("stream");
  1524     } else if (!buf) {
  1525         return SDL_InvalidParamError("buf");
  1526     } else if (len == 0) {
  1527         return 0;  /* nothing to do. */
  1528     } else if ((len % stream->dst_sample_frame_size) != 0) {
  1529         return SDL_SetError("Can't request partial sample frames");
  1530     }
  1531 
  1532     return (int) SDL_ReadFromDataQueue(stream->queue, buf, len);
  1533 }
  1534 
  1535 /* number of converted/resampled bytes available */
  1536 int
  1537 SDL_AudioStreamAvailable(SDL_AudioStream *stream)
  1538 {
  1539     return stream ? (int) SDL_CountDataQueue(stream->queue) : 0;
  1540 }
  1541 
  1542 /* dispose of a stream */
  1543 void
  1544 SDL_FreeAudioStream(SDL_AudioStream *stream)
  1545 {
  1546     if (stream) {
  1547         if (stream->cleanup_resampler_func) {
  1548             stream->cleanup_resampler_func(stream);
  1549         }
  1550         SDL_FreeDataQueue(stream->queue);
  1551         SDL_free(stream->work_buffer_base);
  1552         SDL_free(stream->resampler_padding);
  1553         SDL_free(stream);
  1554     }
  1555 }
  1556 
  1557 /* vi: set ts=4 sw=4 expandtab: */
  1558