From dad07f960b59caa413d84acedea2e17668cf09de Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 23 Jan 2017 16:45:50 -0500 Subject: [PATCH] audio: Resampler now special-cases stereo and mono processing. Turns out that iterating from 0 to channels-1 was a serious performance hit! These cases now tend to match or beat the original audio resampler's speed! --- src/audio/SDL_audiocvt.c | 126 +++++++++++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 30 deletions(-) diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index 178791782..09ea91b89 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -249,49 +249,115 @@ SDL_ResampleAudioSimple(const int chans, const double rate_incr, SDL_assert((dest_samples * framelen) <= outbuflen); SDL_assert((inbuflen % framelen) == 0); - if (rate_incr > 1.0) { + if (rate_incr > 1.0) { /* upsample */ float *target = (outbuf + chans); - const float *earlier_sample = &inbuf[finalpos]; - float final_sample[8]; dst = outbuf + (dest_samples * chans); idx = (double) total; - /* save this off so we can correctly maintain state between runs. */ - SDL_memcpy(final_sample, &inbuf[finalpos], framelen); - - while (dst > target) { - const int pos = ((int) idx) * chans; - const float *src = &inbuf[pos]; - SDL_assert(pos >= 0.0); - for (i = chans - 1; i >= 0; i--) { + if (chans == 1) { + const float final_sample = inbuf[finalpos]; + float earlier_sample = inbuf[finalpos]; + while (dst > target) { + const int pos = ((int) idx) * chans; + const float *src = &inbuf[pos]; const float val = *(--src); - *(--dst) = (val + earlier_sample[i]) * 0.5f; + SDL_assert(pos >= 0.0); + *(--dst) = (val + earlier_sample) * 0.5f; + earlier_sample = val; + idx -= src_incr; } - earlier_sample = src; - idx -= src_incr; + /* do last sample, interpolated against previous run's state. */ + *(--dst) = (inbuf[0] + last_sample[0]) * 0.5f; + *last_sample = final_sample; + } else if (chans == 2) { + const float final_sample2 = inbuf[finalpos+1]; + const float final_sample1 = inbuf[finalpos]; + float earlier_sample2 = inbuf[finalpos]; + float earlier_sample1 = inbuf[finalpos-1]; + while (dst > target) { + const int pos = ((int) idx) * chans; + const float *src = &inbuf[pos]; + const float val2 = *(--src); + const float val1 = *(--src); + SDL_assert(pos >= 0.0); + *(--dst) = (val2 + earlier_sample2) * 0.5f; + *(--dst) = (val1 + earlier_sample1) * 0.5f; + earlier_sample2 = val2; + earlier_sample1 = val1; + idx -= src_incr; + } + /* do last sample, interpolated against previous run's state. */ + *(--dst) = (inbuf[1] + last_sample[1]) * 0.5f; + *(--dst) = (inbuf[0] + last_sample[0]) * 0.5f; + last_sample[1] = final_sample2; + last_sample[0] = final_sample1; + } else { + const float *earlier_sample = &inbuf[finalpos]; + float final_sample[8]; + SDL_memcpy(final_sample, &inbuf[finalpos], framelen); + while (dst > target) { + const int pos = ((int) idx) * chans; + const float *src = &inbuf[pos]; + SDL_assert(pos >= 0.0); + for (i = chans - 1; i >= 0; i--) { + const float val = *(--src); + *(--dst) = (val + earlier_sample[i]) * 0.5f; + } + earlier_sample = src; + idx -= src_incr; + } + /* do last sample, interpolated against previous run's state. */ + for (i = chans - 1; i >= 0; i--) { + const float val = inbuf[i]; + *(--dst) = (val + last_sample[i]) * 0.5f; + } + SDL_memcpy(last_sample, final_sample, framelen); } - /* do last sample, interpolated against previous run's state. */ - for (i = chans - 1; i >= 0; i--) { - const float val = inbuf[i]; - *(--dst) = (val + last_sample[i]) * 0.5f; - } - SDL_memcpy(last_sample, final_sample, framelen); dst = (outbuf + (dest_samples * chans)) - 1; - } else { + } else { /* downsample */ float *target = (outbuf + (dest_samples * chans)); dst = outbuf; idx = 0.0; - while (dst < target) { - const int pos = ((int) idx) * chans; - const float *src = &inbuf[pos]; - SDL_assert(pos <= finalpos); - for (i = 0; i < chans; i++) { - const float val = *(src++); - *(dst++) = (val + last_sample[i]) * 0.5f; - last_sample[i] = val; + if (chans == 1) { + float last = *last_sample; + while (dst < target) { + const int pos = ((int) idx) * chans; + const float val = inbuf[pos]; + SDL_assert(pos <= finalpos); + *(dst++) = (val + last) * 0.5f; + last = val; + idx += src_incr; + } + *last_sample = last; + } else if (chans == 2) { + float last1 = last_sample[0]; + float last2 = last_sample[1]; + while (dst < target) { + const int pos = ((int) idx) * chans; + const float val1 = inbuf[pos]; + const float val2 = inbuf[pos+1]; + SDL_assert(pos <= finalpos); + *(dst++) = (val1 + last1) * 0.5f; + *(dst++) = (val2 + last2) * 0.5f; + last1 = val1; + last2 = val2; + idx += src_incr; + } + last_sample[0] = last1; + last_sample[1] = last2; + } else { + while (dst < target) { + const int pos = ((int) idx) * chans; + const float *src = &inbuf[pos]; + SDL_assert(pos <= finalpos); + for (i = 0; i < chans; i++) { + const float val = *(src++); + *(dst++) = (val + last_sample[i]) * 0.5f; + last_sample[i] = val; + } + idx += src_incr; } - idx += src_incr; } }