src/audio/SDL_audiotypecvt.c
author Ryan C. Gordon <icculus@icculus.org>
Sat, 05 Nov 2016 02:34:38 -0400
changeset 10575 bb99dede0675
parent 9998 f67cf37e9cd4
child 10608 8661c956c368
permissions -rw-r--r--
Reworked audio converter code.

This no longer uses a script to generate code for every possible type
conversion or resampler. This caused a bloat in binary size and and compile
times. Now we use a handful of more generic functions and assume staying in
the CPU cache is the most important thing anyhow.

This shrinks the size of the final build (in this case: macOS X amd64, -Os to
optimize for size) by 15%. When compiling on a single core, build times drop
by about 15% too (although the previous cost was largely hidden by multicore
builds).
icculus@1982
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9998
     3
  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
slouken@5535
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@5535
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@5535
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
icculus@1982
    20
*/
icculus@1982
    21
icculus@8093
    22
#include "../SDL_internal.h"
icculus@1982
    23
#include "SDL_audio.h"
icculus@1982
    24
#include "SDL_audio_c.h"
icculus@10575
    25
#include "SDL_assert.h"
icculus@1982
    26
icculus@1982
    27
#define DIVBY127 0.0078740157480315f
icculus@1982
    28
#define DIVBY32767 3.05185094759972e-05f
icculus@1982
    29
#define DIVBY2147483647 4.6566128752458e-10f
icculus@1982
    30
icculus@10575
    31
void SDLCALL
icculus@10575
    32
SDL_Convert_S8_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format)
icculus@10575
    33
{
icculus@10575
    34
    const Uint8 *src = ((const Uint8 *) (cvt->buf + cvt->len_cvt)) - 1;
icculus@10575
    35
    float *dst = ((float *) (cvt->buf + cvt->len_cvt * 4)) - 1;
icculus@10575
    36
    int i;
icculus@3021
    37
icculus@10575
    38
    LOG_DEBUG_CONVERT("AUDIO_S8", "AUDIO_F32");
icculus@1982
    39
icculus@10575
    40
    for (i = cvt->len_cvt / sizeof (Uint8); i; --i, --src, --dst) {
icculus@10575
    41
        *dst = (((float) ((Sint8) *src)) * DIVBY127);
icculus@1982
    42
    }
icculus@1982
    43
icculus@10575
    44
    cvt->len_cvt *= 4;
icculus@1982
    45
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
    46
        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
icculus@1982
    47
    }
icculus@1982
    48
}
icculus@1982
    49
icculus@10575
    50
void SDLCALL
icculus@10575
    51
SDL_Convert_U8_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format)
icculus@1982
    52
{
icculus@10575
    53
    const Uint8 *src = ((const Uint8 *) (cvt->buf + cvt->len_cvt)) - 1;
icculus@10575
    54
    float *dst = ((float *) (cvt->buf + cvt->len_cvt * 4)) - 1;
icculus@1982
    55
    int i;
icculus@1982
    56
icculus@10575
    57
    LOG_DEBUG_CONVERT("AUDIO_U8", "AUDIO_F32");
icculus@1982
    58
icculus@1982
    59
    for (i = cvt->len_cvt / sizeof (Uint8); i; --i, --src, --dst) {
icculus@10575
    60
        *dst = ((((float) *src) * DIVBY127) - 1.0f);
icculus@10575
    61
    }
icculus@10575
    62
icculus@10575
    63
    cvt->len_cvt *= 4;
icculus@10575
    64
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
    65
        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
icculus@10575
    66
    }
icculus@10575
    67
}
icculus@10575
    68
icculus@10575
    69
void SDLCALL
icculus@10575
    70
SDL_Convert_S16_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format)
icculus@10575
    71
{
icculus@10575
    72
    const Sint16 *src = ((const Sint16 *) (cvt->buf + cvt->len_cvt)) - 1;
icculus@10575
    73
    float *dst = ((float *) (cvt->buf + cvt->len_cvt * 2)) - 1;
icculus@10575
    74
    int i;
icculus@10575
    75
icculus@10575
    76
    LOG_DEBUG_CONVERT("AUDIO_S16", "AUDIO_F32");
icculus@10575
    77
icculus@10575
    78
    for (i = cvt->len_cvt / sizeof (Sint16); i; --i, --src, --dst) {
icculus@10575
    79
        *dst = (((float) *src) * DIVBY32767);
icculus@1982
    80
    }
icculus@1982
    81
icculus@1982
    82
    cvt->len_cvt *= 2;
icculus@1982
    83
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
    84
        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
icculus@1982
    85
    }
