src/audio/SDL_audiocvt.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 28 Aug 2017 21:42:39 -0700
changeset 11406 f40c2dedaded
parent 11405 4e12f78c2b0e
child 11508 a8382e3d0b54
permissions -rw-r--r--
Fixed bug 3662 - Error message when using the audio conversion setup without an initialized audio subsystem is a bit vague

Simon Hug

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