From f29d14fcc841643151af41117a556a55b0a665ff Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 22 Mar 2019 16:48:35 +0100 Subject: [PATCH] resample: Let the resampler object handle all channels Move the code to loop over all channels in the resampler itself. This is better because the resampler can reuse its state for each channel. --- spa/plugins/audioconvert/resample-peaks-sse.h | 64 +++++++++++-------- spa/plugins/audioconvert/resample-peaks.h | 46 +++++++------ spa/plugins/audioconvert/resample-speex.h | 20 ++++-- spa/plugins/audioconvert/resample.c | 26 ++++---- spa/plugins/audioconvert/resample.h | 5 +- 5 files changed, 97 insertions(+), 64 deletions(-) diff --git a/spa/plugins/audioconvert/resample-peaks-sse.h b/spa/plugins/audioconvert/resample-peaks-sse.h index 9994d1abe..4d416c942 100644 --- a/spa/plugins/audioconvert/resample-peaks-sse.h +++ b/spa/plugins/audioconvert/resample-peaks-sse.h @@ -35,47 +35,57 @@ static inline float hmax_ps(__m128 val) return _mm_cvtss_f32(val); } -static void impl_peaks_process_sse(struct resample *r, int channel, - void *src, uint32_t *in_len, void *dst, uint32_t *out_len) +static void impl_peaks_process_sse(struct resample *r, + const void * SPA_RESTRICT src[], uint32_t *in_len, + void * SPA_RESTRICT dst[], uint32_t *out_len) { struct peaks_data *pd = r->data; - float *s = src, *d = dst, m; - uint32_t i, o, end, chunk, unrolled; + uint32_t c, i, o, end, chunk, unrolled, i_count, o_count; __m128 in, max, mask = _mm_andnot_ps(_mm_set_ps1(-0.0f), _mm_cmpeq_ps(_mm_setzero_ps(), _mm_setzero_ps())); - o = i = 0; + if (r->channels == 0) + return; - m = pd->max_f[channel]; - max = _mm_set1_ps(m); + for (c = 0; c < r->channels; c++) { + const float *s = src[c]; + float *d = dst[c], m = pd->max_f[c]; - while (i < *in_len && o < *out_len) { - end = ((uint64_t) (pd->o_count + 1) * r->i_rate) / r->o_rate; - end = end > pd->i_count ? end - pd->i_count : 0; - chunk = SPA_MIN(end, *in_len); + o_count = pd->o_count; + i_count = pd->i_count; + o = i = 0; - unrolled = chunk - ((chunk - i) & 3); + max = _mm_set1_ps(m); - for (; i < unrolled; i+=4) { - in = _mm_loadu_ps(&s[i]); - in = _mm_and_ps(mask, in); - max = _mm_max_ps(in, max); - } - for (; i < chunk; i++) - m = SPA_MAX(fabsf(s[i]), m); - - if (i == end) { - d[o++] = SPA_MAX(hmax_ps(max), m); - m = 0.0f; - max = _mm_set1_ps(m); - pd->o_count++; + while (i < *in_len && o < *out_len) { + end = ((uint64_t) (o_count + 1) * r->i_rate) / r->o_rate; + end = end > i_count ? end - i_count : 0; + chunk = SPA_MIN(end, *in_len); + + unrolled = chunk - ((chunk - i) & 3); + + for (; i < unrolled; i+=4) { + in = _mm_loadu_ps(&s[i]); + in = _mm_and_ps(mask, in); + max = _mm_max_ps(in, max); + } + for (; i < chunk; i++) + m = SPA_MAX(fabsf(s[i]), m); + + if (i == end) { + d[o++] = SPA_MAX(hmax_ps(max), m); + m = 0.0f; + max = _mm_set1_ps(m); + o_count++; + } } + pd->max_f[c] = SPA_MAX(hmax_ps(max), m); } - pd->max_f[channel] = SPA_MAX(hmax_ps(max), m); *out_len = o; *in_len = i; - pd->i_count += i; + pd->o_count = o_count; + pd->i_count = i_count + i; while (pd->i_count >= r->i_rate) { pd->i_count -= r->i_rate; diff --git a/spa/plugins/audioconvert/resample-peaks.h b/spa/plugins/audioconvert/resample-peaks.h index ea5c353e7..f9ced5a95 100644 --- a/spa/plugins/audioconvert/resample-peaks.h +++ b/spa/plugins/audioconvert/resample-peaks.h @@ -44,35 +44,45 @@ static void impl_peaks_update_rate(struct resample *r, double rate) { } -static void impl_peaks_process(struct resample *r, int channel, - void *src, uint32_t *in_len, void *dst, uint32_t *out_len) +static void impl_peaks_process(struct resample *r, + const void * SPA_RESTRICT src[], uint32_t *in_len, + void * SPA_RESTRICT dst[], uint32_t *out_len) { struct peaks_data *pd = r->data; - float *s = src, *d = dst, m; - uint32_t i, o, end, chunk; + uint32_t c, i, o, end, chunk, o_count, i_count; - o = i = 0; - m = pd->max_f[channel]; + if (r->channels == 0) + return; - while (i < *in_len && o < *out_len) { - end = ((uint64_t) (pd->o_count + 1) * r->i_rate) / r->o_rate; - end = end > pd->i_count ? end - pd->i_count : 0; - chunk = SPA_MIN(end, *in_len); + for (c = 0; c < r->channels; c++) { + const float *s = src[c]; + float *d = dst[c], m = pd->max_f[c]; - for (; i < chunk; i++) - m = SPA_MAX(fabsf(s[i]), m); + o_count = pd->o_count; + i_count = pd->i_count; + o = i = 0; - if (i == end) { - d[o++] = m; - m = 0.0f; - pd->o_count++; + while (i < *in_len && o < *out_len) { + end = ((uint64_t) (o_count + 1) * r->i_rate) / r->o_rate; + end = end > i_count ? end - i_count : 0; + chunk = SPA_MIN(end, *in_len); + + for (; i < chunk; i++) + m = SPA_MAX(fabsf(s[i]), m); + + if (i == end) { + d[o++] = m; + m = 0.0f; + o_count++; + } } + pd->max_f[c] = m; } - pd->max_f[channel] = m; *out_len = o; *in_len = i; - pd->i_count += i; + pd->o_count = o_count; + pd->i_count = i_count + i; while (pd->i_count >= r->i_rate) { pd->i_count -= r->i_rate; diff --git a/spa/plugins/audioconvert/resample-speex.h b/spa/plugins/audioconvert/resample-speex.h index 4a2e30911..8e924e959 100644 --- a/spa/plugins/audioconvert/resample-speex.h +++ b/spa/plugins/audioconvert/resample-speex.h @@ -37,16 +37,26 @@ static void impl_speex_update_rate(struct resample *r, double rate) r->i_rate * rate, r->o_rate, r->i_rate, r->o_rate); } -static void impl_speex_process(struct resample *r, int channel, - void *src, uint32_t *in_len, void *dst, uint32_t *out_len) +static void impl_speex_process(struct resample *r, + const void *SPA_RESTRICT src[], uint32_t *in_len, + void * SPA_RESTRICT dst[], uint32_t *out_len) { + uint32_t c, i, o; + if (r->i_rate == r->o_rate) { - *out_len = *in_len = SPA_MIN(*in_len, *out_len); - spa_memcpy(dst, src, *out_len * sizeof(float)); + o = i = SPA_MIN(*in_len, *out_len); + for (c = 0; c < r->channels; c++) + spa_memcpy(dst[c], src[c], o * sizeof(float)); } else { - speex_resampler_process_float(r->data, channel, src, in_len, dst, out_len); + for (c = 0; c < r->channels; c++) { + i = *in_len; + o = *out_len; + speex_resampler_process_float(r->data, c, src[c], &i, dst[c], &o); + } } + *in_len = i; + *out_len = o; } static void impl_speex_reset (struct resample *r) diff --git a/spa/plugins/audioconvert/resample.c b/spa/plugins/audioconvert/resample.c index c2876ba66..0c930be5c 100644 --- a/spa/plugins/audioconvert/resample.c +++ b/spa/plugins/audioconvert/resample.c @@ -730,6 +730,8 @@ static int impl_node_process(struct spa_node *node) struct spa_buffer *sb, *db; uint32_t i, size, in_len, out_len, pin_len, pout_len, maxsize; int res = 0; + const void **src_datas; + void **dst_datas; spa_return_val_if_fail(node != NULL, -EINVAL); @@ -781,23 +783,23 @@ static int impl_node_process(struct spa_node *node) pin_len = in_len = (size - inport->offset) / sizeof(float); pout_len = out_len = (maxsize - outport->offset) / sizeof(float); - for (i = 0; i < sb->n_datas; i++) { - void *src, *dst; + src_datas = alloca(sizeof(void*) * this->resample.channels); + dst_datas = alloca(sizeof(void*) * this->resample.channels); - in_len = pin_len; - out_len = pout_len; + for (i = 0; i < sb->n_datas; i++) + src_datas[i] = SPA_MEMBER(sb->datas[i].data, inport->offset, void); + for (i = 0; i < db->n_datas; i++) + dst_datas[i] = SPA_MEMBER(db->datas[i].data, outport->offset, void); - src = SPA_MEMBER(sb->datas[i].data, inport->offset, void); - dst = SPA_MEMBER(db->datas[i].data, outport->offset, void); + resample_process(&this->resample, src_datas, &in_len, dst_datas, &out_len); - resample_process(&this->resample, i, src, &in_len, dst, &out_len); + spa_log_trace_fp(this->log, NAME " %p: in %d/%d %ld %d out %d/%d %ld %d", + this, pin_len, in_len, size / sizeof(float), inport->offset, + pout_len, out_len, maxsize / sizeof(float), outport->offset); - spa_log_trace_fp(this->log, NAME " %p: in %d/%d %ld %d out %d/%d %ld %d", - this, pin_len, in_len, size / sizeof(float), inport->offset, - pout_len, out_len, maxsize / sizeof(float), outport->offset); - - db->datas[i].chunk->offset = 0; + for (i = 0; i < db->n_datas; i++) { db->datas[i].chunk->size = outport->offset + (out_len * sizeof(float)); + db->datas[i].chunk->offset = 0; } inport->offset += in_len * sizeof(float); diff --git a/spa/plugins/audioconvert/resample.h b/spa/plugins/audioconvert/resample.h index 0333b031a..96d738c7e 100644 --- a/spa/plugins/audioconvert/resample.h +++ b/spa/plugins/audioconvert/resample.h @@ -32,8 +32,9 @@ struct resample { void (*free) (struct resample *r); void (*update_rate) (struct resample *r, double rate); - void (*process) (struct resample *r, int channel, - void *src, uint32_t *in_len, void *dst, uint32_t *out_len); + void (*process) (struct resample *r, + const void * SPA_RESTRICT src[], uint32_t *in_len, + void * SPA_RESTRICT dst[], uint32_t *out_len); void (*reset) (struct resample *r); void *data; };