src/audio/SDL_audiocvt.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 10 Jul 2006 21:04:37 +0000
changeset 1895 c121d94672cb
parent 1769 290b5baf2fca
child 1982 3b4ce57c6215
permissions -rw-r--r--
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
/* Functions for audio drivers to perform runtime conversion of audio format */
slouken@0
    25
slouken@0
    26
#include "SDL_audio.h"
slouken@0
    27
slouken@0
    28
slouken@0
    29
/* Effectively mix right and left channels into a single channel */
slouken@1895
    30
void SDLCALL
slouken@1895
    31
SDL_ConvertMono(SDL_AudioCVT * cvt, Uint16 format)
slouken@0
    32
{
slouken@1895
    33
    int i;
slouken@1895
    34
    Sint32 sample;
slouken@0
    35
slouken@0
    36
#ifdef DEBUG_CONVERT
slouken@1895
    37
    fprintf(stderr, "Converting to mono\n");
slouken@0
    38
#endif
slouken@1895
    39
    switch (format & 0x8018) {
slouken@0
    40
slouken@1895
    41
    case AUDIO_U8:
slouken@1895
    42
        {
slouken@1895
    43
            Uint8 *src, *dst;
slouken@0
    44
slouken@1895
    45
            src = cvt->buf;
slouken@1895
    46
            dst = cvt->buf;
slouken@1895
    47
            for (i = cvt->len_cvt / 2; i; --i) {
slouken@1895
    48
                sample = src[0] + src[1];
slouken@1895
    49
                if (sample > 255) {
slouken@1895
    50
                    *dst = 255;
slouken@1895
    51
                } else {
slouken@1895
    52
                    *dst = (Uint8) sample;
slouken@1895
    53
                }
slouken@1895
    54
                src += 2;
slouken@1895
    55
                dst += 1;
slouken@1895
    56
            }
slouken@1895
    57
        }
slouken@1895
    58
        break;
slouken@0
    59
slouken@1895
    60
    case AUDIO_S8:
slouken@1895
    61
        {
slouken@1895
    62
            Sint8 *src, *dst;
slouken@0
    63
slouken@1895
    64
            src = (Sint8 *) cvt->buf;
slouken@1895
    65
            dst = (Sint8 *) cvt->buf;
slouken@1895
    66
            for (i = cvt->len_cvt / 2; i; --i) {
slouken@1895
    67
                sample = src[0] + src[1];
slouken@1895
    68
                if (sample > 127) {
slouken@1895
    69
                    *dst = 127;
slouken@1895
    70
                } else if (sample < -128) {
slouken@1895
    71
                    *dst = -128;
slouken@1895
    72
                } else {
slouken@1895
    73
                    *dst = (Sint8) sample;
slouken@1895
    74
                }
slouken@1895
    75
                src += 2;
slouken@1895
    76
                dst += 1;
slouken@1895
    77
            }
slouken@1895
    78
        }
slouken@1895
    79
        break;
slouken@0
    80
slouken@1895
    81
    case AUDIO_U16:
slouken@1895
    82
        {
slouken@1895
    83
            Uint8 *src, *dst;
slouken@0
    84
slouken@1895
    85
            src = cvt->buf;
slouken@1895
    86
            dst = cvt->buf;
slouken@1895
    87
            if ((format & 0x1000) == 0x1000) {
slouken@1895
    88
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
    89
                    sample = (Uint16) ((src[0] << 8) | src[1]) +
slouken@1895
    90
                        (Uint16) ((src[2] << 8) | src[3]);
slouken@1895
    91
                    if (sample > 65535) {
slouken@1895
    92
                        dst[0] = 0xFF;
slouken@1895
    93
                        dst[1] = 0xFF;
slouken@1895
    94
                    } else {
slouken@1895
    95
                        dst[1] = (sample & 0xFF);
slouken@1895
    96
                        sample >>= 8;
slouken@1895
    97
                        dst[0] = (sample & 0xFF);
slouken@1895
    98
                    }
slouken@1895
    99
                    src += 4;
slouken@1895
   100
                    dst += 2;
slouken@1895
   101
                }
slouken@1895
   102
            } else {
slouken@1895
   103
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   104
                    sample = (Uint16) ((src[1] << 8) | src[0]) +
slouken@1895
   105
                        (Uint16) ((src[3] << 8) | src[2]);
slouken@1895
   106
                    if (sample > 65535) {
slouken@1895
   107
                        dst[0] = 0xFF;
slouken@1895
   108
                        dst[1] = 0xFF;
slouken@1895
   109
                    } else {
slouken@1895
   110
                        dst[0] = (sample & 0xFF);
slouken@1895
   111
                        sample >>= 8;
slouken@1895
   112
                        dst[1] = (sample & 0xFF);
slouken@1895
   113
                    }
slouken@1895
   114
                    src += 4;
slouken@1895
   115
                    dst += 2;
slouken@1895
   116
                }
slouken@1895
   117
            }
slouken@1895
   118
        }
slouken@1895
   119
        break;
slouken@0
   120
slouken@1895
   121
    case AUDIO_S16:
slouken@1895
   122
        {
slouken@1895
   123
            Uint8 *src, *dst;
slouken@0
   124
slouken@1895
   125
            src = cvt->buf;
slouken@1895
   126
            dst = cvt->buf;
slouken@1895
   127
            if ((format & 0x1000) == 0x1000) {
slouken@1895
   128
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   129
                    sample = (Sint16) ((src[0] << 8) | src[1]) +
slouken@1895
   130
                        (Sint16) ((src[2] << 8) | src[3]);
slouken@1895
   131
                    if (sample > 32767) {
slouken@1895
   132
                        dst[0] = 0x7F;
slouken@1895
   133
                        dst[1] = 0xFF;
slouken@1895
   134
                    } else if (sample < -32768) {
slouken@1895
   135
                        dst[0] = 0x80;
slouken@1895
   136
                        dst[1] = 0x00;
slouken@1895
   137
                    } else {
slouken@1895
   138
                        dst[1] = (sample & 0xFF);
slouken@1895
   139
                        sample >>= 8;
slouken@1895
   140
                        dst[0] = (sample & 0xFF);
slouken@1895
   141
                    }
slouken@1895
   142
                    src += 4;
slouken@1895
   143
                    dst += 2;
slouken@1895
   144
                }
slouken@1895
   145
            } else {
slouken@1895
   146
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   147
                    sample = (Sint16) ((src[1] << 8) | src[0]) +
slouken@1895
   148
                        (Sint16) ((src[3] << 8) | src[2]);
slouken@1895
   149
                    if (sample > 32767) {
slouken@1895
   150
                        dst[1] = 0x7F;
slouken@1895
   151
                        dst[0] = 0xFF;
slouken@1895
   152
                    } else if (sample < -32768) {
slouken@1895
   153
                        dst[1] = 0x80;
slouken@1895
   154
                        dst[0] = 0x00;
slouken@1895
   155
                    } else {
slouken@1895
   156
                        dst[0] = (sample & 0xFF);
slouken@1895
   157
                        sample >>= 8;
slouken@1895
   158
                        dst[1] = (sample & 0xFF);
slouken@1895
   159
                    }
slouken@1895
   160
                    src += 4;
slouken@1895
   161
                    dst += 2;
slouken@1895
   162
                }
slouken@1895
   163
            }
slouken@1895
   164
        }
slouken@1895
   165
        break;
slouken@1895
   166
    }
slouken@1895
   167
    cvt->len_cvt /= 2;
slouken@1895
   168
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   169
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   170
    }
slouken@0
   171
}
slouken@0
   172
slouken@942
   173
/* Discard top 4 channels */
slouken@1895
   174
void SDLCALL
slouken@1895
   175