icculus@1982
    86
}
icculus@1982
    87
icculus@10575
    88
void SDLCALL
icculus@10575
    89
SDL_Convert_U16_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format)
icculus@1982
    90
{
icculus@10575
    91
    const Uint16 *src = ((const Uint16 *) (cvt->buf + cvt->len_cvt)) - 1;
icculus@10575
    92
    float *dst = ((float *) (cvt->buf + cvt->len_cvt * 2)) - 1;
icculus@1982
    93
    int i;
icculus@1982
    94
icculus@10575
    95
    LOG_DEBUG_CONVERT("AUDIO_U16", "AUDIO_F32");
icculus@1982
    96
icculus@10575
    97
    for (i = cvt->len_cvt / sizeof (Uint16); i; --i, --src, --dst) {
icculus@10575
    98
        *dst = ((((float) *src) * DIVBY32767) - 1.0f);
icculus@1982
    99
    }
icculus@1982
   100
icculus@1982
   101
    cvt->len_cvt *= 2;
icculus@1982
   102
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   103
        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
icculus@1982
   104
    }
icculus@1982
   105
}
icculus@1982
   106
icculus@10575
   107
void SDLCALL
icculus@10575
   108
SDL_Convert_S32_to_F32(SDL_AudioCVT *cvt, SDL_AudioFormat format)
icculus@1982
   109
{
icculus@10575
   110
    const Uint32 *src = (const Uint32 *) cvt->buf;
icculus@10575
   111
    float *dst = (float *) cvt->buf;
icculus@1982
   112
    int i;
icculus@1982
   113
icculus@10575
   114
    LOG_DEBUG_CONVERT("AUDIO_S32", "AUDIO_F32");
icculus@1982
   115
icculus@10575
   116
    for (i = cvt->len_cvt / sizeof (Sint32); i; --i, ++src, ++dst) {
icculus@10575
   117
        *dst = (((float) *src) * DIVBY2147483647);
icculus@1982
   118
    }
icculus@1982
   119
icculus@1982
   120
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   121
        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
icculus@1982
   122
    }
icculus@1982
   123
}
icculus@1982
   124
icculus@10575
   125
void SDLCALL
icculus@10575
   126
SDL_Convert_F32_to_S8(SDL_AudioCVT *cvt, SDL_AudioFormat format)
icculus@1982
   127
{
icculus@10575
   128
    const float *src = (const float *) cvt->buf;
icculus@10575
   129
    Sint8 *dst = (Sint8 *) cvt->buf;
icculus@1982
   130
    int i;
icculus@1982
   131
icculus@10575
   132
    LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_S8");
icculus@1982
   133
icculus@10575
   134
    for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
icculus@10575
   135
        *dst = (Sint8) (*src * 127.0f);
icculus@1982
   136
    }
icculus@1982
   137
icculus@10575
   138
    cvt->len_cvt /= 4;
icculus@1982
   139
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   140
        cvt->filters[cvt->filter_index](cvt, AUDIO_S8);
icculus@1982
   141
    }
icculus@1982
   142
}
icculus@1982
   143
icculus@10575
   144
void SDLCALL
icculus@10575
   145
SDL_Convert_F32_to_U8(SDL_AudioCVT *cvt, SDL_AudioFormat format)
icculus@1982
   146
{
icculus@10575
   147
    const float *src = (const float *) cvt->buf;
icculus@10575
   148
    Uint8 *dst = (Uint8 *) cvt->buf;
icculus@1982
   149
    int i;
icculus@1982
   150
icculus@10575
   151
    LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_U8");
icculus@1982
   152
icculus@10575
   153
    for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
icculus@10575
   154
        *dst = (Uint8) ((*src + 1.0f) * 127.0f);
icculus@1982
   155
    }
icculus@1982
   156
icculus@10575
   157
    cvt->len_cvt /= 4;
icculus@1982
   158
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   159
        cvt->filters[cvt->filter_index](cvt, AUDIO_U8);
icculus@1982
   160
    }
icculus@1982
   161
}
icculus@1982
   162
icculus@10575
   163
void SDLCALL
icculus@10575
   164
SDL_Convert_F32_to_S16(SDL_AudioCVT *cvt, SDL_AudioFormat format)
icculus@1982
   165
{
icculus@10575
   166
    const float *src = (const float *) cvt->buf;
icculus@10575
   167
    Sint16 *dst = (Sint16 *) cvt->buf;
icculus@1982
   168
    int i;
icculus@1982
   169
icculus@10575
   170
    LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_S16");
icculus@1982
   171
icculus@10575
   172
    for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
icculus@10575
   173
        *dst = (Sint16) (*src * 32767.0f);
icculus@1982
   174
    }
