size_t resample_buf_size;
size_t from_work_format_buf_size;
- /* points to buffer before resampling stage, remap */
+ /* points to buffer before resampling stage, remap or to_work */
pa_memchunk *leftover_buf;
size_t *leftover_buf_size;
- /* have_leftover points to leftover_in_remap */
+ /* have_leftover points to leftover_in_remap or leftover_in_to_work */
bool *have_leftover;
bool leftover_in_remap;
+ bool leftover_in_to_work;
pa_sample_format_t work_format;
uint8_t work_channels;
const uint32_t rate_a,
const uint32_t rate_b) {
- pa_assert(rate_a > 0 && rate_a <= PA_RATE_MAX);
- pa_assert(rate_b > 0 && rate_b <= PA_RATE_MAX);
+ pa_assert(pa_sample_rate_valid(rate_a));
+ pa_assert(pa_sample_rate_valid(rate_b));
pa_assert(method >= 0);
pa_assert(method < PA_RESAMPLER_MAX);
pa_init_remap(m);
}
-static size_t fit_buf(pa_resampler *r, pa_memchunk *buf, size_t size) {
- if (!buf->memblock || size < buf->length) {
- size = buf->length;
- if (buf->memblock)
+/* check if buf's memblock is large enough to hold 'len' bytes; create a
+ * new memblock if necessary and optionally preserve 'copy' data bytes */
+static void fit_buf(pa_resampler *r, pa_memchunk *buf, size_t len, size_t *size, size_t copy) {
+ pa_assert(size);
+
+ if (!buf->memblock || len > *size) {
+ pa_memblock *new_block = pa_memblock_new(r->mempool, len);
+
+ if (buf->memblock) {
+ if (copy > 0) {
+ void *src = pa_memblock_acquire(buf->memblock);
+ void *dst = pa_memblock_acquire(new_block);
+ pa_assert(copy <= len);
+ memcpy(dst, src, copy);
+ pa_memblock_release(new_block);
+ pa_memblock_release(buf->memblock);
+ }
+
pa_memblock_unref(buf->memblock);
+ }
- buf->memblock = pa_memblock_new(r->mempool, size);
+ buf->memblock = new_block;
+ *size = len;
}
- return size;
+
+ buf->length = len;
}
static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) {
- unsigned n_samples;
+ unsigned in_n_samples, out_n_samples;
void *src, *dst;
+ bool have_leftover;
+ size_t leftover_length = 0;
pa_assert(r);
pa_assert(input);
pa_assert(input->memblock);
/* Convert the incoming sample into the work sample format and place them
- * in to_work_format_buf. */
+ * in to_work_format_buf. The leftover data is already converted, so it's
+ * part of the output buffer. */
+
+ have_leftover = r->leftover_in_to_work;
+ r->leftover_in_to_work = false;
- if (!r->to_work_format_func || !input->length)
+ if (!have_leftover && (!r->to_work_format_func || !input->length))
return input;
+ else if (input->length <= 0)
+ return &r->to_work_format_buf;
- n_samples = (unsigned) ((input->length / r->i_fz) * r->i_ss.channels);
+ in_n_samples = out_n_samples = (unsigned) ((input->length / r->i_fz) * r->i_ss.channels);
- r->to_work_format_buf.length = r->w_sz * n_samples;
- r->to_work_format_buf_size = fit_buf(r, &r->to_work_format_buf, r->to_work_format_buf_size);
+ if (have_leftover) {
+ leftover_length = r->to_work_format_buf.length;
+ out_n_samples += (unsigned) (leftover_length / r->w_sz);
+ }
+
+ fit_buf(r, &r->to_work_format_buf, r->w_sz * out_n_samples, &r->to_work_format_buf_size, leftover_length);
src = pa_memblock_acquire_chunk(input);
- dst = pa_memblock_acquire(r->to_work_format_buf.memblock);
+ dst = (uint8_t *) pa_memblock_acquire(r->to_work_format_buf.memblock) + leftover_length;
- r->to_work_format_func(n_samples, src, dst);
+ if (r->to_work_format_func)
+ r->to_work_format_func(in_n_samples, src, dst);
+ else
+ memcpy(dst, src, input->length);
pa_memblock_release(input->memblock);
pa_memblock_release(r->to_work_format_buf.memblock);
}
out_n_samples = out_n_frames * r->o_ss.channels;
- r->remap_buf.length = out_n_samples * r->w_sz;
-
- if (have_leftover) {
- if (r->remap_buf_size < r->remap_buf.length) {
- pa_memblock *new_block = pa_memblock_new(r->mempool, r->remap_buf.length);
-
- src = pa_memblock_acquire(r->remap_buf.memblock);
- dst = pa_memblock_acquire(new_block);
- memcpy(dst, src, leftover_length);
- pa_memblock_release(r->remap_buf.memblock);
- pa_memblock_release(new_block);
-
- pa_memblock_unref(r->remap_buf.memblock);
- r->remap_buf.memblock = new_block;
- r->remap_buf_size = r->remap_buf.length;
- }
- } else
- r->remap_buf_size = fit_buf(r, &r->remap_buf, r->remap_buf_size);
+ fit_buf(r, &r->remap_buf, out_n_samples * r->w_sz, &r->remap_buf_size, leftover_length);
src = pa_memblock_acquire_chunk(input);
dst = (uint8_t *) pa_memblock_acquire(r->remap_buf.memblock) + leftover_length;
pa_assert(len > 0);
/* Store the leftover data. */
- r->leftover_buf->length = len;
- *r->leftover_buf_size = fit_buf(r, r->leftover_buf, *r->leftover_buf_size);
+ fit_buf(r, r->leftover_buf, len, r->leftover_buf_size, 0);
*r->have_leftover = true;
dst = pa_memblock_acquire(r->leftover_buf->memblock);
in_n_frames = (unsigned) (input->length / r->w_fz);
out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+EXTRA_FRAMES;
-
- r->resample_buf.length = r->w_fz * out_n_frames;
- r->resample_buf_size = fit_buf(r, &r->resample_buf, r->resample_buf_size);
+ fit_buf(r, &r->resample_buf, r->w_fz * out_n_frames, &r->resample_buf_size, 0);
leftover_n_frames = r->impl.resample(r, input, in_n_frames, &r->resample_buf, &out_n_frames);
n_samples = (unsigned) (input->length / r->w_sz);
n_frames = n_samples / r->o_ss.channels;
-
- r->from_work_format_buf.length = r->o_fz * n_frames;
- r->from_work_format_buf_size = fit_buf(r, &r->from_work_format_buf, r->from_work_format_buf_size);
+ fit_buf(r, &r->from_work_format_buf, r->o_fz * n_frames, &r->from_work_format_buf_size, 0);
src = pa_memblock_acquire_chunk(input);
dst = pa_memblock_acquire(r->from_work_format_buf.memblock);