SDL_ConvertStrip(SDL_AudioCVT * cvt, Uint16 format)
slouken@942
   176
{
slouken@1895
   177
    int i;
slouken@1895
   178
    Sint32 lsample, rsample;
slouken@942
   179
slouken@942
   180
#ifdef DEBUG_CONVERT
slouken@1895
   181
    fprintf(stderr, "Converting down to stereo\n");
slouken@942
   182
#endif
slouken@1895
   183
    switch (format & 0x8018) {
slouken@942
   184
slouken@1895
   185
    case AUDIO_U8:
slouken@1895
   186
        {
slouken@1895
   187
            Uint8 *src, *dst;
slouken@942
   188
slouken@1895
   189
            src = cvt->buf;
slouken@1895
   190
            dst = cvt->buf;
slouken@1895
   191
            for (i = cvt->len_cvt / 6; i; --i) {
slouken@1895
   192
                dst[0] = src[0];
slouken@1895
   193
                dst[1] = src[1];
slouken@1895
   194
                src += 6;
slouken@1895
   195
                dst += 2;
slouken@1895
   196
            }
slouken@1895
   197
        }
slouken@1895
   198
        break;
slouken@942
   199
slouken@1895
   200
    case AUDIO_S8:
slouken@1895
   201
        {
slouken@1895
   202
            Sint8 *src, *dst;
slouken@942
   203
slouken@1895
   204
            src = (Sint8 *) cvt->buf;
slouken@1895
   205
            dst = (Sint8 *) cvt->buf;
slouken@1895
   206
            for (i = cvt->len_cvt / 6; i; --i) {
slouken@1895
   207
                dst[0] = src[0];
slouken@1895
   208
                dst[1] = src[1];
slouken@1895
   209
                src += 6;
slouken@1895
   210
                dst += 2;
slouken@1895
   211
            }
slouken@1895
   212
        }
slouken@1895
   213
        break;
slouken@942
   214
slouken@1895
   215
    case AUDIO_U16:
slouken@1895
   216
        {
slouken@1895
   217
            Uint8 *src, *dst;
slouken@942
   218
slouken@1895
   219
            src = cvt->buf;
slouken@1895
   220
            dst = cvt->buf;
slouken@1895
   221
            if ((format & 0x1000) == 0x1000) {
slouken@1895
   222
                for (i = cvt->len_cvt / 12; i; --i) {
slouken@1895
   223
                    lsample = (Uint16) ((src[0] << 8) | src[1]);
slouken@1895
   224
                    rsample = (Uint16) ((src[2] << 8) | src[3]);
slouken@1895
   225
                    dst[1] = (lsample & 0xFF);
slouken@1895
   226
                    lsample >>= 8;
slouken@1895
   227
                    dst[0] = (lsample & 0xFF);
slouken@1895
   228
                    dst[3] = (rsample & 0xFF);
slouken@1895
   229
                    rsample >>= 8;
slouken@1895
   230
                    dst[2] = (rsample & 0xFF);
slouken@1895
   231
                    src += 12;
slouken@1895
   232
                    dst += 4;
slouken@1895
   233
                }
slouken@1895
   234
            } else {
slouken@1895
   235
                for (i = cvt->len_cvt / 12; i; --i) {
slouken@1895
   236
                    lsample = (Uint16) ((src[1] << 8) | src[0]);
slouken@1895
   237
                    rsample = (Uint16) ((src[3] << 8) | src[2]);
slouken@1895
   238
                    dst[0] = (lsample & 0xFF);
slouken@1895
   239
                    lsample >>= 8;
slouken@1895
   240
                    dst[1] = (lsample & 0xFF);
slouken@1895
   241
                    dst[2] = (rsample & 0xFF);
slouken@1895
   242
                    rsample >>= 8;
slouken@1895
   243
                    dst[3] = (rsample & 0xFF);
slouken@1895
   244
                    src += 12;
slouken@1895
   245
                    dst += 4;
slouken@1895
   246
                }
slouken@1895
   247
            }
slouken@1895
   248
        }
slouken@1895
   249
        break;
slouken@942
   250
slouken@1895
   251
    case AUDIO_S16:
slouken@1895
   252
        {
slouken@1895
   253
            Uint8 *src, *dst;
slouken@942
   254
slouken@1895
   255
            src = cvt->buf;
slouken@1895
   256
            dst = cvt->buf;
slouken@1895
   257
            if ((format & 0x1000) == 0x1000) {
slouken@1895
   258
                for (i = cvt->len_cvt / 12; i; --i) {
slouken@1895
   259
                    lsample = (Sint16) ((src[0] << 8) | src[1]);
slouken@1895
   260
                    rsample = (Sint16) ((src[2] << 8) | src[3]);
slouken@1895
   261
                    dst[1] = (lsample & 0xFF);
slouken@1895
   262
                    lsample >>= 8;
slouken@1895
   263
                    dst[0] = (lsample & 0xFF);
slouken@1895
   264
                    dst[3] = (rsample & 0xFF);
slouken@1895
   265
                    rsample >>= 8;
slouken@1895
   266
                    dst[2] = (rsample & 0xFF);
slouken@1895
   267
                    src += 12;
slouken@1895
   268
                    dst += 4;
slouken@1895
   269
                }
slouken@1895
   270
            } else {
slouken@1895
   271
                for (i = cvt->len_cvt / 12; i; --i) {
slouken@1895
   272
                    lsample = (Sint16) ((src[1] << 8) | src[0]);
slouken@1895
   273
                    rsample = (Sint16) ((src[3] << 8) | src[2]);
slouken@1895
   274
                    dst[0] = (lsample & 0xFF);
slouken@1895
   275
                    lsample >>= 8;
slouken@1895
   276
                    dst[1] = (lsample & 0xFF);
slouken@1895
   277
                    dst[2] = (rsample & 0xFF);
slouken@1895
   278
                    rsample >>= 8;
slouken@1895
   279
                    dst[3] = (rsample & 0xFF);
slouken@1895
   280
                    src += 12;
slouken@1895
   281
                    dst += 4;
slouken@1895
   282
                }
slouken@1895
   283
            }
slouken@1895
   284
        }
slouken@1895
   285
        break;
slouken@1895
   286
    }
slouken@1895
   287
    cvt->len_cvt /= 3;
slouken@1895
   288
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   289
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   290
    }
slouken@942
   291
}
slouken@942
   292
slouken@942
   293
slouken@942
   294
/* Discard top 2 channels of 6 */
slouken@1895
   295
void SDLCALL
slouken@1895
   296
SDL_ConvertStrip_2(SDL_AudioCVT * cvt, Uint16 format)
slouken@942
   297
{
slouken@1895
   298
    int i;
slouken@1895
   299
    Sint32 lsample, rsample;
slouken@942
   300
slouken@942
   301
#ifdef DEBUG_CONVERT
slouken@1895
   302
    fprintf(stderr, "Converting 6 down to quad\n");
slouken@942
   303
#endif
slouken@1895
   304
    switch (format & 0x8018) {
slouken@942
   305
slouken@1895
   306
    case AUDIO_U8:
slouken@1895
   307
        {
slouken@1895
   308
            Uint8 *src, *dst;
slouken@942
   309
slouken@1895
   310
            src = cvt->buf;
slouken@1895
   311
            dst = cvt->buf;
slouken@1895
   312
            for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   313
                dst[0] = src[0];
slouken@1895
   314
                dst[1] = src[1];
slouken@1895
   315
                src += 4;
slouken@1895
   316
                dst += 2;
slouken@1895
   317
            }
slouken@1895
   318
        }
slouken@1895
   319
        break;
slouken@942
   320
slouken@1895
   321
    case AUDIO_S8:
slouken@1895
   322
        {
slouken@1895
   323
            Sint8 *src, *dst;
slouken@942
   324
slouken@1895
   325
            src = (Sint8 *) cvt->buf;
slouken@1895
   326
            dst = (Sint8 *) cvt->buf;
slouken@1895
   327
            for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   328
                dst[0] = src[0];
slouken@1895
   329
                dst[1] = src[1];
slouken@1895
   330
                src += 4;
slouken@1895
   331
                dst += 2;
slouken@1895
   332
            }
slouken@1895
   333
        }
slouken@1895
   334
        break;
slouken@942
   335
slouken@1895
   336
    case AUDIO_U16:
slouken@1895
   337
        {
slouken@1895
   338
            Uint8 *src, *dst;
slouken@942
   339
slouken@1895
   340
            src = cvt->buf;
slouken@1895
   341
            dst = cvt->buf;
slouken@1895
   342
            if ((format & 0x1000) == 0x1000) {
slouken@1895
   343
                for (i = cvt->len_cvt / 8; i; --i) {
slouken@1895
   344
                    lsample = (Uint16) ((src[0] << 8) | src[1]);
slouken@1895
   345
                    rsample = (Uint16) ((src[2] << 8) | src[3]);
slouken@1895
   346
                    dst[1] = (lsample & 0xFF);
slouken@1895
   347
                    lsample >>= 8;
slouken@1895
   348
                    dst[0] = (lsample & 0xFF);
slouken@1895
   349
                    dst[3] = (rsample & 0xFF);
slouken@1895
   350
                    rsample >>= 8;
slouken@1895
   351
                    dst[2] = (rsample & 0xFF);
slouken@1895
   352
                    src += 8;
slouken@1895
   353
                    dst += 4;
slouken@1895
   354
                }
slouken@1895
   355
            } else {
slouken@1895
   356
                for (i = cvt->len_cvt / 8; i; --i) {
slouken@1895
   357
                    lsample = (Uint16) ((src[1] << 8) | src[0]);
slouken@1895
   358
                    rsample = (Uint16) ((src[3] << 8) | src[2]);
slouken@1895
   359
                    dst[0] = (lsample & 0xFF);
slouken@1895
   360
                    lsample >>= 8;
slouken@1895
   361
                    dst[1] = (lsample & 0xFF);
slouken@1895
   362
                    dst[2] = (rsample & 0xFF);
slouken@1895
   363
                    rsample >>= 8;
slouken@1895
   364
                    dst[3] = (rsample & 0xFF);
slouken@1895
   365
                    src += 8;
slouken@1895
   366
                    dst += 4;
slouken@1895
   367
                }
slouken@1895
   368
            }
slouken@1895
   369
        }
slouken@1895
   370
        break;
slouken@942
   371
slouken@1895
   372
    case AUDIO_S16:
slouken@1895
   373
        {
slouken@1895
   374
            Uint8 *src, *dst;
slouken@942
   375
slouken@1895
   376
            src = cvt->buf;
slouken@1895
   377
            dst = cvt->buf;
slouken@1895
   378
            if ((format & 0x1000) == 0x1000) {
slouken@1895
   379
                for (i = cvt->len_cvt / 8; i; --i) {
slouken@1895
   380
                    lsample = (Sint16) ((src[0] << 8) | src[1]);
slouken@1895
   381
                    rsample = (Sint16) ((src[2] << 8) | src[3]);
slouken@1895
   382
                    dst[1] = (lsample & 0xFF);
slouken@1895
   383
                    lsample >>= 8;
slouken@1895
   384
                    dst[0] = (lsample & 0xFF);
slouken@1895
   385
                    dst[3] = (rsample & 0xFF);
slouken@1895
   386
                    rsample >>= 8;
slouken@1895
   387
                    dst[2] = (rsample & 0xFF);
slouken@1895
   388
                    src += 8;
slouken@1895
   389
                    dst += 4;
slouken@1895
   390
                }
slouken@1895
   391
            } else {
slouken@1895
   392
                for (i = cvt->len_cvt / 8; i; --i) {
slouken@1895
   393
                    lsample = (Sint16) ((src[1] << 8) | src[0]);
slouken@1895
   394
                    rsample = (Sint16) ((src[3] << 8) | src[2]);
slouken@1895
   395
                    dst[0] = (lsample & 0xFF);
slouken@1895
   396
                    lsample >>= 8;
slouken@1895
   397
                    dst[1] = (lsample & 0xFF);
slouken@1895
   398
                    dst[2] = (rsample & 0xFF);
slouken@1895
   399
                    rsample >>= 8;
slouken@1895
   400
                    dst[3] = (rsample & 0xFF);
slouken@1895
   401
                    src += 8;
slouken@1895
   402
                    dst += 4;
slouken@1895
   403
                }
slouken@1895
   404
            }
slouken@1895
   405
        }
slouken@1895
   406
        break;
slouken@1895
   407
    }
slouken@1895
   408
    cvt->len_cvt /= 2;
slouken@1895
   409
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   410
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   411
    }
slouken@942
   412
}
slouken@0
   413
slouken@0
   414
/* Duplicate a mono channel to both stereo channels */
slouken@1895
   415
void SDLCALL
slouken@1895
   416