icculus@1982
   175
icculus@1982
   176
    cvt->len_cvt /= 2;
icculus@1982
   177
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   178
        cvt->filters[cvt->filter_index](cvt, AUDIO_S16SYS);
icculus@1982
   179
    }
icculus@1982
   180
}
icculus@1982
   181
icculus@10575
   182
void SDLCALL
icculus@10575
   183
SDL_Convert_F32_to_U16(SDL_AudioCVT *cvt, SDL_AudioFormat format)
icculus@1982
   184
{
icculus@10575
   185
    const float *src = (const float *) cvt->buf;
icculus@10575
   186
    Uint16 *dst = (Uint16 *) cvt->buf;
icculus@1982
   187
    int i;
icculus@1982
   188
icculus@10575
   189
    LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_U16");
icculus@1982
   190
icculus@10575
   191
    for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
icculus@10575
   192
        *dst = (Uint16) ((*src + 1.0f) * 32767.0f);
icculus@1982
   193
    }
icculus@1982
   194
icculus@1982
   195
    cvt->len_cvt /= 2;
icculus@1982
   196
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   197
        cvt->filters[cvt->filter_index](cvt, AUDIO_U16SYS);
icculus@1982
   198
    }
icculus@1982
   199
}
icculus@1982
   200
icculus@10575
   201
void SDLCALL
icculus@10575
   202
SDL_Convert_F32_to_S32(SDL_AudioCVT *cvt, SDL_AudioFormat format)
icculus@1982
   203
{
icculus@10575
   204
    const float *src = (const float *) cvt->buf;
icculus@10575
   205
    Sint32 *dst = (Sint32 *) cvt->buf;
icculus@1982
   206
    int i;
icculus@1982
   207
icculus@10575
   208
    LOG_DEBUG_CONVERT("AUDIO_F32", "AUDIO_S32");
icculus@1982
   209
icculus@10575
   210
    for (i = cvt->len_cvt / sizeof (float); i; --i, ++src, ++dst) {
icculus@10575
   211
        *dst = (Sint32) (*src * 2147483647.0);
icculus@1982
   212
    }
icculus@1982
   213
icculus@1982
   214
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   215
        cvt->filters[cvt->filter_index](cvt, AUDIO_S32SYS);
icculus@1982
   216
    }
icculus@1982
   217
}
icculus@1982
   218
icculus@10575
   219
void
icculus@10575
   220
SDL_Upsample_Arbitrary(SDL_AudioCVT *cvt, const int channels)
icculus@1982
   221
{
icculus@10575
   222
    const int srcsize = cvt->len_cvt - (64 * channels);
icculus@10575
   223
    const int dstsize = (int) (((double)(cvt->len_cvt/(channels*4))) * cvt->rate_incr) * (channels*4);
icculus@10575
   224
    register int eps = 0;
icculus@10575
   225
    float *dst = ((float *) (cvt->buf + dstsize)) - 8;
icculus@10575
   226
    const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - 8;
icculus@10575
   227
    const float *target = ((const float *) cvt->buf);
icculus@10575
   228
    const size_t cpy = sizeof (float) * channels;
icculus@10575
   229
    float last_sample[8];
icculus@10575
   230
    float sample[8];
icculus@1982
   231
    int i;
icculus@1982
   232
slouken@3032
   233
#if DEBUG_CONVERT
icculus@10575
   234
    fprintf(stderr, "Upsample arbitrary (x%f), %d channels.\n", cvt->rate_incr, channels);
icculus@1982
   235
#endif
icculus@1982
   236
icculus@10575
   237
    SDL_assert(channels <= 8);
icculus@1982
   238
icculus@10575
   239
    SDL_memcpy(sample, src, cpy);
icculus@10575
   240
    SDL_memcpy(last_sample, src, cpy);
icculus@1982
   241
slouken@6194
   242
    while (dst >= target) {
icculus@10575
   243
        SDL_memcpy(dst, sample, cpy);
icculus@3021
   244
        dst -= 8;
icculus@3021
   245
        eps += srcsize;
icculus@3021
   246
        if ((eps << 1) >= dstsize) {
icculus@3021
   247
            src -= 8;
icculus@10575
   248
            for (i = 0; i < channels; i++) {
icculus@10575
   249
                sample[i] = (float) ((((double) src[i]) + ((double) last_sample[i])) * 0.5);
icculus@10575
   250
            }
icculus@10575
   251
            SDL_memcpy(last_sample, sample, cpy);
icculus@3021
   252
            eps -= dstsize;
icculus@3021
   253
        }
icculus@3021
   254
    }
icculus@10575
   255
icculus@3021
   256
    cvt->len_cvt = dstsize;
icculus@3021
   257
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   258
        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
icculus@3021
   259
    }
