audio: Replaced older resamplers in SDL_AudioCVT with the new ones.
authorRyan C. Gordon <icculus@icculus.org>
Mon, 09 Jan 2017 06:00:58 -0500
changeset 10799234f71894a52
parent 10798 1af225fe35cc
child 10800 f3439b0eb486
audio: Replaced older resamplers in SDL_AudioCVT with the new ones.
src/audio/SDL_audio_c.h
src/audio/SDL_audiocvt.c
src/audio/SDL_audiotypecvt.c
     1.1 --- a/src/audio/SDL_audio_c.h	Mon Jan 09 05:59:30 2017 -0500
     1.2 +++ b/src/audio/SDL_audio_c.h	Mon Jan 09 06:00:58 2017 -0500
     1.3 @@ -63,10 +63,6 @@
     1.4  void SDLCALL SDL_Convert_F32_to_S16(SDL_AudioCVT *cvt, SDL_AudioFormat format);
     1.5  void SDLCALL SDL_Convert_F32_to_U16(SDL_AudioCVT *cvt, SDL_AudioFormat format);
     1.6  void SDLCALL SDL_Convert_F32_to_S32(SDL_AudioCVT *cvt, SDL_AudioFormat format);
     1.7 -void SDL_Upsample_Arbitrary(SDL_AudioCVT *cvt, const int channels);
     1.8 -void SDL_Upsample_Multiple(SDL_AudioCVT *cvt, const int channels);
     1.9 -void SDL_Downsample_Arbitrary(SDL_AudioCVT *cvt, const int channels);
    1.10 -void SDL_Downsample_Multiple(SDL_AudioCVT *cvt, const int channels);
    1.11  
    1.12  
    1.13  /* SDL_AudioStream is a new audio conversion interface. It
     2.1 --- a/src/audio/SDL_audiocvt.c	Mon Jan 09 05:59:30 2017 -0500
     2.2 +++ b/src/audio/SDL_audiocvt.c	Mon Jan 09 06:00:58 2017 -0500
     2.3 @@ -191,6 +191,38 @@
     2.4      }
     2.5  }
     2.6  
     2.7 +static int
     2.8 +SDL_ResampleAudioSimple(const int chans, const double rate_incr,
     2.9 +                        float *last_sample, const float *inbuf,
    2.10 +                        const int inbuflen, float *outbuf, const int outbuflen)
    2.11 +{
    2.12 +    const int framelen = chans * sizeof(float);
    2.13 +    const int total = (inbuflen / framelen);
    2.14 +    const int finalpos = total - chans;
    2.15 +    const double src_incr = 1.0 / rate_incr;
    2.16 +    double idx = 0.0;
    2.17 +    float *dst = outbuf;
    2.18 +    int consumed = 0;
    2.19 +    int i;
    2.20 +
    2.21 +    SDL_assert((inbuflen % framelen) == 0);
    2.22 +
    2.23 +    while (consumed < total) {
    2.24 +        const int pos = ((int)idx) * chans;
    2.25 +        const float *src = &inbuf[(pos >= finalpos) ? finalpos : pos];
    2.26 +        SDL_assert(dst < (outbuf + (outbuflen / framelen)));
    2.27 +        for (i = 0; i < chans; i++) {
    2.28 +            const float val = *(src++);
    2.29 +            *(dst++) = (val + last_sample[i]) * 0.5f;
    2.30 +            last_sample[i] = val;
    2.31 +        }
    2.32 +        consumed = pos + chans;
    2.33 +        idx += src_incr;
    2.34 +    }
    2.35 +
    2.36 +    return (int)((dst - outbuf) * sizeof(float));
    2.37 +}
    2.38 +
    2.39  
    2.40  int
    2.41  SDL_ConvertAudio(SDL_AudioCVT * cvt)
    2.42 @@ -338,31 +370,75 @@
    2.43      return retval;
    2.44  }
    2.45  
    2.46 +static void
    2.47 +SDL_ResampleCVT(SDL_AudioCVT *cvt, const int chans, const SDL_AudioFormat format)
    2.48 +{
    2.49 +    const float *src = (const float *) cvt->buf;
    2.50 +    const int srclen = cvt->len_cvt;
    2.51 +    float *dst = (float *) (cvt->buf + srclen);
    2.52 +    const int dstlen = (cvt->len * cvt->len_mult) - srclen;
    2.53 +    SDL_bool do_simple = SDL_TRUE;
    2.54  
    2.55 -/* !!! FIXME: We only have this macro salsa because SDL_AudioCVT doesn't store
    2.56 -   !!! FIXME:  channel info or integer sample rates, so we have to have
    2.57 -   !!! FIXME:  function entry points for each supported channel count and
    2.58 -   !!! FIXME:  multiple vs arbitrary. When we rev the ABI, remove this. */
    2.59 +    SDL_assert(format == AUDIO_F32SYS);
    2.60 +
    2.61 +#ifdef HAVE_LIBSAMPLERATE_H
    2.62 +    if (SRC_available) {
    2.63 +        int result = 0;
    2.64 +        SRC_STATE *state = SRC_src_new(SRC_SINC_FASTEST, chans, &result);
    2.65 +        if (state) {
    2.66 +            const int framelen = sizeof(float) * chans;
    2.67 +            SRC_DATA data;
    2.68 +
    2.69 +            data.data_in = (float *)src; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */
    2.70 +            data.input_frames = srclen / framelen;
    2.71 +            data.input_frames_used = 0;
    2.72 +
    2.73 +            data.data_out = dst;
    2.74 +            data.output_frames = dstlen / framelen;
    2.75 +
    2.76 +            data.end_of_input = 0;
    2.77 +            data.src_ratio = cvt->rate_incr;
    2.78 +
    2.79 +            result = SRC_src_process(state, &data);
    2.80 +            SDL_assert(result == 0);  /* what to do if this fails? Can it fail? */
    2.81 +
    2.82 +            /* What to do if this fails...? */
    2.83 +            SDL_assert(data.input_frames_used == data.input_frames);
    2.84 +
    2.85 +            SRC_src_delete(state);
    2.86 +            cvt->len_cvt = data.output_frames_gen * (sizeof(float) * chans);
    2.87 +            do_simple = SDL_FALSE;
    2.88 +        }
    2.89 +
    2.90 +        /* failed to create state? Fall back to simple method. */
    2.91 +    }
    2.92 +#endif
    2.93 +
    2.94 +    if (do_simple) {
    2.95 +        float state[8];
    2.96 +        int i;
    2.97 +
    2.98 +        for (i = 0; i < chans; i++) {
    2.99 +            state[i] = src[i];
   2.100 +        }
   2.101 +
   2.102 +        cvt->len_cvt = SDL_ResampleAudioSimple(chans, cvt->rate_incr, state, src, srclen, dst, dstlen);
   2.103 +    }
   2.104 +
   2.105 +    SDL_memcpy(cvt->buf, dst, cvt->len_cvt);
   2.106 +    if (cvt->filters[++cvt->filter_index]) {
   2.107 +        cvt->filters[cvt->filter_index](cvt, format);
   2.108 +    }
   2.109 +}
   2.110 +
   2.111 +/* !!! FIXME: We only have this macro salsa because SDL_AudioCVT doesn't
   2.112 +   !!! FIXME:  store channel info, so we have to have function entry
   2.113 +   !!! FIXME:  points for each supported channel count and multiple
   2.114 +   !!! FIXME:  vs arbitrary. When we rev the ABI, clean this up. */
   2.115  #define RESAMPLER_FUNCS(chans) \
   2.116      static void SDLCALL \
   2.117 -    SDL_Upsample_Multiple_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
   2.118 -        SDL_assert(format == AUDIO_F32SYS); \
   2.119 -        SDL_Upsample_Multiple(cvt, chans); \
   2.120 -    } \
   2.121 -    static void SDLCALL \
   2.122 -    SDL_Upsample_Arbitrary_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
   2.123 -        SDL_assert(format == AUDIO_F32SYS); \
   2.124 -        SDL_Upsample_Arbitrary(cvt, chans); \
   2.125 -    }\
   2.126 -    static void SDLCALL \
   2.127 -    SDL_Downsample_Multiple_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
   2.128 -        SDL_assert(format == AUDIO_F32SYS); \
   2.129 -        SDL_Downsample_Multiple(cvt, chans); \
   2.130 -    } \
   2.131 -    static void SDLCALL \
   2.132 -    SDL_Downsample_Arbitrary_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
   2.133 -        SDL_assert(format == AUDIO_F32SYS); \
   2.134 -        SDL_Downsample_Arbitrary(cvt, chans); \
   2.135 +    SDL_ResampleCVT_c##chans(SDL_AudioCVT *cvt, SDL_AudioFormat format) { \
   2.136 +        SDL_ResampleCVT(cvt, chans, format); \
   2.137      }
   2.138  RESAMPLER_FUNCS(1)
   2.139  RESAMPLER_FUNCS(2)
   2.140 @@ -371,62 +447,19 @@
   2.141  RESAMPLER_FUNCS(8)
   2.142  #undef RESAMPLER_FUNCS
   2.143  
   2.144 -static int
   2.145 -SDL_FindFrequencyMultiple(const int src_rate, const int dst_rate)
   2.146 +static SDL_AudioFilter
   2.147 +ChooseCVTResampler(const int dst_channels)
   2.148  {
   2.149 -    int lo, hi;
   2.150 -
   2.151 -    SDL_assert(src_rate != 0);
   2.152 -    SDL_assert(dst_rate != 0);
   2.153 -    SDL_assert(src_rate != dst_rate);
   2.154 -
   2.155 -    if (src_rate < dst_rate) {
   2.156 -        lo = src_rate;
   2.157 -        hi = dst_rate;
   2.158 -    } else {
   2.159 -        lo = dst_rate;
   2.160 -        hi = src_rate;
   2.161 +    switch (dst_channels) {
   2.162 +        case 1: return SDL_ResampleCVT_c1;
   2.163 +        case 2: return SDL_ResampleCVT_c2;
   2.164 +        case 4: return SDL_ResampleCVT_c4;
   2.165 +        case 6: return SDL_ResampleCVT_c6;
   2.166 +        case 8: return SDL_ResampleCVT_c8;
   2.167 +        default: break;
   2.168      }
   2.169  
   2.170 -    if ((hi % lo) != 0)
   2.171 -        return 0;               /* not a multiple. */
   2.172 -
   2.173 -    return hi / lo;
   2.174 -}
   2.175 -
   2.176 -static SDL_AudioFilter
   2.177 -ChooseResampler(const int dst_channels, const int src_rate, const int dst_rate)
   2.178 -{
   2.179 -    const int upsample = (src_rate < dst_rate) ? 1 : 0;
   2.180 -    const int multiple = SDL_FindFrequencyMultiple(src_rate, dst_rate);
   2.181 -    SDL_AudioFilter filter = NULL;
   2.182 -
   2.183 -    #define PICK_CHANNEL_FILTER(upordown, resampler) switch (dst_channels) { \
   2.184 -        case 1: filter = SDL_##upordown##_##resampler##_c1; break; \
   2.185 -        case 2: filter = SDL_##upordown##_##resampler##_c2; break; \
   2.186 -        case 4: filter = SDL_##upordown##_##resampler##_c4; break; \
   2.187 -        case 6: filter = SDL_##upordown##_##resampler##_c6; break; \
   2.188 -        case 8: filter = SDL_##upordown##_##resampler##_c8; break; \
   2.189 -        default: break; \
   2.190 -    }
   2.191 -
   2.192 -    if (upsample) {
   2.193 -        if (multiple) {
   2.194 -            PICK_CHANNEL_FILTER(Upsample, Multiple);
   2.195 -        } else {
   2.196 -            PICK_CHANNEL_FILTER(Upsample, Arbitrary);
   2.197 -        }
   2.198 -    } else {
   2.199 -        if (multiple) {
   2.200 -            PICK_CHANNEL_FILTER(Downsample, Multiple);
   2.201 -        } else {
   2.202 -            PICK_CHANNEL_FILTER(Downsample, Arbitrary);
   2.203 -        }
   2.204 -    }
   2.205 -
   2.206 -    #undef PICK_CHANNEL_FILTER
   2.207 -
   2.208 -    return filter;
   2.209 +    return NULL;
   2.210  }
   2.211  
   2.212  static int
   2.213 @@ -439,7 +472,7 @@
   2.214          return 0;  /* no conversion necessary. */
   2.215      }
   2.216  
   2.217 -    filter = ChooseResampler(dst_channels, src_rate, dst_rate);
   2.218 +    filter = ChooseCVTResampler(dst_channels);
   2.219      if (filter == NULL) {
   2.220          return SDL_SetError("No conversion available for these rates");
   2.221      }
   2.222 @@ -454,6 +487,10 @@
   2.223          cvt->len_ratio /= ((double) src_rate) / ((double) dst_rate);
   2.224      }
   2.225  
   2.226 +    /* the buffer is big enough to hold the destination now, but
   2.227 +       we need it large enough to hold a separate scratch buffer. */
   2.228 +    cvt->len_mult *= 2;
   2.229 +
   2.230      return 1;               /* added a converter. */
   2.231  }
   2.232  
   2.233 @@ -638,16 +675,17 @@
   2.234  static int
   2.235  SDL_ResampleAudioStream_SRC(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
   2.236  {
   2.237 +    const int framelen = sizeof(float) * stream->pre_resample_channels;
   2.238      SRC_STATE *state = (SRC_STATE *)stream->resampler_state;
   2.239      SRC_DATA data;
   2.240      int result;
   2.241  
   2.242      data.data_in = (float *)inbuf; /* Older versions of libsamplerate had a non-const pointer, but didn't write to it */
   2.243 -    data.input_frames = inbuflen / ( sizeof(float) * stream->pre_resample_channels );
   2.244 +    data.input_frames = inbuflen / framelen;
   2.245      data.input_frames_used = 0;
   2.246  
   2.247      data.data_out = outbuf;
   2.248 -    data.output_frames = outbuflen / (sizeof(float) * stream->pre_resample_channels);
   2.249 +    data.output_frames = outbuflen / framelen;
   2.250  
   2.251      data.end_of_input = 0;
   2.252      data.src_ratio = stream->rate_incr;
   2.253 @@ -721,51 +759,20 @@
   2.254  static int
   2.255  SDL_ResampleAudioStream(SDL_AudioStream *stream, const float *inbuf, const int inbuflen, float *outbuf, const int outbuflen)
   2.256  {
   2.257 -    /* !!! FIXME: this resampler sucks, but not much worse than our usual resampler.  :)  */  /* ... :( */
   2.258      SDL_AudioStreamResamplerState *state = (SDL_AudioStreamResamplerState*)stream->resampler_state;
   2.259      const int chans = (int)stream->pre_resample_channels;
   2.260 -    const int framelen = chans * sizeof(float);
   2.261 -    const int total = (inbuflen / framelen);
   2.262 -    const int finalpos = total - chans;
   2.263 -    const double src_incr = 1.0 / stream->rate_incr;
   2.264 -    double idx = 0.0;
   2.265 -    float *dst = outbuf;
   2.266 -    float last_sample[SDL_arraysize(state->resampler_state)];
   2.267 -    int consumed = 0;
   2.268 -    int i;
   2.269  
   2.270 -    SDL_assert(chans <= SDL_arraysize(last_sample));
   2.271 -    SDL_assert((inbuflen % framelen) == 0);
   2.272 +    SDL_assert(chans <= SDL_arraysize(state->resampler_state));
   2.273  
   2.274      if (!state->resampler_seeded) {
   2.275 +        int i;
   2.276          for (i = 0; i < chans; i++) {
   2.277              state->resampler_state[i] = inbuf[i];
   2.278          }
   2.279          state->resampler_seeded = SDL_TRUE;
   2.280      }
   2.281  
   2.282 -    for (i = 0; i < chans; i++) {
   2.283 -        last_sample[i] = state->resampler_state[i];
   2.284 -    }
   2.285 -
   2.286 -    while (consumed < total) {
   2.287 -        const int pos = ((int)idx) * chans;
   2.288 -        const float *src = &inbuf[(pos >= finalpos) ? finalpos : pos];
   2.289 -        SDL_assert(dst < (outbuf + (outbuflen / framelen)));
   2.290 -        for (i = 0; i < chans; i++) {
   2.291 -            const float val = *(src++);
   2.292 -            *(dst++) = (val + last_sample[i]) * 0.5f;
   2.293 -            last_sample[i] = val;
   2.294 -        }
   2.295 -        consumed = pos + chans;
   2.296 -        idx += src_incr;
   2.297 -    }
   2.298 -
   2.299 -    for (i = 0; i < chans; i++) {
   2.300 -        state->resampler_state[i] = last_sample[i];
   2.301 -    }
   2.302 -
   2.303 -    return (int)((dst - outbuf) * sizeof(float));
   2.304 +    return SDL_ResampleAudioSimple(chans, stream->rate_incr, state->resampler_state, inbuf, inbuflen, outbuf, outbuflen);
   2.305  }
   2.306  
   2.307  static void
     3.1 --- a/src/audio/SDL_audiotypecvt.c	Mon Jan 09 05:59:30 2017 -0500
     3.2 +++ b/src/audio/SDL_audiotypecvt.c	Mon Jan 09 06:00:58 2017 -0500
     3.3 @@ -216,177 +216,4 @@
     3.4      }
     3.5  }
     3.6  
     3.7 -void
     3.8 -SDL_Upsample_Arbitrary(SDL_AudioCVT *cvt, const int channels)
     3.9 -{
    3.10 -    const int srcsize = cvt->len_cvt - (64 * channels);
    3.11 -    const int dstsize = (int) ((((double)(cvt->len_cvt/(channels*4))) * cvt->rate_incr)) * (channels*4);
    3.12 -    register int eps = 0;
    3.13 -    float *dst = ((float *) (cvt->buf + dstsize)) - channels;
    3.14 -    const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - channels;
    3.15 -    const float *target = ((const float *) cvt->buf);
    3.16 -    const size_t cpy = sizeof (float) * channels;
    3.17 -    float sample[8];
    3.18 -    float last_sample[8];
    3.19 -    int i;
    3.20 -
    3.21 -#if DEBUG_CONVERT
    3.22 -    fprintf(stderr, "Upsample arbitrary (x%f), %d channels.\n", cvt->rate_incr, channels);
    3.23 -#endif
    3.24 -
    3.25 -    SDL_assert(channels <= 8);
    3.26 -
    3.27 -    for (i = 0; i < channels; i++) {
    3.28 -        sample[i] = (float) ((((double) src[i]) + ((double) src[i - channels])) * 0.5);
    3.29 -    }
    3.30 -    SDL_memcpy(last_sample, src, cpy);
    3.31 -
    3.32 -    while (dst > target) {
    3.33 -        SDL_memcpy(dst, sample, cpy);
    3.34 -        dst -= channels;
    3.35 -        eps += srcsize;
    3.36 -        if ((eps << 1) >= dstsize) {
    3.37 -            if (src > target) {
    3.38 -                src -= channels;
    3.39 -                for (i = 0; i < channels; i++) {
    3.40 -                    sample[i] = (float) ((((double) src[i]) + ((double) last_sample[i])) * 0.5);
    3.41 -                }
    3.42 -            } else {
    3.43 -
    3.44 -            }
    3.45 -            SDL_memcpy(last_sample, src, cpy);
    3.46 -            eps -= dstsize;
    3.47 -        }
    3.48 -    }
    3.49 -
    3.50 -    cvt->len_cvt = dstsize;
    3.51 -    if (cvt->filters[++cvt->filter_index]) {
    3.52 -        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
    3.53 -    }
    3.54 -}
    3.55 -
    3.56 -void
    3.57 -SDL_Downsample_Arbitrary(SDL_AudioCVT *cvt, const int channels)
    3.58 -{
    3.59 -    const int srcsize = cvt->len_cvt - (64 * channels);
    3.60 -    const int dstsize = (int) (((double)(cvt->len_cvt/(channels*4))) * cvt->rate_incr) * (channels*4);
    3.61 -    register int eps = 0;
    3.62 -    float *dst = (float *) cvt->buf;
    3.63 -    const float *src = (float *) cvt->buf;
    3.64 -    const float *target = (const float *) (cvt->buf + dstsize);
    3.65 -    const size_t cpy = sizeof (float) * channels;
    3.66 -    float last_sample[8];
    3.67 -    float sample[8];
    3.68 -    int i;
    3.69 -
    3.70 -#if DEBUG_CONVERT
    3.71 -    fprintf(stderr, "Downsample arbitrary (x%f), %d channels.\n", cvt->rate_incr, channels);
    3.72 -#endif
    3.73 -
    3.74 -    SDL_assert(channels <= 8);
    3.75 -
    3.76 -    SDL_memcpy(sample, src, cpy);
    3.77 -    SDL_memcpy(last_sample, src, cpy);
    3.78 -
    3.79 -    while (dst < target) {
    3.80 -        src += channels;
    3.81 -        eps += dstsize;
    3.82 -        if ((eps << 1) >= srcsize) {
    3.83 -            SDL_memcpy(dst, sample, cpy);
    3.84 -            dst += channels;
    3.85 -            for (i = 0; i < channels; i++) {
    3.86 -                sample[i] = (float) ((((double) src[i]) + ((double) last_sample[i])) * 0.5);
    3.87 -            }
    3.88 -            SDL_memcpy(last_sample, src, cpy);
    3.89 -            eps -= srcsize;
    3.90 -        }
    3.91 -    }
    3.92 -
    3.93 -    cvt->len_cvt = dstsize;
    3.94 -    if (cvt->filters[++cvt->filter_index]) {
    3.95 -        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
    3.96 -    }
    3.97 -}
    3.98 -
    3.99 -void
   3.100 -SDL_Upsample_Multiple(SDL_AudioCVT *cvt, const int channels)
   3.101 -{
   3.102 -    const int multiple = (int) cvt->rate_incr;
   3.103 -    const int dstsize = cvt->len_cvt * multiple;
   3.104 -    float *buf = (float *) cvt->buf;
   3.105 -    float *dst = ((float *) (cvt->buf + dstsize)) - channels;
   3.106 -    const float *src = ((float *) (cvt->buf + cvt->len_cvt)) - channels;
   3.107 -    const float *target = buf + channels;
   3.108 -    const size_t cpy = sizeof (float) * channels;
   3.109 -    float last_sample[8];
   3.110 -    int i;
   3.111 -
   3.112 -#if DEBUG_CONVERT
   3.113 -    fprintf(stderr, "Upsample (x%d), %d channels.\n", multiple, channels);
   3.114 -#endif
   3.115 -
   3.116 -    SDL_assert(channels <= 8);
   3.117 -
   3.118 -    SDL_memcpy(last_sample, src, cpy);
   3.119 -
   3.120 -    while (dst > target) {
   3.121 -        SDL_assert(src >= buf);
   3.122 -
   3.123 -        for (i = 0; i < channels; i++) {
   3.124 -            dst[i] = (float) ((((double)src[i]) + ((double)last_sample[i])) * 0.5);
   3.125 -        }
   3.126 -        dst -= channels;
   3.127 -
   3.128 -        for (i = 1; i < multiple; i++) {
   3.129 -            SDL_memcpy(dst, dst + channels, cpy);
   3.130 -            dst -= channels;
   3.131 -        }
   3.132 -
   3.133 -        src -= channels;
   3.134 -        if (src > buf) {
   3.135 -            SDL_memcpy(last_sample, src - channels, cpy);
   3.136 -        }
   3.137 -    }
   3.138 -
   3.139 -    cvt->len_cvt = dstsize;
   3.140 -    if (cvt->filters[++cvt->filter_index]) {
   3.141 -        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
   3.142 -    }
   3.143 -}
   3.144 -
   3.145 -void
   3.146 -SDL_Downsample_Multiple(SDL_AudioCVT *cvt, const int channels)
   3.147 -{
   3.148 -    const int multiple = (int) (1.0 / cvt->rate_incr);
   3.149 -    const int dstsize = cvt->len_cvt / multiple;
   3.150 -    float *dst = (float *) cvt->buf;
   3.151 -    const float *src = (float *) cvt->buf;
   3.152 -    const float *target = (const float *) (cvt->buf + dstsize);
   3.153 -    const size_t cpy = sizeof (float) * channels;
   3.154 -    float last_sample[8];
   3.155 -    int i;
   3.156 -
   3.157 -#if DEBUG_CONVERT
   3.158 -    fprintf(stderr, "Downsample (x%d), %d channels.\n", multiple, channels);
   3.159 -#endif
   3.160 -
   3.161 -    SDL_assert(channels <= 8);
   3.162 -    SDL_memcpy(last_sample, src, cpy);
   3.163 -
   3.164 -    while (dst < target) {
   3.165 -        for (i = 0; i < channels; i++) {
   3.166 -            dst[i] = (float) ((((double)src[i]) + ((double)last_sample[i])) * 0.5);
   3.167 -        }
   3.168 -        dst += channels;
   3.169 -
   3.170 -        SDL_memcpy(last_sample, src, cpy);
   3.171 -        src += (channels * multiple);
   3.172 -    }
   3.173 -
   3.174 -    cvt->len_cvt = dstsize;
   3.175 -    if (cvt->filters[++cvt->filter_index]) {
   3.176 -        cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
   3.177 -    }
   3.178 -}
   3.179 -
   3.180  /* vi: set ts=4 sw=4 expandtab: */