SDL_ConvertStereo(SDL_AudioCVT * cvt, Uint16 format)
slouken@0
   417
{
slouken@1895
   418
    int i;
slouken@0
   419
slouken@0
   420
#ifdef DEBUG_CONVERT
slouken@1895
   421
    fprintf(stderr, "Converting to stereo\n");
slouken@0
   422
#endif
slouken@1895
   423
    if ((format & 0xFF) == 16) {
slouken@1895
   424
        Uint16 *src, *dst;
slouken@0
   425
slouken@1895
   426
        src = (Uint16 *) (cvt->buf + cvt->len_cvt);
slouken@1895
   427
        dst = (Uint16 *) (cvt->buf + cvt->len_cvt * 2);
slouken@1895
   428
        for (i = cvt->len_cvt / 2; i; --i) {
slouken@1895
   429
            dst -= 2;
slouken@1895
   430
            src -= 1;
slouken@1895
   431
            dst[0] = src[0];
slouken@1895
   432
            dst[1] = src[0];
slouken@1895
   433
        }
slouken@1895
   434
    } else {
slouken@1895
   435
        Uint8 *src, *dst;
slouken@0
   436
slouken@1895
   437
        src = cvt->buf + cvt->len_cvt;
slouken@1895
   438
        dst = cvt->buf + cvt->len_cvt * 2;
slouken@1895
   439
        for (i = cvt->len_cvt; i; --i) {
slouken@1895
   440
            dst -= 2;
slouken@1895
   441
            src -= 1;
slouken@1895
   442
            dst[0] = src[0];
slouken@1895
   443
            dst[1] = src[0];
slouken@1895
   444
        }
slouken@1895
   445
    }
slouken@1895
   446
    cvt->len_cvt *= 2;
slouken@1895
   447
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   448
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   449
    }
slouken@0
   450
}
slouken@0
   451
slouken@942
   452
slouken@942
   453
/* Duplicate a stereo channel to a pseudo-5.1 stream */
slouken@1895
   454
void SDLCALL
slouken@1895
   455
SDL_ConvertSurround(SDL_AudioCVT * cvt, Uint16 format)
slouken@942
   456
{
slouken@1895
   457
    int i;
slouken@942
   458
slouken@942
   459
#ifdef DEBUG_CONVERT
slouken@1895
   460
    fprintf(stderr, "Converting stereo to surround\n");
slouken@942
   461
#endif
slouken@1895
   462
    switch (format & 0x8018) {
slouken@942
   463
slouken@1895
   464
    case AUDIO_U8:
slouken@1895
   465
        {
slouken@1895
   466
            Uint8 *src, *dst, lf, rf, ce;
slouken@942
   467
slouken@1895
   468
            src = (Uint8 *) (cvt->buf + cvt->len_cvt);
slouken@1895
   469
            dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 3);
slouken@1895
   470
            for (i = cvt->len_cvt; i; --i) {
slouken@1895
   471
                dst -= 6;
slouken@1895
   472
                src -= 2;
slouken@1895
   473
                lf = src[0];
slouken@1895
   474
                rf = src[1];
slouken@1895
   475
                ce = (lf / 2) + (rf / 2);
slouken@1895
   476
                dst[0] = lf;
slouken@1895
   477
                dst[1] = rf;
slouken@1895
   478
                dst[2] = lf - ce;
slouken@1895
   479
                dst[3] = rf - ce;
slouken@1895
   480
                dst[4] = ce;
slouken@1895
   481
                dst[5] = ce;
slouken@1895
   482
            }
slouken@1895
   483
        }
slouken@1895
   484
        break;
slouken@942
   485
slouken@1895
   486
    case AUDIO_S8:
slouken@1895
   487
        {
slouken@1895
   488
            Sint8 *src, *dst, lf, rf, ce;
slouken@942
   489
slouken@1895
   490
            src = (Sint8 *) cvt->buf + cvt->len_cvt;
slouken@1895
   491
            dst = (Sint8 *) cvt->buf + cvt->len_cvt * 3;
slouken@1895
   492
            for (i = cvt->len_cvt; i; --i) {
slouken@1895
   493
                dst -= 6;
slouken@1895
   494
                src -= 2;
slouken@1895
   495
                lf = src[0];
slouken@1895
   496
                rf = src[1];
slouken@1895
   497
                ce = (lf / 2) + (rf / 2);
slouken@1895
   498
                dst[0] = lf;
slouken@1895
   499
                dst[1] = rf;
slouken@1895
   500
                dst[2] = lf - ce;
slouken@1895
   501
                dst[3] = rf - ce;
slouken@1895
   502
                dst[4] = ce;
slouken@1895
   503
                dst[5] = ce;
slouken@1895
   504
            }
slouken@1895
   505
        }
slouken@1895
   506
        break;
slouken@942
   507
slouken@1895
   508
    case AUDIO_U16:
slouken@1895
   509
        {
slouken@1895
   510
            Uint8 *src, *dst;
slouken@1895
   511
            Uint16 lf, rf, ce, lr, rr;
slouken@942
   512
slouken@1895
   513
            src = cvt->buf + cvt->len_cvt;
slouken@1895
   514
            dst = cvt->buf + cvt->len_cvt * 3;
slouken@942
   515
slouken@1895
   516
            if ((format & 0x1000) == 0x1000) {
slouken@1895
   517
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   518
                    dst -= 12;
slouken@1895
   519
                    src -= 4;
slouken@1895
   520
                    lf = (Uint16) ((src[0] << 8) | src[1]);
slouken@1895
   521
                    rf = (Uint16) ((src[2] << 8) | src[3]);
slouken@1895
   522
                    ce = (lf / 2) + (rf / 2);
slouken@1895
   523
                    rr = lf - ce;
slouken@1895
   524
                    lr = rf - ce;
slouken@1895
   525
                    dst[1] = (lf & 0xFF);
slouken@1895
   526
                    dst[0] = ((lf >> 8) & 0xFF);
slouken@1895
   527
                    dst[3] = (rf & 0xFF);
slouken@1895
   528
                    dst[2] = ((rf >> 8) & 0xFF);
slouken@942
   529
slouken@1895
   530
                    dst[1 + 4] = (lr & 0xFF);
slouken@1895
   531
                    dst[0 + 4] = ((lr >> 8) & 0xFF);
slouken@1895
   532
                    dst[3 + 4] = (rr & 0xFF);
slouken@1895
   533
                    dst[2 + 4] = ((rr >> 8) & 0xFF);
slouken@942
   534
slouken@1895
   535
                    dst[1 + 8] = (ce & 0xFF);
slouken@1895
   536
                    dst[0 + 8] = ((ce >> 8) & 0xFF);
slouken@1895
   537
                    dst[3 + 8] = (ce & 0xFF);
slouken@1895
   538
                    dst[2 + 8] = ((ce >> 8) & 0xFF);
slouken@1895
   539
                }
slouken@1895
   540
            } else {
slouken@1895
   541
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   542
                    dst -= 12;
slouken@1895
   543
                    src -= 4;
slouken@1895
   544
                    lf = (Uint16) ((src[1] << 8) | src[0]);
slouken@1895
   545
                    rf = (Uint16) ((src[3] << 8) | src[2]);
slouken@1895
   546
                    ce = (lf / 2) + (rf / 2);
slouken@1895
   547
                    rr = lf - ce;
slouken@1895
   548
                    lr = rf - ce;
slouken@1895
   549
                    dst[0] = (lf & 0xFF);
slouken@1895
   550
                    dst[1] = ((lf >> 8) & 0xFF);
slouken@1895
   551
                    dst[2] = (rf & 0xFF);
slouken@1895
   552
                    dst[3] = ((rf >> 8) & 0xFF);
slouken@942
   553
slouken@1895
   554
                    dst[0 + 4] = (lr & 0xFF);
slouken@1895
   555
                    dst[1 + 4] = ((lr >> 8) & 0xFF);
slouken@1895
   556
                    dst[2 + 4] = (rr & 0xFF);
slouken@1895
   557
                    dst[3 + 4] = ((rr >> 8) & 0xFF);
slouken@942
   558
slouken@1895
   559
                    dst[0 + 8] = (ce & 0xFF);
slouken@1895
   560
                    dst[1 + 8] = ((ce >> 8) & 0xFF);
slouken@1895
   561
                    dst[2 + 8] = (ce & 0xFF);
slouken@1895
   562
                    dst[3 + 8] = ((ce >> 8) & 0xFF);
slouken@1895
   563
                }
slouken@1895
   564
            }
slouken@1895
   565
        }
slouken@1895
   566
        break;
slouken@942
   567
slouken@1895
   568
    case AUDIO_S16:
slouken@1895
   569
        {
slouken@1895
   570
            Uint8 *src, *dst;
slouken@1895
   571
            Sint16 lf, rf, ce, lr, rr;
slouken@942
   572
slouken@1895
   573
            src = cvt->buf + cvt->len_cvt;
slouken@1895
   574
            dst = cvt->buf + cvt->len_cvt * 3;
slouken@942
   575
slouken@1895
   576
            if ((format & 0x1000) == 0x1000) {
slouken@1895
   577
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   578
                    dst -= 12;
slouken@1895
   579
                    src -= 4;
slouken@1895
   580
                    lf = (Sint16) ((src[0] << 8) | src[1]);
slouken@1895
   581
                    rf = (Sint16) ((src[2] << 8) | src[3]);
slouken@1895
   582
                    ce = (lf / 2) + (rf / 2);
slouken@1895
   583
                    rr = lf - ce;
slouken@1895
   584
                    lr = rf - ce;
slouken@1895
   585
                    dst[1] = (lf & 0xFF);
slouken@1895
   586
                    dst[0] = ((lf >> 8) & 0xFF);
slouken@1895
   587
                    dst[3] = (rf & 0xFF);
slouken@1895
   588
                    dst[2] = ((rf >> 8) & 0xFF);
slouken@942
   589
slouken@1895
   590
                    dst[1 + 4] = (lr & 0xFF);
slouken@1895
   591
                    dst[0 + 4] = ((lr >> 8) & 0xFF);
slouken@1895
   592
                    dst[3 + 4] = (rr & 0xFF);
slouken@1895
   593
                    dst[2 + 4] = ((rr >> 8) & 0xFF);
slouken@942
   594
slouken@1895
   595
                    dst[1 + 8] = (ce & 0xFF);
slouken@1895
   596
                    dst[0 + 8] = ((ce >> 8) & 0xFF);
slouken@1895
   597
                    dst[3 + 8] = (ce & 0xFF);
slouken@1895
   598
                    dst[2 + 8] = ((ce >> 8) & 0xFF);
slouken@1895
   599
                }
slouken@1895
   600
            } else {
slouken@1895
   601
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   602
                    dst -= 12;
slouken@1895
   603
                    src -= 4;
slouken@1895
   604
                    lf = (Sint16) ((src[1] << 8) | src[0]);
slouken@1895
   605
                    rf = (Sint16) ((src[3] << 8) | src[2]);
slouken@1895
   606
                    ce = (lf / 2) + (rf / 2);
slouken@1895
   607
                    rr = lf - ce;
slouken@1895
   608
                    lr = rf - ce;
slouken@1895
   609
                    dst[0] = (lf & 0xFF);
slouken@1895
   610
                    dst[1] = ((lf >> 8) & 0xFF);
slouken@1895
   611
                    dst[2] = (rf & 0xFF);
slouken@1895
   612
                    dst[3] = ((rf >> 8) & 0xFF);
slouken@942
   613
slouken@1895
   614
                    dst[0 + 4] = (lr & 0xFF);
slouken@1895
   615
                    dst[1 + 4] = ((lr >> 8) & 0xFF);
slouken@1895
   616
                    dst[2 + 4] = (rr & 0xFF);
slouken@1895
   617
                    dst[3 + 4] = ((rr >> 8) & 0xFF);
slouken@942
   618
slouken@1895
   619
                    dst[0 + 8] = (ce & 0xFF);
slouken@1895
   620
                    dst[1 + 8] = ((ce >> 8) & 0xFF);
slouken@1895
   621
                    dst[2 + 8] = (ce & 0xFF);
slouken@1895
   622
                    dst[3 + 8] = ((ce >> 8) & 0xFF);
slouken@1895
   623
                }
