resamplers: Rework the peaks resampler

The algorithm had been implemented the same way as the trivial resampler.  But
an important difference between the two is that the trivial resampler can write
an output as soon as the first corresponding input sample is seen, whereas the
peaks resampler must have read all input samples before writing an output
sample.

With this rework, the peaks resampler now outputs samples correctly when the
input data is spanning multiple memblocks.
This commit is contained in:
Maarten Bosmans 2011-11-02 21:54:16 +01:00 committed by Colin Guthrie
parent ae179d7321
commit 115d903ab7

View file

@ -1443,9 +1443,9 @@ static int trivial_init(pa_resampler*r) {
static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
size_t fz; size_t fz;
unsigned o_index; unsigned c, o_index = 0;
unsigned i, i_end = 0;
void *src, *dst; void *src, *dst;
unsigned start = 0;
pa_assert(r); pa_assert(r);
pa_assert(input); pa_assert(input);
@ -1457,25 +1457,20 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index; src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
dst = (uint8_t*) pa_memblock_acquire(output->memblock) + output->index; dst = (uint8_t*) pa_memblock_acquire(output->memblock) + output->index;
for (o_index = 0;; o_index++, r->peaks.o_counter++) { i = ((r->peaks.o_counter * r->i_ss.rate) / r->o_ss.rate);
unsigned j; i = i > r->peaks.i_counter ? i - r->peaks.i_counter : 0;
j = ((r->peaks.o_counter * r->i_ss.rate) / r->o_ss.rate); while (i_end < in_n_frames) {
i_end = (((r->peaks.o_counter+1) * r->i_ss.rate) / r->o_ss.rate);
if (j > r->peaks.i_counter) i_end = i_end > r->peaks.i_counter ? i_end - r->peaks.i_counter : 0;
j -= r->peaks.i_counter;
else
j = 0;
pa_assert(o_index * fz < pa_memblock_get_length(output->memblock)); pa_assert(o_index * fz < pa_memblock_get_length(output->memblock));
if (r->work_format == PA_SAMPLE_S16NE) { if (r->work_format == PA_SAMPLE_S16NE) {
unsigned i, c; int16_t *s = (int16_t*) ((uint8_t*) src + fz * i);
int16_t *s = (int16_t*) ((uint8_t*) src + fz * start);
int16_t *d = (int16_t*) ((uint8_t*) dst + fz * o_index); int16_t *d = (int16_t*) ((uint8_t*) dst + fz * o_index);
for (i = start; i <= j && i < in_n_frames; i++) for (; i < i_end && i < in_n_frames; i++)
for (c = 0; c < r->o_ss.channels; c++, s++) { for (c = 0; c < r->o_ss.channels; c++, s++) {
int16_t n; int16_t n;
@ -1485,22 +1480,20 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
r->peaks.max_i[c] = n; r->peaks.max_i[c] = n;
} }
if (i >= in_n_frames) if (i == i_end) {
break; for (c = 0; c < r->o_ss.channels; c++, d++) {
*d = r->peaks.max_i[c];
for (c = 0; c < r->o_ss.channels; c++, d++) { r->peaks.max_i[c] = 0;
*d = r->peaks.max_i[c]; }
r->peaks.max_i[c] = 0; o_index++, r->peaks.o_counter++;
} }
} else { } else {
unsigned i, c; float *s = (float*) ((uint8_t*) src + fz * i);
float *s = (float*) ((uint8_t*) src + fz * start);
float *d = (float*) ((uint8_t*) dst + fz * o_index); float *d = (float*) ((uint8_t*) dst + fz * o_index);
pa_assert(r->work_format == PA_SAMPLE_FLOAT32NE); pa_assert(r->work_format == PA_SAMPLE_FLOAT32NE);
for (i = start; i <= j && i < in_n_frames; i++) for (; i < i_end && i < in_n_frames; i++)
for (c = 0; c < r->o_ss.channels; c++, s++) { for (c = 0; c < r->o_ss.channels; c++, s++) {
float n = fabsf(*s); float n = fabsf(*s);
@ -1508,16 +1501,14 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
r->peaks.max_f[c] = n; r->peaks.max_f[c] = n;
} }
if (i >= in_n_frames) if (i == i_end) {
break; for (c = 0; c < r->o_ss.channels; c++, d++) {
*d = r->peaks.max_f[c];
for (c = 0; c < r->o_ss.channels; c++, d++) { r->peaks.max_f[c] = 0;
*d = r->peaks.max_f[c]; }
r->peaks.max_f[c] = 0; o_index++, r->peaks.o_counter++;
} }
} }
start = j;
} }
pa_memblock_release(input->memblock); pa_memblock_release(input->memblock);