icculus@3021
   260
}
icculus@3021
   261
icculus@10575
   262
void
icculus@10575
   263
SDL_Downsample_Arbitrary(SDL_AudioCVT *cvt, const int channels)
icculus@3021
   264
{
icculus@10575
   265
    const int srcsize = cvt->len_cvt - (64 * channels);
icculus@10575
   266
    const int dstsize = (int) (((double)(cvt->len_cvt/(channels*4))) * cvt->rate_incr) * (channels*4);
icculus@10575
   267
    register int eps = 0;
icculus@10575
   268
    float *dst = (float *) cvt->buf;
icculus@10575
   269
    const float *src = (float *) cvt->buf;
icculus@10575
   270
    const float *target = (const float *) (cvt->buf + dstsize);
icculus@10575
   271
    const size_t cpy = sizeof (float) * channels;
icculus@10575
   272
    float last_sample[8];
icculus@10575
   273
    float sample[8];
icculus@10575
   274
    int i;
icculus@10575
   275
slouken@3032
   276
#if DEBUG_CONVERT
icculus@10575
   277
    fprintf(stderr, "Downsample arbitrary (x%f), %d channels.\n", cvt->rate_incr, channels);
icculus@3021
   278
#endif
icculus@3021
   279
icculus@10575
   280
    SDL_assert(channels <= 8);
icculus@10575
   281
icculus@10575
   282
    SDL_memcpy(sample, src, cpy);
icculus@10575
   283
    SDL_memcpy(last_sample, src, cpy);
icculus@10575
   284
slouken@4889
   285
    while (dst < target) {
icculus@3021
   286
        src += 8;
icculus@3021
   287
        eps += dstsize;
icculus@3021
   288
        if ((eps << 1) >= srcsize) {
icculus@10575
   289
            SDL_memcpy(dst, sample, cpy);
icculus@3021
   290
            dst += 8;
icculus@10575
   291
            for (i = 0; i < channels; i++) {
icculus@10575
   292
                sample[i] = (float) ((((double) src[i]) + ((double) last_sample[i])) * 0.5);
icculus@10575
   293
            }
icculus@10575
   294
            SDL_memcpy(last_sample, sample, cpy);
icculus@3021
   295
            eps -= srcsize;
icculus@3021
   296
        }
icculus@3021
   297
    }
icculus@3021
   298
icculus@3021
   299
    cvt->len_cvt = dstsize;
icculus@3021
   300
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   301
        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
icculus@3021
   302
    }
icculus@3021
   303
}
icculus@3021
   304
icculus@10575
   305
void
icculus@10575
   306
SDL_Upsample_x2(SDL_AudioCVT *cvt, const int channels)
icculus@3021
   307
{
icculus@10575
   308
    const int dstsize = cvt->len_cvt * 2;
icculus@10575
   309
    float *dst = ((float *) (cvt->buf + dstsize)) - (channels * 2);
icculus@10575
   310
    const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - channels;
icculus@10575
   311
    const float *target = ((const float *) cvt->buf);
icculus@10575
   312
    const size_t cpy = sizeof (float) * channels;
icculus@10575
   313
    float last_sample[8];
icculus@10575
   314
    int i;
icculus@10575
   315
slouken@3032
   316
#if DEBUG_CONVERT
icculus@10575
   317
    fprintf(stderr, "Upsample (x2), %d channels.\n", channels);
icculus@3021
   318
#endif
icculus@3021
   319
icculus@10575
   320
    SDL_assert(channels <= 8);
icculus@10575
   321
    SDL_memcpy(last_sample, src, cpy);
icculus@10575
   322
icculus@10575
   323
    while (dst >= target) {
icculus@10575
   324
        for (i = 0; i < channels; i++) {
icculus@10575
   325
            dst[i] = (float) ((((double)src[i]) + ((double)last_sample[i])) * 0.5);
icculus@10575
   326
        }
icculus@10575
   327
        dst -= channels;
icculus@10575
   328
        SDL_memcpy(dst, src, cpy);
icculus@10575
   329
        SDL_memcpy(last_sample, src, cpy);
icculus@10575
   330
        src -= channels;
icculus@10575
   331
        dst -= channels;
icculus@3021
   332
    }
icculus@3021
   333
icculus@3021
   334
    cvt->len_cvt = dstsize;
icculus@3021
   335
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   336
        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
icculus@3021
   337
    }