slouken@1895
   624
            }
slouken@1895
   625
        }
slouken@1895
   626
        break;
slouken@1895
   627
    }
slouken@1895
   628
    cvt->len_cvt *= 3;
slouken@1895
   629
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   630
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   631
    }
slouken@942
   632
}
slouken@942
   633
slouken@942
   634
slouken@942
   635
/* Duplicate a stereo channel to a pseudo-4.0 stream */
slouken@1895
   636
void SDLCALL
slouken@1895
   637
SDL_ConvertSurround_4(SDL_AudioCVT * cvt, Uint16 format)
slouken@942
   638
{
slouken@1895
   639
    int i;
slouken@942
   640
slouken@942
   641
#ifdef DEBUG_CONVERT
slouken@1895
   642
    fprintf(stderr, "Converting stereo to quad\n");
slouken@942
   643
#endif
slouken@1895
   644
    switch (format & 0x8018) {
slouken@942
   645
slouken@1895
   646
    case AUDIO_U8:
slouken@1895
   647
        {
slouken@1895
   648
            Uint8 *src, *dst, lf, rf, ce;
slouken@942
   649
slouken@1895
   650
            src = (Uint8 *) (cvt->buf + cvt->len_cvt);
slouken@1895
   651
            dst = (Uint8 *) (cvt->buf + cvt->len_cvt * 2);
slouken@1895
   652
            for (i = cvt->len_cvt; i; --i) {
slouken@1895
   653
                dst -= 4;
slouken@1895
   654
                src -= 2;
slouken@1895
   655
                lf = src[0];
slouken@1895
   656
                rf = src[1];
slouken@1895
   657
                ce = (lf / 2) + (rf / 2);
slouken@1895
   658
                dst[0] = lf;
slouken@1895
   659
                dst[1] = rf;
slouken@1895
   660
                dst[2] = lf - ce;
slouken@1895
   661
                dst[3] = rf - ce;
slouken@1895
   662
            }
slouken@1895
   663
        }
slouken@1895
   664
        break;
slouken@942
   665
slouken@1895
   666
    case AUDIO_S8:
slouken@1895
   667
        {
slouken@1895
   668
            Sint8 *src, *dst, lf, rf, ce;
slouken@942
   669
slouken@1895
   670
            src = (Sint8 *) cvt->buf + cvt->len_cvt;
slouken@1895
   671
            dst = (Sint8 *) cvt->buf + cvt->len_cvt * 2;
slouken@1895
   672
            for (i = cvt->len_cvt; i; --i) {
slouken@1895
   673
                dst -= 4;
slouken@1895
   674
                src -= 2;
slouken@1895
   675
                lf = src[0];
slouken@1895
   676
                rf = src[1];
slouken@1895
   677
                ce = (lf / 2) + (rf / 2);
slouken@1895
   678
                dst[0] = lf;
slouken@1895
   679
                dst[1] = rf;
slouken@1895
   680
                dst[2] = lf - ce;
slouken@1895
   681
                dst[3] = rf - ce;
slouken@1895
   682
            }
slouken@1895
   683
        }
slouken@1895
   684
        break;
slouken@942
   685
slouken@1895
   686
    case AUDIO_U16:
slouken@1895
   687
        {
slouken@1895
   688
            Uint8 *src, *dst;
slouken@1895
   689
            Uint16 lf, rf, ce, lr, rr;
slouken@942
   690
slouken@1895
   691
            src = cvt->buf + cvt->len_cvt;
slouken@1895
   692
            dst = cvt->buf + cvt->len_cvt * 2;
slouken@942
   693
slouken@1895
   694
            if ((format & 0x1000) == 0x1000) {
slouken@1895
   695
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   696
                    dst -= 8;
slouken@1895
   697
                    src -= 4;
slouken@1895
   698
                    lf = (Uint16) ((src[0] << 8) | src[1]);
slouken@1895
   699
                    rf = (Uint16) ((src[2] << 8) | src[3]);
slouken@1895
   700
                    ce = (lf / 2) + (rf / 2);
slouken@1895
   701
                    rr = lf - ce;
slouken@1895
   702
                    lr = rf - ce;
slouken@1895
   703
                    dst[1] = (lf & 0xFF);
slouken@1895
   704
                    dst[0] = ((lf >> 8) & 0xFF);
slouken@1895
   705
                    dst[3] = (rf & 0xFF);
slouken@1895
   706
                    dst[2] = ((rf >> 8) & 0xFF);
slouken@942
   707
slouken@1895
   708
                    dst[1 + 4] = (lr & 0xFF);
slouken@1895
   709
                    dst[0 + 4] = ((lr >> 8) & 0xFF);
slouken@1895
   710
                    dst[3 + 4] = (rr & 0xFF);
slouken@1895
   711
                    dst[2 + 4] = ((rr >> 8) & 0xFF);
slouken@1895
   712
                }
slouken@1895
   713
            } else {
slouken@1895
   714
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   715
                    dst -= 8;
slouken@1895
   716
                    src -= 4;
slouken@1895
   717
                    lf = (Uint16) ((src[1] << 8) | src[0]);
slouken@1895
   718
                    rf = (Uint16) ((src[3] << 8) | src[2]);
slouken@1895
   719
                    ce = (lf / 2) + (rf / 2);
slouken@1895
   720
                    rr = lf - ce;
slouken@1895
   721
                    lr = rf - ce;
slouken@1895
   722
                    dst[0] = (lf & 0xFF);
slouken@1895
   723
                    dst[1] = ((lf >> 8) & 0xFF);
slouken@1895
   724
                    dst[2] = (rf & 0xFF);
slouken@1895
   725
                    dst[3] = ((rf >> 8) & 0xFF);
slouken@942
   726
slouken@1895
   727
                    dst[0 + 4] = (lr & 0xFF);
slouken@1895
   728
                    dst[1 + 4] = ((lr >> 8) & 0xFF);
slouken@1895
   729
                    dst[2 + 4] = (rr & 0xFF);
slouken@1895
   730
                    dst[3 + 4] = ((rr >> 8) & 0xFF);
slouken@1895
   731
                }
slouken@1895
   732
            }
slouken@1895
   733
        }
slouken@1895
   734
        break;
slouken@942
   735
slouken@1895
   736
    case AUDIO_S16:
slouken@1895
   737
        {
slouken@1895
   738
            Uint8 *src, *dst;
slouken@1895
   739
            Sint16 lf, rf, ce, lr, rr;
slouken@942
   740
slouken@1895
   741
            src = cvt->buf + cvt->len_cvt;
slouken@1895
   742
            dst = cvt->buf + cvt->len_cvt * 2;
slouken@942
   743
slouken@1895
   744
            if ((format & 0x1000) == 0x1000) {
slouken@1895
   745
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   746
                    dst -= 8;
slouken@1895
   747
                    src -= 4;
slouken@1895
   748
                    lf = (Sint16) ((src[0] << 8) | src[1]);
slouken@1895
   749
                    rf = (Sint16) ((src[2] << 8) | src[3]);
slouken@1895
   750
                    ce = (lf / 2) + (rf / 2);
slouken@1895
   751
                    rr = lf - ce;
slouken@1895
   752
                    lr = rf - ce;
slouken@1895
   753
                    dst[1] = (lf & 0xFF);
slouken@1895
   754
                    dst[0] = ((lf >> 8) & 0xFF);
slouken@1895
   755
                    dst[3] = (rf & 0xFF);
slouken@1895
   756
                    dst[2] = ((rf >> 8) & 0xFF);
slouken@942
   757
slouken@1895
   758
                    dst[1 + 4] = (lr & 0xFF);
slouken@1895
   759
                    dst[0 + 4] = ((lr >> 8) & 0xFF);
slouken@1895
   760
                    dst[3 + 4] = (rr & 0xFF);
slouken@1895
   761
                    dst[2 + 4] = ((rr >> 8) & 0xFF);
slouken@1895
   762
                }
slouken@1895
   763
            } else {
slouken@1895
   764
                for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   765
                    dst -= 8;
slouken@1895
   766
                    src -= 4;
slouken@1895
   767
                    lf = (Sint16) ((src[1] << 8) | src[0]);
slouken@1895
   768
                    rf = (Sint16) ((src[3] << 8) | src[2]);
slouken@1895
   769
                    ce = (lf / 2) + (rf / 2);
slouken@1895
   770
                    rr = lf - ce;
slouken@1895
   771
                    lr = rf - ce;
slouken@1895
   772
                    dst[0] = (lf & 0xFF);
slouken@1895
   773
                    dst[1] = ((lf >> 8) & 0xFF);
slouken@1895
   774
                    dst[2] = (rf & 0xFF);
slouken@1895
   775
                    dst[3] = ((rf >> 8) & 0xFF);
slouken@942
   776
slouken@1895
   777
                    dst[0 + 4] = (lr & 0xFF);
slouken@1895
   778
                    dst[1 + 4] = ((lr >> 8) & 0xFF);
slouken@1895
   779
                    dst[2 + 4] = (rr & 0xFF);
slouken@1895
   780
                    dst[3 + 4] = ((rr >> 8) & 0xFF);
slouken@1895
   781
                }
slouken@1895
   782
            }
slouken@1895
   783
        }
slouken@1895
   784
        break;
slouken@1895
   785
    }
slouken@1895
   786
    cvt->len_cvt *= 2;
slouken@1895
   787
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   788
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   789
    }
slouken@942
   790
}
slouken@942
   791
slouken@942
   792
slouken@0
   793
/* Convert 8-bit to 16-bit - LSB */
slouken@1895
   794
void SDLCALL
slouken@1895
   795
