cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_audiocvt.c (36638B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 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_audio.h"
     26#include "SDL_audio_c.h"
     27
     28#include "SDL_assert.h"
     29
     30/* #define DEBUG_CONVERT */
     31
     32/* Effectively mix right and left channels into a single channel */
     33static void SDLCALL
     34SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format)
     35{
     36    int i;
     37    Sint32 sample;
     38
     39#ifdef DEBUG_CONVERT
     40    fprintf(stderr, "Converting to mono\n");
     41#endif
     42	switch (format & (SDL_AUDIO_MASK_SIGNED |
     43                      SDL_AUDIO_MASK_BITSIZE |
     44                      SDL_AUDIO_MASK_DATATYPE)) {
     45    case AUDIO_U8:
     46        {
     47            Uint8 *src, *dst;
     48
     49            src = cvt->buf;
     50            dst = cvt->buf;
     51            for (i = cvt->len_cvt / 2; i; --i) {
     52                sample = src[0] + src[1];
     53                *dst = (Uint8) (sample / 2);
     54                src += 2;
     55                dst += 1;
     56            }
     57        }
     58        break;
     59
     60    case AUDIO_S8:
     61        {
     62            Sint8 *src, *dst;
     63
     64            src = (Sint8 *) cvt->buf;
     65            dst = (Sint8 *) cvt->buf;
     66            for (i = cvt->len_cvt / 2; i; --i) {
     67                sample = src[0] + src[1];
     68                *dst = (Sint8) (sample / 2);
     69                src += 2;
     70                dst += 1;
     71            }
     72        }
     73        break;
     74
     75    case AUDIO_U16:
     76        {
     77            Uint8 *src, *dst;
     78
     79            src = cvt->buf;
     80            dst = cvt->buf;
     81            if (SDL_AUDIO_ISBIGENDIAN(format)) {
     82                for (i = cvt->len_cvt / 4; i; --i) {
     83                    sample = (Uint16) ((src[0] << 8) | src[1]) +
     84                        (Uint16) ((src[2] << 8) | src[3]);
     85                    sample /= 2;
     86                    dst[1] = (sample & 0xFF);
     87                    sample >>= 8;
     88                    dst[0] = (sample & 0xFF);
     89                    src += 4;
     90                    dst += 2;
     91                }
     92            } else {
     93                for (i = cvt->len_cvt / 4; i; --i) {
     94                    sample = (Uint16) ((src[1] << 8) | src[0]) +
     95                        (Uint16) ((src[3] << 8) | src[2]);
     96                    sample /= 2;
     97                    dst[0] = (sample & 0xFF);
     98                    sample >>= 8;
     99                    dst[1] = (sample & 0xFF);
    100                    src += 4;
    101                    dst += 2;
    102                }
    103            }
    104        }
    105        break;
    106
    107    case AUDIO_S16:
    108        {
    109            Uint8 *src, *dst;
    110
    111            src = cvt->buf;
    112            dst = cvt->buf;
    113            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    114                for (i = cvt->len_cvt / 4; i; --i) {
    115                    sample = (Sint16) ((src[0] << 8) | src[1]) +
    116                        (Sint16) ((src[2] << 8) | src[3]);
    117                    sample /= 2;
    118                    dst[1] = (sample & 0xFF);
    119                    sample >>= 8;
    120                    dst[0] = (sample & 0xFF);
    121                    src += 4;
    122                    dst += 2;
    123                }
    124            } else {
    125                for (i = cvt->len_cvt / 4; i; --i) {
    126                    sample = (Sint16) ((src[1] << 8) | src[0]) +
    127                        (Sint16) ((src[3] << 8) | src[2]);
    128                    sample /= 2;
    129                    dst[0] = (sample & 0xFF);
    130                    sample >>= 8;
    131                    dst[1] = (sample & 0xFF);
    132                    src += 4;
    133                    dst += 2;
    134                }
    135            }
    136        }
    137        break;
    138
    139    case AUDIO_S32:
    140        {
    141            const Uint32 *src = (const Uint32 *) cvt->buf;
    142            Uint32 *dst = (Uint32 *) cvt->buf;
    143            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    144                for (i = cvt->len_cvt / 8; i; --i, src += 2) {
    145                    const Sint64 added =
    146                        (((Sint64) (Sint32) SDL_SwapBE32(src[0])) +
    147                         ((Sint64) (Sint32) SDL_SwapBE32(src[1])));
    148                    *(dst++) = SDL_SwapBE32((Uint32) ((Sint32) (added / 2)));
    149                }
    150            } else {
    151                for (i = cvt->len_cvt / 8; i; --i, src += 2) {
    152                    const Sint64 added =
    153                        (((Sint64) (Sint32) SDL_SwapLE32(src[0])) +
    154                         ((Sint64) (Sint32) SDL_SwapLE32(src[1])));
    155                    *(dst++) = SDL_SwapLE32((Uint32) ((Sint32) (added / 2)));
    156                }
    157            }
    158        }
    159        break;
    160
    161    case AUDIO_F32:
    162        {
    163            const float *src = (const float *) cvt->buf;
    164            float *dst = (float *) cvt->buf;
    165            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    166                for (i = cvt->len_cvt / 8; i; --i, src += 2) {
    167                    const float src1 = SDL_SwapFloatBE(src[0]);
    168                    const float src2 = SDL_SwapFloatBE(src[1]);
    169                    const double added = ((double) src1) + ((double) src2);
    170                    const float halved = (float) (added * 0.5);
    171                    *(dst++) = SDL_SwapFloatBE(halved);
    172                }
    173            } else {
    174                for (i = cvt->len_cvt / 8; i; --i, src += 2) {
    175                    const float src1 = SDL_SwapFloatLE(src[0]);
    176                    const float src2 = SDL_SwapFloatLE(src[1]);
    177                    const double added = ((double) src1) + ((double) src2);
    178                    const float halved = (float) (added * 0.5);
    179                    *(dst++) = SDL_SwapFloatLE(halved);
    180                }
    181            }
    182        }
    183        break;
    184    }
    185
    186    cvt->len_cvt /= 2;
    187    if (cvt->filters[++cvt->filter_index]) {
    188        cvt->filters[cvt->filter_index] (cvt, format);
    189    }
    190}
    191
    192
    193/* Discard top 4 channels */
    194static void SDLCALL
    195SDL_ConvertStrip(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    196{
    197    int i;
    198
    199#ifdef DEBUG_CONVERT
    200    fprintf(stderr, "Converting down from 6 channels to stereo\n");
    201#endif
    202
    203#define strip_chans_6_to_2(type) \
    204    { \
    205        const type *src = (const type *) cvt->buf; \
    206        type *dst = (type *) cvt->buf; \
    207        for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
    208            dst[0] = src[0]; \
    209            dst[1] = src[1]; \
    210            src += 6; \
    211            dst += 2; \
    212        } \
    213    }
    214
    215    /* this function only cares about typesize, and data as a block of bits. */
    216    switch (SDL_AUDIO_BITSIZE(format)) {
    217    case 8:
    218        strip_chans_6_to_2(Uint8);
    219        break;
    220    case 16:
    221        strip_chans_6_to_2(Uint16);
    222        break;
    223    case 32:
    224        strip_chans_6_to_2(Uint32);
    225        break;
    226    }
    227
    228#undef strip_chans_6_to_2
    229
    230    cvt->len_cvt /= 3;
    231    if (cvt->filters[++cvt->filter_index]) {
    232        cvt->filters[cvt->filter_index] (cvt, format);
    233    }
    234}
    235
    236
    237/* Discard top 2 channels of 6 */
    238static void SDLCALL
    239SDL_ConvertStrip_2(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    240{
    241    int i;
    242
    243#ifdef DEBUG_CONVERT
    244    fprintf(stderr, "Converting 6 down to quad\n");
    245#endif
    246
    247#define strip_chans_6_to_4(type) \
    248    { \
    249        const type *src = (const type *) cvt->buf; \
    250        type *dst = (type *) cvt->buf; \
    251        for (i = cvt->len_cvt / (sizeof (type) * 6); i; --i) { \
    252            dst[0] = src[0]; \
    253            dst[1] = src[1]; \
    254            dst[2] = src[2]; \
    255            dst[3] = src[3]; \
    256            src += 6; \
    257            dst += 4; \
    258        } \
    259    }
    260
    261    /* this function only cares about typesize, and data as a block of bits. */
    262    switch (SDL_AUDIO_BITSIZE(format)) {
    263    case 8:
    264        strip_chans_6_to_4(Uint8);
    265        break;
    266    case 16:
    267        strip_chans_6_to_4(Uint16);
    268        break;
    269    case 32:
    270        strip_chans_6_to_4(Uint32);
    271        break;
    272    }
    273
    274#undef strip_chans_6_to_4
    275
    276    cvt->len_cvt /= 6;
    277    cvt->len_cvt *= 4;
    278    if (cvt->filters[++cvt->filter_index]) {
    279        cvt->filters[cvt->filter_index] (cvt, format);
    280    }
    281}
    282
    283/* Duplicate a mono channel to both stereo channels */
    284static void SDLCALL
    285SDL_ConvertStereo(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    286{
    287    int i;
    288
    289#ifdef DEBUG_CONVERT
    290    fprintf(stderr, "Converting to stereo\n");
    291#endif
    292
    293#define dup_chans_1_to_2(type) \
    294    { \
    295        const type *src = (const type *) (cvt->buf + cvt->len_cvt); \
    296        type *dst = (type *) (cvt->buf + cvt->len_cvt * 2); \
    297        for (i = cvt->len_cvt / sizeof(type); i; --i) { \
    298            src -= 1; \
    299            dst -= 2; \
    300            dst[0] = dst[1] = *src; \
    301        } \
    302    }
    303
    304    /* this function only cares about typesize, and data as a block of bits. */
    305    switch (SDL_AUDIO_BITSIZE(format)) {
    306    case 8:
    307        dup_chans_1_to_2(Uint8);
    308        break;
    309    case 16:
    310        dup_chans_1_to_2(Uint16);
    311        break;
    312    case 32:
    313        dup_chans_1_to_2(Uint32);
    314        break;
    315    }
    316
    317#undef dup_chans_1_to_2
    318
    319    cvt->len_cvt *= 2;
    320    if (cvt->filters[++cvt->filter_index]) {
    321        cvt->filters[cvt->filter_index] (cvt, format);
    322    }
    323}
    324
    325
    326/* Duplicate a stereo channel to a pseudo-5.1 stream */
    327static void SDLCALL
    328SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    329{
    330    int i;
    331
    332#ifdef DEBUG_CONVERT
    333    fprintf(stderr, "Converting stereo to surround\n");
    334#endif
    335
    336    switch (format & (SDL_AUDIO_MASK_SIGNED  |
    337                      SDL_AUDIO_MASK_BITSIZE |
    338                      SDL_AUDIO_MASK_DATATYPE)) {
    339    case AUDIO_U8:
    340        {
    341            Uint8 *src, *dst, lf, rf, ce;
    342
    343            src = (Uint8 *) (cvt->buf + cvt->len_cvt);
    344            dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3);
    345            for (i = cvt->len_cvt; i; --i) {
    346                dst -= 6;
    347                src -= 2;
    348                lf = src[0];
    349                rf = src[1];
    350                ce = (lf / 2) + (rf / 2);
    351                dst[0] = lf;
    352                dst[1] = rf;
    353                dst[2] = lf - ce;
    354                dst[3] = rf - ce;
    355                dst[4] = ce;
    356                dst[5] = ce;
    357            }
    358        }
    359        break;
    360
    361    case AUDIO_S8:
    362        {
    363            Sint8 *src, *dst, lf, rf, ce;
    364
    365            src = (Sint8 *) cvt->buf + cvt->len_cvt;
    366            dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3;
    367            for (i = cvt->len_cvt; i; --i) {
    368                dst -= 6;
    369                src -= 2;
    370                lf = src[0];
    371                rf = src[1];
    372                ce = (lf / 2) + (rf / 2);
    373                dst[0] = lf;
    374                dst[1] = rf;
    375                dst[2] = lf - ce;
    376                dst[3] = rf - ce;
    377                dst[4] = ce;
    378                dst[5] = ce;
    379            }
    380        }
    381        break;
    382
    383    case AUDIO_U16:
    384        {
    385            Uint8 *src, *dst;
    386            Uint16 lf, rf, ce, lr, rr;
    387
    388            src = cvt->buf + cvt->len_cvt;
    389            dst = cvt->buf + cvt->len_cvt * 3;
    390
    391            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    392                for (i = cvt->len_cvt / 4; i; --i) {
    393                    dst -= 12;
    394                    src -= 4;
    395                    lf = (Uint16) ((src[0] << 8) | src[1]);
    396                    rf = (Uint16) ((src[2] << 8) | src[3]);
    397                    ce = (lf / 2) + (rf / 2);
    398                    rr = lf - ce;
    399                    lr = rf - ce;
    400                    dst[1] = (lf & 0xFF);
    401                    dst[0] = ((lf >> 8) & 0xFF);
    402                    dst[3] = (rf & 0xFF);
    403                    dst[2] = ((rf >> 8) & 0xFF);
    404
    405                    dst[1 + 4] = (lr & 0xFF);
    406                    dst[0 + 4] = ((lr >> 8) & 0xFF);
    407                    dst[3 + 4] = (rr & 0xFF);
    408                    dst[2 + 4] = ((rr >> 8) & 0xFF);
    409
    410                    dst[1 + 8] = (ce & 0xFF);
    411                    dst[0 + 8] = ((ce >> 8) & 0xFF);
    412                    dst[3 + 8] = (ce & 0xFF);
    413                    dst[2 + 8] = ((ce >> 8) & 0xFF);
    414                }
    415            } else {
    416                for (i = cvt->len_cvt / 4; i; --i) {
    417                    dst -= 12;
    418                    src -= 4;
    419                    lf = (Uint16) ((src[1] << 8) | src[0]);
    420                    rf = (Uint16) ((src[3] << 8) | src[2]);
    421                    ce = (lf / 2) + (rf / 2);
    422                    rr = lf - ce;
    423                    lr = rf - ce;
    424                    dst[0] = (lf & 0xFF);
    425                    dst[1] = ((lf >> 8) & 0xFF);
    426                    dst[2] = (rf & 0xFF);
    427                    dst[3] = ((rf >> 8) & 0xFF);
    428
    429                    dst[0 + 4] = (lr & 0xFF);
    430                    dst[1 + 4] = ((lr >> 8) & 0xFF);
    431                    dst[2 + 4] = (rr & 0xFF);
    432                    dst[3 + 4] = ((rr >> 8) & 0xFF);
    433
    434                    dst[0 + 8] = (ce & 0xFF);
    435                    dst[1 + 8] = ((ce >> 8) & 0xFF);
    436                    dst[2 + 8] = (ce & 0xFF);
    437                    dst[3 + 8] = ((ce >> 8) & 0xFF);
    438                }
    439            }
    440        }
    441        break;
    442
    443    case AUDIO_S16:
    444        {
    445            Uint8 *src, *dst;
    446            Sint16 lf, rf, ce, lr, rr;
    447
    448            src = cvt->buf + cvt->len_cvt;
    449            dst = cvt->buf + cvt->len_cvt * 3;
    450
    451            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    452                for (i = cvt->len_cvt / 4; i; --i) {
    453                    dst -= 12;
    454                    src -= 4;
    455                    lf = (Sint16) ((src[0] << 8) | src[1]);
    456                    rf = (Sint16) ((src[2] << 8) | src[3]);
    457                    ce = (lf / 2) + (rf / 2);
    458                    rr = lf - ce;
    459                    lr = rf - ce;
    460                    dst[1] = (lf & 0xFF);
    461                    dst[0] = ((lf >> 8) & 0xFF);
    462                    dst[3] = (rf & 0xFF);
    463                    dst[2] = ((rf >> 8) & 0xFF);
    464
    465                    dst[1 + 4] = (lr & 0xFF);
    466                    dst[0 + 4] = ((lr >> 8) & 0xFF);
    467                    dst[3 + 4] = (rr & 0xFF);
    468                    dst[2 + 4] = ((rr >> 8) & 0xFF);
    469
    470                    dst[1 + 8] = (ce & 0xFF);
    471                    dst[0 + 8] = ((ce >> 8) & 0xFF);
    472                    dst[3 + 8] = (ce & 0xFF);
    473                    dst[2 + 8] = ((ce >> 8) & 0xFF);
    474                }
    475            } else {
    476                for (i = cvt->len_cvt / 4; i; --i) {
    477                    dst -= 12;
    478                    src -= 4;
    479                    lf = (Sint16) ((src[1] << 8) | src[0]);
    480                    rf = (Sint16) ((src[3] << 8) | src[2]);
    481                    ce = (lf / 2) + (rf / 2);
    482                    rr = lf - ce;
    483                    lr = rf - ce;
    484                    dst[0] = (lf & 0xFF);
    485                    dst[1] = ((lf >> 8) & 0xFF);
    486                    dst[2] = (rf & 0xFF);
    487                    dst[3] = ((rf >> 8) & 0xFF);
    488
    489                    dst[0 + 4] = (lr & 0xFF);
    490                    dst[1 + 4] = ((lr >> 8) & 0xFF);
    491                    dst[2 + 4] = (rr & 0xFF);
    492                    dst[3 + 4] = ((rr >> 8) & 0xFF);
    493
    494                    dst[0 + 8] = (ce & 0xFF);
    495                    dst[1 + 8] = ((ce >> 8) & 0xFF);
    496                    dst[2 + 8] = (ce & 0xFF);
    497                    dst[3 + 8] = ((ce >> 8) & 0xFF);
    498                }
    499            }
    500        }
    501        break;
    502
    503    case AUDIO_S32:
    504        {
    505            Sint32 lf, rf, ce;
    506            const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
    507            Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 3);
    508
    509            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    510                for (i = cvt->len_cvt / 8; i; --i) {
    511                    dst -= 6;
    512                    src -= 2;
    513                    lf = (Sint32) SDL_SwapBE32(src[0]);
    514                    rf = (Sint32) SDL_SwapBE32(src[1]);
    515                    ce = (lf / 2) + (rf / 2);
    516                    dst[0] = SDL_SwapBE32((Uint32) lf);
    517                    dst[1] = SDL_SwapBE32((Uint32) rf);
    518                    dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
    519                    dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
    520                    dst[4] = SDL_SwapBE32((Uint32) ce);
    521                    dst[5] = SDL_SwapBE32((Uint32) ce);
    522                }
    523            } else {
    524                for (i = cvt->len_cvt / 8; i; --i) {
    525                    dst -= 6;
    526                    src -= 2;
    527                    lf = (Sint32) SDL_SwapLE32(src[0]);
    528                    rf = (Sint32) SDL_SwapLE32(src[1]);
    529                    ce = (lf / 2) + (rf / 2);
    530                    dst[0] = src[0];
    531                    dst[1] = src[1];
    532                    dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
    533                    dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
    534                    dst[4] = SDL_SwapLE32((Uint32) ce);
    535                    dst[5] = SDL_SwapLE32((Uint32) ce);
    536                }
    537            }
    538        }
    539        break;
    540
    541    case AUDIO_F32:
    542        {
    543            float lf, rf, ce;
    544            const float *src = (const float *) (cvt->buf + cvt->len_cvt);
    545            float *dst = (float *) (cvt->buf + cvt->len_cvt * 3);
    546
    547            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    548                for (i = cvt->len_cvt / 8; i; --i) {
    549                    dst -= 6;
    550                    src -= 2;
    551                    lf = SDL_SwapFloatBE(src[0]);
    552                    rf = SDL_SwapFloatBE(src[1]);
    553                    ce = (lf * 0.5f) + (rf * 0.5f);
    554                    dst[0] = src[0];
    555                    dst[1] = src[1];
    556                    dst[2] = SDL_SwapFloatBE(lf - ce);
    557                    dst[3] = SDL_SwapFloatBE(rf - ce);
    558                    dst[4] = dst[5] = SDL_SwapFloatBE(ce);
    559                }
    560            } else {
    561                for (i = cvt->len_cvt / 8; i; --i) {
    562                    dst -= 6;
    563                    src -= 2;
    564                    lf = SDL_SwapFloatLE(src[0]);
    565                    rf = SDL_SwapFloatLE(src[1]);
    566                    ce = (lf * 0.5f) + (rf * 0.5f);
    567                    dst[0] = src[0];
    568                    dst[1] = src[1];
    569                    dst[2] = SDL_SwapFloatLE(lf - ce);
    570                    dst[3] = SDL_SwapFloatLE(rf - ce);
    571                    dst[4] = dst[5] = SDL_SwapFloatLE(ce);
    572                }
    573            }
    574        }
    575        break;
    576
    577    }
    578    cvt->len_cvt *= 3;
    579    if (cvt->filters[++cvt->filter_index]) {
    580        cvt->filters[cvt->filter_index] (cvt, format);
    581    }
    582}
    583
    584
    585/* Duplicate a stereo channel to a pseudo-4.0 stream */
    586static void SDLCALL
    587SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format)
    588{
    589    int i;
    590
    591#ifdef DEBUG_CONVERT
    592    fprintf(stderr, "Converting stereo to quad\n");
    593#endif
    594
    595    switch (format & (SDL_AUDIO_MASK_SIGNED |
    596                      SDL_AUDIO_MASK_BITSIZE |
    597                      SDL_AUDIO_MASK_DATATYPE)) {
    598    case AUDIO_U8:
    599        {
    600            Uint8 *src, *dst, lf, rf, ce;
    601
    602            src = (Uint8 *) (cvt->buf + cvt->len_cvt);
    603            dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2);
    604            for (i = cvt->len_cvt; i; --i) {
    605                dst -= 4;
    606                src -= 2;
    607                lf = src[0];
    608                rf = src[1];
    609                ce = (lf / 2) + (rf / 2);
    610                dst[0] = lf;
    611                dst[1] = rf;
    612                dst[2] = lf - ce;
    613                dst[3] = rf - ce;
    614            }
    615        }
    616        break;
    617
    618    case AUDIO_S8:
    619        {
    620            Sint8 *src, *dst, lf, rf, ce;
    621
    622            src = (Sint8 *) cvt->buf + cvt->len_cvt;
    623            dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2;
    624            for (i = cvt->len_cvt; i; --i) {
    625                dst -= 4;
    626                src -= 2;
    627                lf = src[0];
    628                rf = src[1];
    629                ce = (lf / 2) + (rf / 2);
    630                dst[0] = lf;
    631                dst[1] = rf;
    632                dst[2] = lf - ce;
    633                dst[3] = rf - ce;
    634            }
    635        }
    636        break;
    637
    638    case AUDIO_U16:
    639        {
    640            Uint8 *src, *dst;
    641            Uint16 lf, rf, ce, lr, rr;
    642
    643            src = cvt->buf + cvt->len_cvt;
    644            dst = cvt->buf + cvt->len_cvt * 2;
    645
    646            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    647                for (i = cvt->len_cvt / 4; i; --i) {
    648                    dst -= 8;
    649                    src -= 4;
    650                    lf = (Uint16) ((src[0] << 8) | src[1]);
    651                    rf = (Uint16) ((src[2] << 8) | src[3]);
    652                    ce = (lf / 2) + (rf / 2);
    653                    rr = lf - ce;
    654                    lr = rf - ce;
    655                    dst[1] = (lf & 0xFF);
    656                    dst[0] = ((lf >> 8) & 0xFF);
    657                    dst[3] = (rf & 0xFF);
    658                    dst[2] = ((rf >> 8) & 0xFF);
    659
    660                    dst[1 + 4] = (lr & 0xFF);
    661                    dst[0 + 4] = ((lr >> 8) & 0xFF);
    662                    dst[3 + 4] = (rr & 0xFF);
    663                    dst[2 + 4] = ((rr >> 8) & 0xFF);
    664                }
    665            } else {
    666                for (i = cvt->len_cvt / 4; i; --i) {
    667                    dst -= 8;
    668                    src -= 4;
    669                    lf = (Uint16) ((src[1] << 8) | src[0]);
    670                    rf = (Uint16) ((src[3] << 8) | src[2]);
    671                    ce = (lf / 2) + (rf / 2);
    672                    rr = lf - ce;
    673                    lr = rf - ce;
    674                    dst[0] = (lf & 0xFF);
    675                    dst[1] = ((lf >> 8) & 0xFF);
    676                    dst[2] = (rf & 0xFF);
    677                    dst[3] = ((rf >> 8) & 0xFF);
    678
    679                    dst[0 + 4] = (lr & 0xFF);
    680                    dst[1 + 4] = ((lr >> 8) & 0xFF);
    681                    dst[2 + 4] = (rr & 0xFF);
    682                    dst[3 + 4] = ((rr >> 8) & 0xFF);
    683                }
    684            }
    685        }
    686        break;
    687
    688    case AUDIO_S16:
    689        {
    690            Uint8 *src, *dst;
    691            Sint16 lf, rf, ce, lr, rr;
    692
    693            src = cvt->buf + cvt->len_cvt;
    694            dst = cvt->buf + cvt->len_cvt * 2;
    695
    696            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    697                for (i = cvt->len_cvt / 4; i; --i) {
    698                    dst -= 8;
    699                    src -= 4;
    700                    lf = (Sint16) ((src[0] << 8) | src[1]);
    701                    rf = (Sint16) ((src[2] << 8) | src[3]);
    702                    ce = (lf / 2) + (rf / 2);
    703                    rr = lf - ce;
    704                    lr = rf - ce;
    705                    dst[1] = (lf & 0xFF);
    706                    dst[0] = ((lf >> 8) & 0xFF);
    707                    dst[3] = (rf & 0xFF);
    708                    dst[2] = ((rf >> 8) & 0xFF);
    709
    710                    dst[1 + 4] = (lr & 0xFF);
    711                    dst[0 + 4] = ((lr >> 8) & 0xFF);
    712                    dst[3 + 4] = (rr & 0xFF);
    713                    dst[2 + 4] = ((rr >> 8) & 0xFF);
    714                }
    715            } else {
    716                for (i = cvt->len_cvt / 4; i; --i) {
    717                    dst -= 8;
    718                    src -= 4;
    719                    lf = (Sint16) ((src[1] << 8) | src[0]);
    720                    rf = (Sint16) ((src[3] << 8) | src[2]);
    721                    ce = (lf / 2) + (rf / 2);
    722                    rr = lf - ce;
    723                    lr = rf - ce;
    724                    dst[0] = (lf & 0xFF);
    725                    dst[1] = ((lf >> 8) & 0xFF);
    726                    dst[2] = (rf & 0xFF);
    727                    dst[3] = ((rf >> 8) & 0xFF);
    728
    729                    dst[0 + 4] = (lr & 0xFF);
    730                    dst[1 + 4] = ((lr >> 8) & 0xFF);
    731                    dst[2 + 4] = (rr & 0xFF);
    732                    dst[3 + 4] = ((rr >> 8) & 0xFF);
    733                }
    734            }
    735        }
    736        break;
    737
    738    case AUDIO_S32:
    739        {
    740            const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt);
    741            Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 2);
    742            Sint32 lf, rf, ce;
    743
    744            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    745                for (i = cvt->len_cvt / 8; i; --i) {
    746                    dst -= 4;
    747                    src -= 2;
    748                    lf = (Sint32) SDL_SwapBE32(src[0]);
    749                    rf = (Sint32) SDL_SwapBE32(src[1]);
    750                    ce = (lf / 2) + (rf / 2);
    751                    dst[0] = src[0];
    752                    dst[1] = src[1];
    753                    dst[2] = SDL_SwapBE32((Uint32) (lf - ce));
    754                    dst[3] = SDL_SwapBE32((Uint32) (rf - ce));
    755                }
    756            } else {
    757                for (i = cvt->len_cvt / 8; i; --i) {
    758                    dst -= 4;
    759                    src -= 2;
    760                    lf = (Sint32) SDL_SwapLE32(src[0]);
    761                    rf = (Sint32) SDL_SwapLE32(src[1]);
    762                    ce = (lf / 2) + (rf / 2);
    763                    dst[0] = src[0];
    764                    dst[1] = src[1];
    765                    dst[2] = SDL_SwapLE32((Uint32) (lf - ce));
    766                    dst[3] = SDL_SwapLE32((Uint32) (rf - ce));
    767                }
    768            }
    769        }
    770        break;
    771
    772    case AUDIO_F32:
    773        {
    774            const float *src = (const float *) (cvt->buf + cvt->len_cvt);
    775            float *dst = (float *) (cvt->buf + cvt->len_cvt * 2);
    776            float lf, rf, ce;
    777
    778            if (SDL_AUDIO_ISBIGENDIAN(format)) {
    779                for (i = cvt->len_cvt / 8; i; --i) {
    780                    dst -= 4;
    781                    src -= 2;
    782                    lf = SDL_SwapFloatBE(src[0]);
    783                    rf = SDL_SwapFloatBE(src[1]);
    784                    ce = (lf / 2) + (rf / 2);
    785                    dst[0] = src[0];
    786                    dst[1] = src[1];
    787                    dst[2] = SDL_SwapFloatBE(lf - ce);
    788                    dst[3] = SDL_SwapFloatBE(rf - ce);
    789                }
    790            } else {
    791                for (i = cvt->len_cvt / 8; i; --i) {
    792                    dst -= 4;
    793                    src -= 2;
    794                    lf = SDL_SwapFloatLE(src[0]);
    795                    rf = SDL_SwapFloatLE(src[1]);
    796                    ce = (lf / 2) + (rf / 2);
    797                    dst[0] = src[0];
    798                    dst[1] = src[1];
    799                    dst[2] = SDL_SwapFloatLE(lf - ce);
    800                    dst[3] = SDL_SwapFloatLE(rf - ce);
    801                }
    802            }
    803        }
    804        break;
    805    }
    806    cvt->len_cvt *= 2;
    807    if (cvt->filters[++cvt->filter_index]) {
    808        cvt->filters[cvt->filter_index] (cvt, format);
    809    }
    810}
    811
    812
    813int
    814SDL_ConvertAudio(SDL_AudioCVT * cvt)
    815{
    816    /* !!! FIXME: (cvt) should be const; stack-copy it here. */
    817    /* !!! FIXME: (actually, we can't...len_cvt needs to be updated. Grr.) */
    818
    819    /* Make sure there's data to convert */
    820    if (cvt->buf == NULL) {
    821        SDL_SetError("No buffer allocated for conversion");
    822        return (-1);
    823    }
    824    /* Return okay if no conversion is necessary */
    825    cvt->len_cvt = cvt->len;
    826    if (cvt->filters[0] == NULL) {
    827        return (0);
    828    }
    829
    830    /* Set up the conversion and go! */
    831    cvt->filter_index = 0;
    832    cvt->filters[0] (cvt, cvt->src_format);
    833    return (0);
    834}
    835
    836
    837static SDL_AudioFilter
    838SDL_HandTunedTypeCVT(SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
    839{
    840    /*
    841     * Fill in any future conversions that are specialized to a
    842     *  processor, platform, compiler, or library here.
    843     */
    844
    845    return NULL;                /* no specialized converter code available. */
    846}
    847
    848
    849/*
    850 * Find a converter between two data types. We try to select a hand-tuned
    851 *  asm/vectorized/optimized function first, and then fallback to an
    852 *  autogenerated function that is customized to convert between two
    853 *  specific data types.
    854 */
    855static int
    856SDL_BuildAudioTypeCVT(SDL_AudioCVT * cvt,
    857                      SDL_AudioFormat src_fmt, SDL_AudioFormat dst_fmt)
    858{
    859    if (src_fmt != dst_fmt) {
    860        const Uint16 src_bitsize = SDL_AUDIO_BITSIZE(src_fmt);
    861        const Uint16 dst_bitsize = SDL_AUDIO_BITSIZE(dst_fmt);
    862        SDL_AudioFilter filter = SDL_HandTunedTypeCVT(src_fmt, dst_fmt);
    863
    864        /* No hand-tuned converter? Try the autogenerated ones. */
    865        if (filter == NULL) {
    866            int i;
    867            for (i = 0; sdl_audio_type_filters[i].filter != NULL; i++) {
    868                const SDL_AudioTypeFilters *filt = &sdl_audio_type_filters[i];
    869                if ((filt->src_fmt == src_fmt) && (filt->dst_fmt == dst_fmt)) {
    870                    filter = filt->filter;
    871                    break;
    872                }
    873            }
    874
    875            if (filter == NULL) {
    876                SDL_SetError("No conversion available for these formats");
    877                return -1;
    878            }
    879        }
    880
    881        /* Update (cvt) with filter details... */
    882        cvt->filters[cvt->filter_index++] = filter;
    883        if (src_bitsize < dst_bitsize) {
    884            const int mult = (dst_bitsize / src_bitsize);
    885            cvt->len_mult *= mult;
    886            cvt->len_ratio *= mult;
    887        } else if (src_bitsize > dst_bitsize) {
    888            cvt->len_ratio /= (src_bitsize / dst_bitsize);
    889        }
    890
    891        return 1;               /* added a converter. */
    892    }
    893
    894    return 0;                   /* no conversion necessary. */
    895}
    896
    897
    898static SDL_AudioFilter
    899SDL_HandTunedResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
    900                         int src_rate, int dst_rate)
    901{
    902    /*
    903     * Fill in any future conversions that are specialized to a
    904     *  processor, platform, compiler, or library here.
    905     */
    906
    907    return NULL;                /* no specialized converter code available. */
    908}
    909
    910static int
    911SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
    912{
    913    int retval = 0;
    914
    915    /* If we only built with the arbitrary resamplers, ignore multiples. */
    916#if !LESS_RESAMPLERS
    917    int lo, hi;
    918    int div;
    919
    920    SDL_assert(src_rate != 0);
    921    SDL_assert(dst_rate != 0);
    922    SDL_assert(src_rate != dst_rate);
    923
    924    if (src_rate < dst_rate) {
    925        lo = src_rate;
    926        hi = dst_rate;
    927    } else {
    928        lo = dst_rate;
    929        hi = src_rate;
    930    }
    931
    932    /* zero means "not a supported multiple" ... we only do 2x and 4x. */
    933    if ((hi % lo) != 0)
    934        return 0;               /* not a multiple. */
    935
    936    div = hi / lo;
    937    retval = ((div == 2) || (div == 4)) ? div : 0;
    938#endif
    939
    940    return retval;
    941}
    942
    943static int
    944SDL_BuildAudioResampleCVT(SDL_AudioCVT * cvt, int dst_channels,
    945                          int src_rate, int dst_rate)
    946{
    947    if (src_rate != dst_rate) {
    948        SDL_AudioFilter filter = SDL_HandTunedResampleCVT(cvt, dst_channels,
    949                                                          src_rate, dst_rate);
    950
    951        /* No hand-tuned converter? Try the autogenerated ones. */
    952        if (filter == NULL) {
    953            int i;
    954            const int upsample = (src_rate < dst_rate) ? 1 : 0;
    955            const int multiple =
    956                SDL_FindFrequencyMultiple(src_rate, dst_rate);
    957
    958            for (i = 0; sdl_audio_rate_filters[i].filter != NULL; i++) {
    959                const SDL_AudioRateFilters *filt = &sdl_audio_rate_filters[i];
    960                if ((filt->fmt == cvt->dst_format) &&
    961                    (filt->channels == dst_channels) &&
    962                    (filt->upsample == upsample) &&
    963                    (filt->multiple == multiple)) {
    964                    filter = filt->filter;
    965                    break;
    966                }
    967            }
    968
    969            if (filter == NULL) {
    970                SDL_SetError("No conversion available for these rates");
    971                return -1;
    972            }
    973        }
    974
    975        /* Update (cvt) with filter details... */
    976        cvt->filters[cvt->filter_index++] = filter;
    977        if (src_rate < dst_rate) {
    978            const double mult = ((double) dst_rate) / ((double) src_rate);
    979            cvt->len_mult *= (int) SDL_ceil(mult);
    980            cvt->len_ratio *= mult;
    981        } else {
    982            cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
    983        }
    984
    985        return 1;               /* added a converter. */
    986    }
    987
    988    return 0;                   /* no conversion necessary. */
    989}
    990
    991
    992/* Creates a set of audio filters to convert from one format to another.
    993   Returns -1 if the format conversion is not supported, 0 if there's
    994   no conversion needed, or 1 if the audio filter is set up.
    995*/
    996
    997int
    998SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
    999                  SDL_AudioFormat src_fmt, Uint8 src_channels, int src_rate,
   1000                  SDL_AudioFormat dst_fmt, Uint8 dst_channels, int dst_rate)
   1001{
   1002    /*
   1003     * !!! FIXME: reorder filters based on which grow/shrink the buffer.
   1004     * !!! FIXME: ideally, we should do everything that shrinks the buffer
   1005     * !!! FIXME: first, so we don't have to process as many bytes in a given
   1006     * !!! FIXME: filter and abuse the CPU cache less. This might not be as
   1007     * !!! FIXME: good in practice as it sounds in theory, though.
   1008     */
   1009
   1010    /* Sanity check target pointer */
   1011    if (cvt == NULL) {
   1012        return SDL_InvalidParamError("cvt");
   1013    }
   1014
   1015    /* there are no unsigned types over 16 bits, so catch this up front. */
   1016    if ((SDL_AUDIO_BITSIZE(src_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(src_fmt))) {
   1017        return SDL_SetError("Invalid source format");
   1018    }
   1019    if ((SDL_AUDIO_BITSIZE(dst_fmt) > 16) && (!SDL_AUDIO_ISSIGNED(dst_fmt))) {
   1020        return SDL_SetError("Invalid destination format");
   1021    }
   1022
   1023    /* prevent possible divisions by zero, etc. */
   1024    if ((src_channels == 0) || (dst_channels == 0)) {
   1025        return SDL_SetError("Source or destination channels is zero");
   1026    }
   1027    if ((src_rate == 0) || (dst_rate == 0)) {
   1028        return SDL_SetError("Source or destination rate is zero");
   1029    }
   1030#ifdef DEBUG_CONVERT
   1031    printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
   1032           src_fmt, dst_fmt, src_channels, dst_channels, src_rate, dst_rate);
   1033#endif
   1034
   1035    /* Start off with no conversion necessary */
   1036    SDL_zerop(cvt);
   1037    cvt->src_format = src_fmt;
   1038    cvt->dst_format = dst_fmt;
   1039    cvt->needed = 0;
   1040    cvt->filter_index = 0;
   1041    cvt->filters[0] = NULL;
   1042    cvt->len_mult = 1;
   1043    cvt->len_ratio = 1.0;
   1044    cvt->rate_incr = ((double) dst_rate) / ((double) src_rate);
   1045
   1046    /* Convert data types, if necessary. Updates (cvt). */
   1047    if (SDL_BuildAudioTypeCVT(cvt, src_fmt, dst_fmt) == -1) {
   1048        return -1;              /* shouldn't happen, but just in case... */
   1049    }
   1050
   1051    /* Channel conversion */
   1052    if (src_channels != dst_channels) {
   1053        if ((src_channels == 1) && (dst_channels > 1)) {
   1054            cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
   1055            cvt->len_mult *= 2;
   1056            src_channels = 2;
   1057            cvt->len_ratio *= 2;
   1058        }
   1059        if ((src_channels == 2) && (dst_channels == 6)) {
   1060            cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
   1061            src_channels = 6;
   1062            cvt->len_mult *= 3;
   1063            cvt->len_ratio *= 3;
   1064        }
   1065        if ((src_channels == 2) && (dst_channels == 4)) {
   1066            cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
   1067            src_channels = 4;
   1068            cvt->len_mult *= 2;
   1069            cvt->len_ratio *= 2;
   1070        }
   1071        while ((src_channels * 2) <= dst_channels) {
   1072            cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
   1073            cvt->len_mult *= 2;
   1074            src_channels *= 2;
   1075            cvt->len_ratio *= 2;
   1076        }
   1077        if ((src_channels == 6) && (dst_channels <= 2)) {
   1078            cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
   1079            src_channels = 2;
   1080            cvt->len_ratio /= 3;
   1081        }
   1082        if ((src_channels == 6) && (dst_channels == 4)) {
   1083            cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
   1084            src_channels = 4;
   1085            cvt->len_ratio /= 2;
   1086        }
   1087        /* This assumes that 4 channel audio is in the format:
   1088           Left {front/back} + Right {front/back}
   1089           so converting to L/R stereo works properly.
   1090         */
   1091        while (((src_channels % 2) == 0) &&
   1092               ((src_channels / 2) >= dst_channels)) {
   1093            cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
   1094            src_channels /= 2;
   1095            cvt->len_ratio /= 2;
   1096        }
   1097        if (src_channels != dst_channels) {
   1098            /* Uh oh.. */ ;
   1099        }
   1100    }
   1101
   1102    /* Do rate conversion, if necessary. Updates (cvt). */
   1103    if (SDL_BuildAudioResampleCVT(cvt, dst_channels, src_rate, dst_rate) ==
   1104        -1) {
   1105        return -1;              /* shouldn't happen, but just in case... */
   1106    }
   1107
   1108    /* Set up the filter information */
   1109    if (cvt->filter_index != 0) {
   1110        cvt->needed = 1;
   1111        cvt->src_format = src_fmt;
   1112        cvt->dst_format = dst_fmt;
   1113        cvt->len = 0;
   1114        cvt->buf = NULL;
   1115        cvt->filters[cvt->filter_index] = NULL;
   1116    }
   1117    return (cvt->needed);
   1118}
   1119
   1120
   1121/* vi: set ts=4 sw=4 expandtab: */