icculus@3021
   338
}
icculus@3021
   339
icculus@10575
   340
void
icculus@10575
   341
SDL_Upsample_x4(SDL_AudioCVT *cvt, const int channels)
icculus@3021
   342
{
icculus@10575
   343
    const int dstsize = cvt->len_cvt * 4;
icculus@10575
   344
    float *dst = ((float *) (cvt->buf + dstsize)) - (channels * 4);
icculus@10575
   345
    const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - channels;
icculus@10575
   346
    const float *target = ((const float *) cvt->buf);
icculus@10575
   347
    const size_t cpy = sizeof (float) * channels;
icculus@10575
   348
    float last_sample[8];
icculus@10575
   349
    int i;
icculus@10575
   350
slouken@3032
   351
#if DEBUG_CONVERT
icculus@10575
   352
    fprintf(stderr, "Upsample (x4), %d channels.\n", channels);
icculus@3021
   353
#endif
icculus@3021
   354
icculus@10575
   355
    SDL_assert(channels <= 8);
icculus@10575
   356
    SDL_memcpy(last_sample, src, cpy);
icculus@10575
   357
slouken@6194
   358
    while (dst >= target) {
icculus@10575
   359
        for (i = 0; i < channels; i++) {
icculus@10575
   360
            dst[i] = (float) ((((double) src[i]) + (3.0 * ((double) last_sample[i]))) * 0.25);
icculus@10575
   361
        }
icculus@10575
   362
        dst -= channels;
icculus@10575
   363
        for (i = 0; i < channels; i++) {
icculus@10575
   364
            dst[i] = (float) ((((double) src[i]) + ((double) last_sample[i])) * 0.25);
icculus@10575
   365
        }
icculus@10575
   366
        dst -= channels;
icculus@10575
   367
        for (i = 0; i < channels; i++) {
icculus@10575
   368
            dst[i] = (float) (((3.0 * ((double) src[i])) + ((double) last_sample[i])) * 0.25);
icculus@10575
   369
        }
icculus@10575
   370
        dst -= channels;
icculus@10575
   371
        SDL_memcpy(dst, src, cpy);
icculus@10575
   372
        dst -= channels;
icculus@10575
   373
        SDL_memcpy(last_sample, src, cpy);
icculus@10575
   374
        src -= channels;
icculus@3021
   375
    }
icculus@3021
   376
icculus@3021
   377
    cvt->len_cvt = dstsize;
icculus@3021
   378
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   379
        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
icculus@3021
   380
    }
icculus@3021
   381
}
icculus@3021
   382
icculus@10575
   383
void
icculus@10575
   384
SDL_Downsample_Multiple(SDL_AudioCVT *cvt, const int multiple, const int channels)
icculus@3021
   385
{
icculus@10575
   386
    const int dstsize = cvt->len_cvt / multiple;
icculus@10575
   387
    float *dst = (float *) cvt->buf;
icculus@10575
   388
    const float *src = (float *) cvt->buf;
icculus@10575
   389
    const float *target = (const float *) (cvt->buf + dstsize);
icculus@10575
   390
    const size_t cpy = sizeof (float) * channels;
icculus@10575
   391
    float last_sample[8];
icculus@10575
   392
    int i;
icculus@10575
   393
slouken@3032
   394
#if DEBUG_CONVERT
icculus@10575
   395
    fprintf(stderr, "Downsample (x%d), %d channels.\n", multiple, channels);
icculus@3021
   396
#endif
icculus@3021
   397
icculus@10575
   398
    SDL_assert(channels <= 8);
icculus@10575
   399
    SDL_memcpy(last_sample, src, cpy);
icculus@10575
   400
icculus@3602
   401
    while (dst < target) {
icculus@10575
   402
        for (i = 0; i < channels; i++) {
icculus@10575
   403
            dst[i] = (float) ((((double)src[i]) + ((double)last_sample[i])) * 0.5);
icculus@10575
   404
        }
icculus@10575
   405
        dst += channels;
icculus@10575
   406
icculus@10575
   407
        SDL_memcpy(last_sample, src, cpy);
icculus@10575
   408
        src += (channels * multiple);
icculus@3021
   409
    }
icculus@3021
   410
icculus@3021
   411
    cvt->len_cvt = dstsize;
icculus@3021
   412
    if (cvt->filters[++cvt->filter_index]) {
icculus@10575
   413
        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
icculus@3021
   414
    }
icculus@3021
   415
}
icculus@3021
   416
slouken@1985
   417
/* vi: set ts=4 sw=4 expandtab: */