SDL_Convert16LSB(SDL_AudioCVT * cvt, Uint16 format)
slouken@0
   796
{
slouken@1895
   797
    int i;
slouken@1895
   798
    Uint8 *src, *dst;
slouken@0
   799
slouken@0
   800
#ifdef DEBUG_CONVERT
slouken@1895
   801
    fprintf(stderr, "Converting to 16-bit LSB\n");
slouken@0
   802
#endif
slouken@1895
   803
    src = cvt->buf + cvt->len_cvt;
slouken@1895
   804
    dst = cvt->buf + cvt->len_cvt * 2;
slouken@1895
   805
    for (i = cvt->len_cvt; i; --i) {
slouken@1895
   806
        src -= 1;
slouken@1895
   807
        dst -= 2;
slouken@1895
   808
        dst[1] = *src;
slouken@1895
   809
        dst[0] = 0;
slouken@1895
   810
    }
slouken@1895
   811
    format = ((format & ~0x0008) | AUDIO_U16LSB);
slouken@1895
   812
    cvt->len_cvt *= 2;
slouken@1895
   813
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   814
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   815
    }
slouken@0
   816
}
slouken@1895
   817
slouken@0
   818
/* Convert 8-bit to 16-bit - MSB */
slouken@1895
   819
void SDLCALL
slouken@1895
   820
SDL_Convert16MSB(SDL_AudioCVT * cvt, Uint16 format)
slouken@0
   821
{
slouken@1895
   822
    int i;
slouken@1895
   823
    Uint8 *src, *dst;
slouken@0
   824
slouken@0
   825
#ifdef DEBUG_CONVERT
slouken@1895
   826
    fprintf(stderr, "Converting to 16-bit MSB\n");
slouken@0
   827
#endif
slouken@1895
   828
    src = cvt->buf + cvt->len_cvt;
slouken@1895
   829
    dst = cvt->buf + cvt->len_cvt * 2;
slouken@1895
   830
    for (i = cvt->len_cvt; i; --i) {
slouken@1895
   831
        src -= 1;
slouken@1895
   832
        dst -= 2;
slouken@1895
   833
        dst[0] = *src;
slouken@1895
   834
        dst[1] = 0;
slouken@1895
   835
    }
slouken@1895
   836
    format = ((format & ~0x0008) | AUDIO_U16MSB);
slouken@1895
   837
    cvt->len_cvt *= 2;
slouken@1895
   838
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   839
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   840
    }
slouken@0
   841
}
slouken@0
   842
slouken@0
   843
/* Convert 16-bit to 8-bit */
slouken@1895
   844
void SDLCALL
slouken@1895
   845
SDL_Convert8(SDL_AudioCVT * cvt, Uint16 format)
slouken@0
   846
{
slouken@1895
   847
    int i;
slouken@1895
   848
    Uint8 *src, *dst;
slouken@0
   849
slouken@0
   850
#ifdef DEBUG_CONVERT
slouken@1895
   851
    fprintf(stderr, "Converting to 8-bit\n");
slouken@0
   852
#endif
slouken@1895
   853
    src = cvt->buf;
slouken@1895
   854
    dst = cvt->buf;
slouken@1895
   855
    if ((format & 0x1000) != 0x1000) {  /* Little endian */
slouken@1895
   856
        ++src;
slouken@1895
   857
    }
slouken@1895
   858
    for (i = cvt->len_cvt / 2; i; --i) {
slouken@1895
   859
        *dst = *src;
slouken@1895
   860
        src += 2;
slouken@1895
   861
        dst += 1;
slouken@1895
   862
    }
slouken@1895
   863
    format = ((format & ~0x9010) | AUDIO_U8);
slouken@1895
   864
    cvt->len_cvt /= 2;
slouken@1895
   865
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   866
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   867
    }
slouken@0
   868
}
slouken@0
   869
slouken@0
   870
/* Toggle signed/unsigned */
slouken@1895
   871
void SDLCALL
slouken@1895
   872
SDL_ConvertSign(SDL_AudioCVT * cvt, Uint16 format)
slouken@0
   873
{
slouken@1895
   874
    int i;
slouken@1895
   875
    Uint8 *data;
slouken@0
   876
slouken@0
   877
#ifdef DEBUG_CONVERT
slouken@1895
   878
    fprintf(stderr, "Converting audio signedness\n");
slouken@0
   879
#endif
slouken@1895
   880
    data = cvt->buf;
slouken@1895
   881
    if ((format & 0xFF) == 16) {
slouken@1895
   882
        if ((format & 0x1000) != 0x1000) {      /* Little endian */
slouken@1895
   883
            ++data;
slouken@1895
   884
        }
slouken@1895
   885
        for (i = cvt->len_cvt / 2; i; --i) {
slouken@1895
   886
            *data ^= 0x80;
slouken@1895
   887
            data += 2;
slouken@1895
   888
        }
slouken@1895
   889
    } else {
slouken@1895
   890
        for (i = cvt->len_cvt; i; --i) {
slouken@1895
   891
            *data++ ^= 0x80;
slouken@1895
   892
        }
slouken@1895
   893
    }
slouken@1895
   894
    format = (format ^ 0x8000);
slouken@1895
   895
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   896
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   897
    }
slouken@0
   898
}
slouken@0
   899
slouken@0
   900
/* Toggle endianness */
slouken@1895
   901
void SDLCALL
slouken@1895
   902
SDL_ConvertEndian(SDL_AudioCVT * cvt, Uint16 format)
slouken@0
   903
{
slouken@1895
   904
    int i;
slouken@1895
   905
    Uint8 *data, tmp;
slouken@0
   906
slouken@0
   907
#ifdef DEBUG_CONVERT
slouken@1895
   908
    fprintf(stderr, "Converting audio endianness\n");
slouken@0
   909
#endif
slouken@1895
   910
    data = cvt->buf;
slouken@1895
   911
    for (i = cvt->len_cvt / 2; i; --i) {
slouken@1895
   912
        tmp = data[0];
slouken@1895
   913
        data[0] = data[1];
slouken@1895
   914
        data[1] = tmp;
slouken@1895
   915
        data += 2;
slouken@1895
   916
    }
slouken@1895
   917
    format = (format ^ 0x1000);
slouken@1895
   918
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   919
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   920
    }
slouken@0
   921
}
slouken@0
   922
slouken@0
   923
/* Convert rate up by multiple of 2 */
slouken@1895
   924
void SDLCALL
slouken@1895
   925
SDL_RateMUL2(SDL_AudioCVT * cvt, Uint16 format)
slouken@0
   926
{
slouken@1895
   927
    int i;
slouken@1895
   928
    Uint8 *src, *dst;
slouken@0
   929
slouken@0
   930
#ifdef DEBUG_CONVERT
slouken@1895
   931
    fprintf(stderr, "Converting audio rate * 2\n");
slouken@0
   932
#endif
slouken@1895
   933
    src = cvt->buf + cvt->len_cvt;
slouken@1895
   934
    dst = cvt->buf + cvt->len_cvt * 2;
slouken@1895
   935
    switch (format & 0xFF) {
slouken@1895
   936
    case 8:
slouken@1895
   937
        for (i = cvt->len_cvt; i; --i) {
slouken@1895
   938
            src -= 1;
slouken@1895
   939
            dst -= 2;
slouken@1895
   940
            dst[0] = src[0];
slouken@1895
   941
            dst[1] = src[0];
slouken@1895
   942
        }
slouken@1895
   943
        break;
slouken@1895
   944
    case 16:
slouken@1895
   945
        for (i = cvt->len_cvt / 2; i; --i) {
slouken@1895
   946
            src -= 2;
slouken@1895
   947
            dst -= 4;
slouken@1895
   948
            dst[0] = src[0];
slouken@1895
   949
            dst[1] = src[1];
slouken@1895
   950
            dst[2] = src[0];
slouken@1895
   951
            dst[3] = src[1];
slouken@1895
   952
        }
slouken@1895
   953
        break;
slouken@1895
   954
    }
slouken@1895
   955
    cvt->len_cvt *= 2;
slouken@1895
   956
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
   957
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
   958
    }
slouken@0
   959
}
slouken@0
   960
slouken@942
   961
slouken@942
   962
/* Convert rate up by multiple of 2, for stereo */
slouken@1895
   963
void SDLCALL
slouken@1895
   964
SDL_RateMUL2_c2(SDL_AudioCVT * cvt, Uint16 format)
slouken@942
   965
{
slouken@1895
   966
    int i;
slouken@1895
   967
    Uint8 *src, *dst;
slouken@942
   968
slouken@942
   969
#ifdef DEBUG_CONVERT
slouken@1895
   970
    fprintf(stderr, "Converting audio rate * 2\n");
slouken@942
   971
#endif
slouken@1895
   972
    src = cvt->buf + cvt->len_cvt;
slouken@1895
   973
    dst = cvt->buf + cvt->len_cvt * 2;
slouken@1895
   974
    switch (format & 0xFF) {
slouken@1895
   975
    case 8:
slouken@1895
   976
        for (i = cvt->len_cvt / 2; i; --i) {
slouken@1895
   977
            src -= 2;
slouken@1895
   978
            dst -= 4;
slouken@1895
   979
            dst[0] = src[0];
slouken@1895
   980
            dst[1] = src[1];
slouken@1895
   981
            dst[2] = src[0];
slouken@1895
   982
            dst[3] = src[1];
slouken@1895
   983
        }
slouken@1895
   984
        break;
slouken@1895
   985
    case 16:
slouken@1895
   986
        for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
   987
            src -= 4;
slouken@1895
   988
            dst -= 8;
slouken@1895
   989
            dst[0] = src[0];
slouken@1895
   990
            dst[1] = src[1];
slouken@1895
   991
            dst[2] = src[2];
slouken@1895
   992
            dst[3] = src[3];
slouken@1895
   993
            dst[4] = src[0];
slouken@1895
   994
            dst[5] = src[1];
slouken@1895
   995
            dst[6] = src[2];
slouken@1895
   996
            dst[7] = src[3];
slouken@1895
   997
        }
slouken@1895
   998
        break;
slouken@1895
   999
    }
slouken@1895
  1000
    cvt->len_cvt *= 2;
slouken@1895
  1001
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
  1002
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
  1003
    }
slouken@942
  1004
}
slouken@942
  1005
slouken@942
  1006
/* Convert rate up by multiple of 2, for quad */
slouken@1895
  1007
void SDLCALL
slouken@1895
  1008
SDL_RateMUL2_c4(SDL_AudioCVT * cvt, Uint16 format)
slouken@942
  1009
{
slouken@1895
  1010
    int i;
slouken@1895
  1011
    Uint8 *src, *dst;
slouken@942
  1012
slouken@942
  1013
#ifdef DEBUG_CONVERT
slouken@1895
  1014
    fprintf(stderr, "Converting audio rate * 2\n");
slouken@942
  1015
#endif
slouken@1895
  1016
    src = cvt->buf + cvt->len_cvt;
slouken@1895
  1017
    dst = cvt->buf + cvt->len_cvt * 2;
slouken@1895
  1018
    switch (format & 0xFF) {
slouken@1895
  1019
    case 8:
slouken@1895
  1020
        for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
  1021
            src -= 4;
slouken@1895
  1022
            dst -= 8;
slouken@1895
  1023
            dst[0] = src[0];
slouken@1895
  1024
            dst[1] = src[1];
slouken@1895
  1025
            dst[2] = src[2];
slouken@1895
  1026
            dst[3] = src[3];
slouken@1895
  1027
            dst[4] = src[0];
slouken@1895
  1028
            dst[5] = src[1];
slouken@1895
  1029
            dst[6] = src[2];
slouken@1895
  1030
            dst[7] = src[3];
slouken@1895
  1031
        }
slouken@1895
  1032
        break;
slouken@1895
  1033
    case 16:
slouken@1895
  1034
        for (i = cvt->len_cvt / 8; i; --i) {
slouken@1895
  1035
            src -= 8;
slouken@1895
  1036
            dst -= 16;
slouken@1895
  1037
            dst[0] = src[0];
slouken@1895
  1038
            dst[1] = src[1];
slouken@1895
  1039
            dst[2] = src[2];
slouken@1895
  1040
            dst[3] = src[3];
slouken@1895
  1041
            dst[4] = src[4];
slouken@1895
  1042
            dst[5] = src[5];
slouken@1895
  1043
            dst[6] = src[6];
slouken@1895
  1044
            dst[7] = src[7];
slouken@1895
  1045
            dst[8] = src[0];
slouken@1895
  1046
            dst[9] = src[1];
slouken@1895
  1047
            dst[10] = src[2];
slouken@1895
  1048
            dst[11] = src[3];
slouken@1895
  1049
            dst[12] = src[4];
slouken@1895
  1050
            dst[13] = src[5];
slouken@1895
  1051
            dst[14] = src[6];
slouken@1895
  1052
            dst[15] = src[7];
slouken@1895
  1053
        }
slouken@1895
  1054
        break;
slouken@1895
  1055
    }
slouken@1895
  1056
    cvt->len_cvt *= 2;
slouken@1895
  1057
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
  1058
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
  1059
    }
slouken@942
  1060
}
slouken@942
  1061
slouken@942
  1062
slouken@942
  1063
/* Convert rate up by multiple of 2, for 5.1 */
slouken@1895
  1064
void SDLCALL
slouken@1895
  1065
SDL_RateMUL2_c6(SDL_AudioCVT * cvt, Uint16 format)
slouken@942
  1066
{
slouken@1895
  1067
    int i;
slouken@1895
  1068
    Uint8 *src, *dst;
slouken@942
  1069
slouken@942
  1070
#ifdef DEBUG_CONVERT
slouken@1895
  1071
    fprintf(stderr, "Converting audio rate * 2\n");
slouken@942
  1072
#endif
slouken@1895
  1073
    src = cvt->buf + cvt->len_cvt;
slouken@1895
  1074
    dst = cvt->buf + cvt->len_cvt * 2;
slouken@1895
  1075
    switch (format & 0xFF) {
slouken@1895
  1076
    case 8:
slouken@1895
  1077
        for (i = cvt->len_cvt / 6; i; --i) {
slouken@1895
  1078
            src -= 6;
slouken@1895
  1079
            dst -= 12;
slouken@1895
  1080
            dst[0] = src[0];
slouken@1895
  1081
            dst[1] = src[1];
slouken@1895
  1082
            dst[2] = src[2];
slouken@1895
  1083
            dst[3] = src[3];
slouken@1895
  1084
            dst[4] = src[4];
slouken@1895
  1085
            dst[5] = src[5];
slouken@1895
  1086
            dst[6] = src[0];
slouken@1895
  1087
            dst[7] = src[1];
slouken@1895
  1088
            dst[8] = src[2];
slouken@1895
  1089
            dst[9] = src[3];
slouken@1895
  1090
            dst[10] = src[4];
slouken@1895
  1091
            dst[11] = src[5];
slouken@1895
  1092
        }
slouken@1895
  1093
        break;
slouken@1895
  1094
    case 16:
slouken@1895
  1095
        for (i = cvt->len_cvt / 12; i; --i) {
slouken@1895
  1096
            src -= 12;
slouken@1895
  1097
            dst -= 24;
slouken@1895
  1098
            dst[0] = src[0];
slouken@1895
  1099
            dst[1] = src[1];
slouken@1895
  1100
            dst[2] = src[2];
slouken@1895
  1101
            dst[3] = src[3];
slouken@1895
  1102
            dst[4] = src[4];
slouken@1895
  1103
            dst[5] = src[5];
slouken@1895
  1104
            dst[6] = src[6];
slouken@1895
  1105
            dst[7] = src[7];
slouken@1895
  1106
            dst[8] = src[8];
slouken@1895
  1107
            dst[9] = src[9];
slouken@1895
  1108
            dst[10] = src[10];
slouken@1895
  1109
            dst[11] = src[11];
slouken@1895
  1110
            dst[12] = src[0];
slouken@1895
  1111
            dst[13] = src[1];
slouken@1895
  1112
            dst[14] = src[2];
slouken@1895
  1113
            dst[15] = src[3];
slouken@1895
  1114
            dst[16] = src[4];
slouken@1895
  1115
            dst[17] = src[5];
slouken@1895
  1116
            dst[18] = src[6];
slouken@1895
  1117
            dst[19] = src[7];
slouken@1895
  1118
            dst[20] = src[8];
slouken@1895
  1119
            dst[21] = src[9];
slouken@1895
  1120
            dst[22] = src[10];
slouken@1895
  1121
            dst[23] = src[11];
slouken@1895
  1122
        }
slouken@1895
  1123
        break;
slouken@1895
  1124
    }
slouken@1895
  1125
    cvt->len_cvt *= 2;
slouken@1895
  1126
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
  1127
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
  1128
    }
slouken@942
  1129
}
slouken@942
  1130
slouken@0
  1131
/* Convert rate down by multiple of 2 */
slouken@1895
  1132
void SDLCALL
slouken@1895
  1133
SDL_RateDIV2(SDL_AudioCVT * cvt, Uint16 format)
slouken@0
  1134
{
slouken@1895
  1135
    int i;
slouken@1895
  1136
    Uint8 *src, *dst;
slouken@0
  1137
slouken@0
  1138
#ifdef DEBUG_CONVERT
slouken@1895
  1139
    fprintf(stderr, "Converting audio rate / 2\n");
slouken@0
  1140
#endif
slouken@1895
  1141
    src = cvt->buf;
slouken@1895
  1142
    dst = cvt->buf;
slouken@1895
  1143
    switch (format & 0xFF) {
slouken@1895
  1144
    case 8:
slouken@1895
  1145
        for (i = cvt->len_cvt / 2; i; --i) {
slouken@1895
  1146
            dst[0] = src[0];
slouken@1895
  1147
            src += 2;
slouken@1895
  1148
            dst += 1;
slouken@1895
  1149
        }
slouken@1895
  1150
        break;
slouken@1895
  1151
    case 16:
slouken@1895
  1152
        for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
  1153
            dst[0] = src[0];
slouken@1895
  1154
            dst[1] = src[1];
slouken@1895
  1155
            src += 4;
slouken@1895
  1156
            dst += 2;
slouken@1895
  1157
        }
slouken@1895
  1158
        break;
slouken@1895
  1159
    }
slouken@1895
  1160
    cvt->len_cvt /= 2;
slouken@1895
  1161
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
  1162
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
  1163
    }
slouken@0
  1164
}
slouken@0
  1165
slouken@942
  1166
slouken@942
  1167
/* Convert rate down by multiple of 2, for stereo */
slouken@1895
  1168
void SDLCALL
slouken@1895
  1169
SDL_RateDIV2_c2(SDL_AudioCVT * cvt, Uint16 format)
slouken@942
  1170
{
slouken@1895
  1171
    int i;
slouken@1895
  1172
    Uint8 *src, *dst;
slouken@942
  1173
slouken@942
  1174
#ifdef DEBUG_CONVERT
slouken@1895
  1175
    fprintf(stderr, "Converting audio rate / 2\n");
slouken@942
  1176
#endif
slouken@1895
  1177
    src = cvt->buf;
slouken@1895
  1178
    dst = cvt->buf;
slouken@1895
  1179
    switch (format & 0xFF) {
slouken@1895
  1180
    case 8:
slouken@1895
  1181
        for (i = cvt->len_cvt / 4; i; --i) {
slouken@1895
  1182
            dst[0] = src[0];
slouken@1895
  1183
            dst[1] = src[1];
slouken@1895
  1184
            src += 4;
slouken@1895
  1185
            dst += 2;
slouken@1895
  1186
        }
slouken@1895
  1187
        break;
slouken@1895
  1188
    case 16:
slouken@1895
  1189
        for (i = cvt->len_cvt / 8; i; --i) {
slouken@1895
  1190
            dst[0] = src[0];
slouken@1895
  1191
            dst[1] = src[1];
slouken@1895
  1192
            dst[2] = src[2];
slouken@1895
  1193
            dst[3] = src[3];
slouken@1895
  1194
            src += 8;
slouken@1895
  1195
            dst += 4;
slouken@1895
  1196
        }
slouken@1895
  1197
        break;
slouken@1895
  1198
    }
slouken@1895
  1199
    cvt->len_cvt /= 2;
slouken@1895
  1200
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
  1201
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
  1202
    }
slouken@942
  1203
}
slouken@942
  1204
slouken@942
  1205
slouken@942
  1206
/* Convert rate down by multiple of 2, for quad */
slouken@1895
  1207
void SDLCALL
slouken@1895
  1208
SDL_RateDIV2_c4(SDL_AudioCVT * cvt, Uint16 format)
slouken@942
  1209
{
slouken@1895
  1210
    int i;
slouken@1895
  1211
    Uint8 *src, *dst;
slouken@942
  1212
slouken@942
  1213
#ifdef DEBUG_CONVERT
slouken@1895
  1214
    fprintf(stderr, "Converting audio rate / 2\n");
slouken@942
  1215
#endif
slouken@1895
  1216
    src = cvt->buf;
slouken@1895
  1217
    dst = cvt->buf;
slouken@1895
  1218
    switch (format & 0xFF) {
slouken@1895
  1219
    case 8:
slouken@1895
  1220
        for (i = cvt->len_cvt / 8; i; --i) {
slouken@1895
  1221
            dst[0] = src[0];
slouken@1895
  1222
            dst[1] = src[1];
slouken@1895
  1223
            dst[2] = src[2];
slouken@1895
  1224
            dst[3] = src[3];
slouken@1895
  1225
            src += 8;
slouken@1895
  1226
            dst += 4;
slouken@1895
  1227
        }
slouken@1895
  1228
        break;
slouken@1895
  1229
    case 16:
slouken@1895
  1230
        for (i = cvt->len_cvt / 16; i; --i) {
slouken@1895
  1231
            dst[0] = src[0];
slouken@1895
  1232
            dst[1] = src[1];
slouken@1895
  1233
            dst[2] = src[2];
slouken@1895
  1234
            dst[3] = src[3];
slouken@1895
  1235
            dst[4] = src[4];
slouken@1895
  1236
            dst[5] = src[5];
slouken@1895
  1237
            dst[6] = src[6];
slouken@1895
  1238
            dst[7] = src[7];
slouken@1895
  1239
            src += 16;
slouken@1895
  1240
            dst += 8;
slouken@1895
  1241
        }
slouken@1895
  1242
        break;
slouken@1895
  1243
    }
slouken@1895
  1244
    cvt->len_cvt /= 2;
slouken@1895
  1245
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
  1246
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
  1247
    }
slouken@942
  1248
}
slouken@942
  1249
slouken@942
  1250
/* Convert rate down by multiple of 2, for 5.1 */
slouken@1895
  1251
void SDLCALL
slouken@1895
  1252
SDL_RateDIV2_c6(SDL_AudioCVT * cvt, Uint16 format)
slouken@942
  1253
{
slouken@1895
  1254
    int i;
slouken@1895
  1255
    Uint8 *src, *dst;
slouken@942
  1256
slouken@942
  1257
#ifdef DEBUG_CONVERT
slouken@1895
  1258
    fprintf(stderr, "Converting audio rate / 2\n");
slouken@942
  1259
#endif
slouken@1895
  1260
    src = cvt->buf;
slouken@1895
  1261
    dst = cvt->buf;
slouken@1895
  1262
    switch (format & 0xFF) {
slouken@1895
  1263
    case 8:
slouken@1895
  1264
        for (i = cvt->len_cvt / 12; i; --i) {
slouken@1895
  1265
            dst[0] = src[0];
slouken@1895
  1266
            dst[1] = src[1];
slouken@1895
  1267
            dst[2] = src[2];
slouken@1895
  1268
            dst[3] = src[3];
slouken@1895
  1269
            dst[4] = src[4];
slouken@1895
  1270
            dst[5] = src[5];
slouken@1895
  1271
            src += 12;
slouken@1895
  1272
            dst += 6;
slouken@1895
  1273
        }
slouken@1895
  1274
        break;
slouken@1895
  1275
    case 16:
slouken@1895
  1276
        for (i = cvt->len_cvt / 24; i; --i) {
slouken@1895
  1277
            dst[0] = src[0];
slouken@1895
  1278
            dst[1] = src[1];
slouken@1895
  1279
            dst[2] = src[2];
slouken@1895
  1280
            dst[3] = src[3];
slouken@1895
  1281
            dst[4] = src[4];
slouken@1895
  1282
            dst[5] = src[5];
slouken@1895
  1283
            dst[6] = src[6];
slouken@1895
  1284
            dst[7] = src[7];
slouken@1895
  1285
            dst[8] = src[8];
slouken@1895
  1286
            dst[9] = src[9];
slouken@1895
  1287
            dst[10] = src[10];
slouken@1895
  1288
            dst[11] = src[11];
slouken@1895
  1289
            src += 24;
slouken@1895
  1290
            dst += 12;
slouken@1895
  1291
        }
slouken@1895
  1292
        break;
slouken@1895
  1293
    }
slouken@1895
  1294
    cvt->len_cvt /= 2;
slouken@1895
  1295
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
  1296
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
  1297
    }
slouken@942
  1298
}
slouken@942
  1299
slouken@0
  1300
/* Very slow rate conversion routine */
slouken@1895
  1301
void SDLCALL
slouken@1895
  1302
SDL_RateSLOW(SDL_AudioCVT * cvt, Uint16 format)
slouken@0
  1303
{
slouken@1895
  1304
    double ipos;
slouken@1895
  1305
    int i, clen;
slouken@0
  1306
slouken@0
  1307
#ifdef DEBUG_CONVERT
slouken@1895
  1308
    fprintf(stderr, "Converting audio rate * %4.4f\n", 1.0 / cvt->rate_incr);
slouken@0
  1309
#endif
slouken@1895
  1310
    clen = (int) ((double) cvt->len_cvt / cvt->rate_incr);
slouken@1895
  1311
    if (cvt->rate_incr > 1.0) {
slouken@1895
  1312
        switch (format & 0xFF) {
slouken@1895
  1313
        case 8:
slouken@1895
  1314
            {
slouken@1895
  1315
                Uint8 *output;
slouken@0
  1316
slouken@1895
  1317
                output = cvt->buf;
slouken@1895
  1318
                ipos = 0.0;
slouken@1895
  1319
                for (i = clen; i; --i) {
slouken@1895
  1320
                    *output = cvt->buf[(int) ipos];
slouken@1895
  1321
                    ipos += cvt->rate_incr;
slouken@1895
  1322
                    output += 1;
slouken@1895
  1323
                }
slouken@1895
  1324
            }
slouken@1895
  1325
            break;
slouken@0
  1326
slouken@1895
  1327
        case 16:
slouken@1895
  1328
            {
slouken@1895
  1329
                Uint16 *output;
slouken@0
  1330
slouken@1895
  1331
                clen &= ~1;
slouken@1895
  1332
                output = (Uint16 *) cvt->buf;
slouken@1895
  1333
                ipos = 0.0;
slouken@1895
  1334
                for (i = clen / 2; i; --i) {
slouken@1895
  1335
                    *output = ((Uint16 *) cvt->buf)[(int) ipos];
slouken@1895
  1336
                    ipos += cvt->rate_incr;
slouken@1895
  1337
                    output += 1;
slouken@1895
  1338
                }
slouken@1895
  1339
            }
slouken@1895
  1340
            break;
slouken@1895
  1341
        }
slouken@1895
  1342
    } else {
slouken@1895
  1343
        switch (format & 0xFF) {
slouken@1895
  1344
        case 8:
slouken@1895
  1345
            {
slouken@1895
  1346
                Uint8 *output;
slouken@0
  1347
slouken@1895
  1348
                output = cvt->buf + clen;
slouken@1895
  1349
                ipos = (double) cvt->len_cvt;
slouken@1895
  1350
                for (i = clen; i; --i) {
slouken@1895
  1351
                    ipos -= cvt->rate_incr;
slouken@1895
  1352
                    output -= 1;
slouken@1895
  1353
                    *output = cvt->buf[(int) ipos];
slouken@1895
  1354
                }
slouken@1895
  1355
            }
slouken@1895
  1356
            break;
slouken@0
  1357
slouken@1895
  1358
        case 16:
slouken@1895
  1359
            {
slouken@1895
  1360
                Uint16 *output;
slouken@0
  1361
slouken@1895
  1362
                clen &= ~1;
slouken@1895
  1363
                output = (Uint16 *) (cvt->buf + clen);
slouken@1895
  1364
                ipos = (double) cvt->len_cvt / 2;
slouken@1895
  1365
                for (i = clen / 2; i; --i) {
slouken@1895
  1366
                    ipos -= cvt->rate_incr;
slouken@1895
  1367
                    output -= 1;
slouken@1895
  1368
                    *output = ((Uint16 *) cvt->buf)[(int) ipos];
slouken@1895
  1369
                }
slouken@1895
  1370
            }
slouken@1895
  1371
            break;
slouken@1895
  1372
        }
slouken@1895
  1373
    }
slouken@1895
  1374
    cvt->len_cvt = clen;
slouken@1895
  1375
    if (cvt->filters[++cvt->filter_index]) {
slouken@1895
  1376
        cvt->filters[cvt->filter_index] (cvt, format);
slouken@1895
  1377
    }
slouken@0
  1378
}
slouken@0
  1379
slouken@1895
  1380
int
slouken@1895
  1381
SDL_ConvertAudio(SDL_AudioCVT * cvt)
slouken@0
  1382
{
slouken@1895
  1383
    /* Make sure there's data to convert */
slouken@1895
  1384
    if (cvt->buf == NULL) {
slouken@1895
  1385
        SDL_SetError("No buffer allocated for conversion");
slouken@1895
  1386
        return (-1);
slouken@1895
  1387
    }
slouken@1895
  1388
    /* Return okay if no conversion is necessary */
slouken@1895
  1389
    cvt->len_cvt = cvt->len;
slouken@1895
  1390
    if (cvt->filters[0] == NULL) {
slouken@1895
  1391
        return (0);
slouken@1895
  1392
    }
slouken@0
  1393
slouken@1895
  1394
    /* Set up the conversion and go! */
slouken@1895
  1395
    cvt->filter_index = 0;
slouken@1895
  1396
    cvt->filters[0] (cvt, cvt->src_format);
slouken@1895
  1397
    return (0);
slouken@0
  1398
}
slouken@0
  1399
slouken@0
  1400
/* Creates a set of audio filters to convert from one format to another. 
slouken@0
  1401
   Returns -1 if the format conversion is not supported, or 1 if the
slouken@0
  1402
   audio filter is set up.
slouken@0
  1403
*/
slouken@1895
  1404
slouken@1895
  1405
int
slouken@1895
  1406
SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
slouken@1895
  1407
                  Uint16 src_format, Uint8 src_channels, int src_rate,
slouken@1895
  1408
                  Uint16 dst_format, Uint8 dst_channels, int dst_rate)
slouken@0
  1409
{
slouken@942
  1410
/*printf("Build format %04x->%04x, channels %u->%u, rate %d->%d\n",
slouken@942
  1411
		src_format, dst_format, src_channels, dst_channels, src_rate, dst_rate);*/
slouken@1895
  1412
    /* Start off with no conversion necessary */
slouken@1895
  1413
    cvt->needed = 0;
slouken@1895
  1414
    cvt->filter_index = 0;
slouken@1895
  1415
    cvt->filters[0] = NULL;
slouken@1895
  1416
    cvt->len_mult = 1;
slouken@1895
  1417
    cvt->len_ratio = 1.0;
slouken@0
  1418
slouken@1895
  1419
    /* First filter:  Endian conversion from src to dst */
slouken@1895
  1420
    if ((src_format & 0x1000) != (dst_format & 0x1000)
slouken@1895
  1421
        && ((src_format & 0xff) != 8)) {
slouken@1895
  1422
        cvt->filters[cvt->filter_index++] = SDL_ConvertEndian;
slouken@1895
  1423
    }
slouken@0
  1424
slouken@1895
  1425
    /* Second filter: Sign conversion -- signed/unsigned */
slouken@1895
  1426
    if ((src_format & 0x8000) != (dst_format & 0x8000)) {
slouken@1895
  1427
        cvt->filters[cvt->filter_index++] = SDL_ConvertSign;
slouken@1895
  1428
    }
slouken@0
  1429
slouken@1895
  1430
    /* Next filter:  Convert 16 bit <--> 8 bit PCM */
slouken@1895
  1431
    if ((src_format & 0xFF) != (dst_format & 0xFF)) {
slouken@1895
  1432
        switch (dst_format & 0x10FF) {
slouken@1895
  1433
        case AUDIO_U8:
slouken@1895
  1434
            cvt->filters[cvt->filter_index++] = SDL_Convert8;
slouken@1895
  1435
            cvt->len_ratio /= 2;
slouken@1895
  1436
            break;
slouken@1895
  1437
        case AUDIO_U16LSB:
slouken@1895
  1438
            cvt->filters[cvt->filter_index++] = SDL_Convert16LSB;
slouken@1895
  1439
            cvt->len_mult *= 2;
slouken@1895
  1440
            cvt->len_ratio *= 2;
slouken@1895
  1441
            break;
slouken@1895
  1442
        case AUDIO_U16MSB:
slouken@1895
  1443
            cvt->filters[cvt->filter_index++] = SDL_Convert16MSB;
slouken@1895
  1444
            cvt->len_mult *= 2;
slouken@1895
  1445
            cvt->len_ratio *= 2;
slouken@1895
  1446
            break;
slouken@1895
  1447
        }
slouken@1895
  1448
    }
slouken@0
  1449
slouken@1895
  1450
    /* Last filter:  Mono/Stereo conversion */
slouken@1895
  1451
    if (src_channels != dst_channels) {
slouken@1895
  1452
        if ((src_channels == 1) && (dst_channels > 1)) {
slouken@1895
  1453
            cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
slouken@1895
  1454
            cvt->len_mult *= 2;
slouken@1895
  1455
            src_channels = 2;
slouken@1895
  1456
            cvt->len_ratio *= 2;
slouken@1895
  1457
        }
slouken@1895
  1458
        if ((src_channels == 2) && (dst_channels == 6)) {
slouken@1895
  1459
            cvt->filters[cvt->filter_index++] = SDL_ConvertSurround;
slouken@1895
  1460
            src_channels = 6;
slouken@1895
  1461
            cvt->len_mult *= 3;
slouken@1895
  1462
            cvt->len_ratio *= 3;
slouken@1895
  1463
        }
slouken@1895
  1464
        if ((src_channels == 2) && (dst_channels == 4)) {
slouken@1895
  1465
            cvt->filters[cvt->filter_index++] = SDL_ConvertSurround_4;
slouken@1895
  1466
            src_channels = 4;
slouken@1895
  1467
            cvt->len_mult *= 2;
slouken@1895
  1468
            cvt->len_ratio *= 2;
slouken@1895
  1469
        }
slouken@1895
  1470
        while ((src_channels * 2) <= dst_channels) {
slouken@1895
  1471
            cvt->filters[cvt->filter_index++] = SDL_ConvertStereo;
slouken@1895
  1472
            cvt->len_mult *= 2;
slouken@1895
  1473
            src_channels *= 2;
slouken@1895
  1474
            cvt->len_ratio *= 2;
slouken@1895
  1475
        }
slouken@1895
  1476
        if ((src_channels == 6) && (dst_channels <= 2)) {
slouken@1895
  1477
            cvt->filters[cvt->filter_index++] = SDL_ConvertStrip;
slouken@1895
  1478
            src_channels = 2;
slouken@1895
  1479
            cvt->len_ratio /= 3;
slouken@1895
  1480
        }
slouken@1895
  1481
        if ((src_channels == 6) && (dst_channels == 4)) {
slouken@1895
  1482
            cvt->filters[cvt->filter_index++] = SDL_ConvertStrip_2;
slouken@1895
  1483
            src_channels = 4;
slouken@1895
  1484
            cvt->len_ratio /= 2;
slouken@1895
  1485
        }
slouken@1895
  1486
        /* This assumes that 4 channel audio is in the format:
slouken@1895
  1487
           Left {front/back} + Right {front/back}
slouken@1895
  1488
           so converting to L/R stereo works properly.
slouken@1895
  1489
         */
slouken@1895
  1490
        while (((src_channels % 2) == 0) &&
slouken@1895
  1491
               ((src_channels / 2) >= dst_channels)) {
slouken@1895
  1492
            cvt->filters[cvt->filter_index++] = SDL_ConvertMono;
slouken@1895
  1493
            src_channels /= 2;
slouken@1895
  1494
            cvt->len_ratio /= 2;
slouken@1895
  1495
        }
slouken@1895
  1496
        if (src_channels != dst_channels) {
slouken@1895
  1497
            /* Uh oh.. */ ;
slouken@1895
  1498
        }
slouken@1895
  1499
    }
slouken@0
  1500
slouken@1895
  1501
    /* Do rate conversion */
slouken@1895
  1502
    cvt->rate_incr = 0.0;
slouken@1895
  1503
    if ((src_rate / 100) != (dst_rate / 100)) {
slouken@1895
  1504
        Uint32 hi_rate, lo_rate;
slouken@1895
  1505
        int len_mult;
slouken@1895
  1506
        double len_ratio;
slouken@1895
  1507
        void (SDLCALL * rate_cvt) (SDL_AudioCVT * cvt, Uint16 format);
slouken@1895
  1508
slouken@1895
  1509
        if (src_rate > dst_rate) {
slouken@1895
  1510
            hi_rate = src_rate;
slouken@1895
  1511
            lo_rate = dst_rate;
slouken@1895
  1512
            switch (src_channels) {
slouken@1895
  1513
            case 1:
slouken@1895
  1514
                rate_cvt = SDL_RateDIV2;
slouken@1895
  1515
                break;
slouken@1895
  1516
            case 2:
slouken@1895
  1517
                rate_cvt = SDL_RateDIV2_c2;
slouken@1895
  1518
                break;
slouken@1895
  1519
            case 4:
slouken@1895
  1520
                rate_cvt = SDL_RateDIV2_c4;
slouken@1895
  1521
                break;
slouken@1895
  1522
            case 6:
slouken@1895
  1523
                rate_cvt = SDL_RateDIV2_c6;
slouken@1895
  1524
                break;
slouken@1895
  1525
            default:
slouken@1895
  1526
                return -1;
slouken@1895
  1527
            }
slouken@1895
  1528
            len_mult = 1;
slouken@1895
  1529
            len_ratio = 0.5;
slouken@1895
  1530
        } else {
slouken@1895
  1531
            hi_rate = dst_rate;
slouken@1895
  1532
            lo_rate = src_rate;
slouken@1895
  1533
            switch (src_channels) {
slouken@1895
  1534
            case 1:
slouken@1895
  1535
                rate_cvt = SDL_RateMUL2;
slouken@1895
  1536
                break;
slouken@1895
  1537
            case 2:
slouken@1895
  1538
                rate_cvt = SDL_RateMUL2_c2;
slouken@1895
  1539
                break;
slouken@1895
  1540
            case 4:
slouken@1895
  1541
                rate_cvt = SDL_RateMUL2_c4;
slouken@1895
  1542
                break;
slouken@1895
  1543
            case 6:
slouken@1895
  1544
                rate_cvt = SDL_RateMUL2_c6;
slouken@1895
  1545
                break;
slouken@1895
  1546
            default:
slouken@1895
  1547
                return -1;
slouken@1895
  1548
            }
slouken@1895
  1549
            len_mult = 2;
slouken@1895
  1550
            len_ratio = 2.0;
slouken@1895
  1551
        }
slouken@1895
  1552
        /* If hi_rate = lo_rate*2^x then conversion is easy */
slouken@1895
  1553
        while (((lo_rate * 2) / 100) <= (hi_rate / 100)) {
slouken@1895
  1554
            cvt->filters[cvt->filter_index++] = rate_cvt;
slouken@1895
  1555
            cvt->len_mult *= len_mult;
slouken@1895
  1556
            lo_rate *= 2;
slouken@1895
  1557
            cvt->len_ratio *= len_ratio;
slouken@1895
  1558
        }
slouken@1895
  1559
        /* We may need a slow conversion here to finish up */
slouken@1895
  1560
        if ((lo_rate / 100) != (hi_rate / 100)) {
slouken@0
  1561
#if 1
slouken@1895
  1562
            /* The problem with this is that if the input buffer is
slouken@1895
  1563
               say 1K, and the conversion rate is say 1.1, then the
slouken@1895
  1564
               output buffer is 1.1K, which may not be an acceptable
slouken@1895
  1565
               buffer size for the audio driver (not a power of 2)
slouken@1895
  1566
             */
slouken@1895
  1567
            /* For now, punt and hope the rate distortion isn't great.
slouken@1895
  1568
             */
slouken@0
  1569
#else
slouken@1895
  1570
            if (src_rate < dst_rate) {
slouken@1895
  1571
                cvt->rate_incr = (double) lo_rate / hi_rate;
slouken@1895
  1572
                cvt->len_mult *= 2;
slouken@1895
  1573
                cvt->len_ratio /= cvt->rate_incr;
slouken@1895
  1574
            } else {
slouken@1895
  1575
                cvt->rate_incr = (double) hi_rate / lo_rate;
slouken@1895
  1576
                cvt->len_ratio *= cvt->rate_incr;
slouken@1895
  1577
            }
slouken@1895
  1578
            cvt->filters[cvt->filter_index++] = SDL_RateSLOW;
slouken@0
  1579
#endif
slouken@1895
  1580
        }
slouken@1895
  1581
    }
slouken@0
  1582
slouken@1895
  1583
    /* Set up the filter information */
slouken@1895
  1584
    if (cvt->filter_index != 0) {
slouken@1895
  1585
        cvt->needed = 1;
slouken@1895
  1586
        cvt->src_format = src_format;
slouken@1895
  1587
        cvt->dst_format = dst_format;
slouken@1895
  1588
        cvt->len = 0;
slouken@1895
  1589
        cvt->buf = NULL;
slouken@1895
  1590
        cvt->filters[cvt->filter_index] = NULL;
slouken@1895
  1591
    }
slouken@1895
  1592
    return (cvt->needed);
slouken@0
  1593
}
slouken@1895
  1594
slouken@1895
  1595
/* vi: set ts=4 sw=4 expandtab: */