From 22bd1c328a2a3a4ea0b2cac7922f0c0c9037603a Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 11 Mar 2002 14:59:11 +0000 Subject: [PATCH] Added proper initialization for expand, added corrections for sw_params (checks for period_size and buffer_size) --- src/pcm/pcm_rate.c | 61 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index f1f55324..8d1f11bf 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -41,6 +41,7 @@ const char *_snd_module_pcm_rate = ""; #define DIV (1<<16) typedef struct { + int init; int16_t sample; int sum; unsigned int pos; @@ -69,6 +70,22 @@ typedef struct { snd_pcm_rate_state_t *states; } snd_pcm_rate_t; +static int16_t initial_sample(const char *src, unsigned int getidx) +{ +#define GET16_LABELS +#include "plugin_ops.h" +#undef GET16_LABELS + void *get = get16_labels[getidx]; + int sample = 0; + + goto *get; +#define GET16_END after_get +#include "plugin_ops.h" +#undef GET16_END + after_get: + return sample; +} + static snd_pcm_uframes_t snd_pcm_rate_expand(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset, snd_pcm_uframes_t *dst_framesp, const snd_pcm_channel_area_t *src_areas, @@ -108,6 +125,10 @@ static snd_pcm_uframes_t snd_pcm_rate_expand(const snd_pcm_channel_area_t *dst_a dst_step = snd_pcm_channel_area_step(dst_area); src_frames1 = 0; dst_frames1 = 0; + if (states->init) { + old_sample = initial_sample(src, getidx); + states->init = 0; + } while (dst_frames1 < dst_frames) { if (pos >= get_threshold) { int16_t new_sample; @@ -178,6 +199,7 @@ static snd_pcm_uframes_t snd_pcm_rate_shrink(const snd_pcm_channel_area_t *dst_a int src_step, dst_step; sum = states->sum; pos = states->pos; + states->init = 0; src = snd_pcm_channel_area_addr(src_area, src_offset); dst = snd_pcm_channel_area_addr(dst_area, dst_offset); src_step = snd_pcm_channel_area_step(src_area); @@ -382,23 +404,40 @@ static int snd_pcm_rate_hw_free(snd_pcm_t *pcm) snd_pcm_rate_t *rate = pcm->private_data; if (rate->states) { free(rate->states); - rate->states = 0; + rate->states = NULL; } return snd_pcm_hw_free(rate->plug.slave); } +static void recalc(snd_pcm_t *pcm, snd_pcm_uframes_t *val) +{ + snd_pcm_rate_t *rate = pcm->private_data; + snd_pcm_t *slave = rate->plug.slave; + unsigned long div; + + if (*val == pcm->buffer_size) { + *val = slave->buffer_size; + } else { + div = *val / pcm->period_size; + if (div * pcm->period_size == *val) + *val = div * slave->period_size; + else + *val = muldiv_near(*val, slave->rate, pcm->rate); + } +} + static int snd_pcm_rate_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) { snd_pcm_rate_t *rate = pcm->private_data; snd_pcm_t *slave = rate->plug.slave; snd_pcm_sw_params_t sparams; sparams = *params; - sparams.avail_min = muldiv_near(sparams.avail_min, slave->rate, pcm->rate); - sparams.xfer_align = muldiv_near(sparams.xfer_align, slave->rate, pcm->rate); - sparams.silence_threshold = muldiv_near(sparams.silence_threshold, slave->rate, pcm->rate); - sparams.silence_size = muldiv_near(sparams.silence_size, slave->rate, pcm->rate); - sparams.start_threshold = muldiv_near(sparams.start_threshold, slave->rate, pcm->rate); - sparams.stop_threshold = muldiv_near(sparams.stop_threshold, slave->rate, pcm->rate); + recalc(pcm, &sparams.avail_min); + recalc(pcm, &sparams.xfer_align); + recalc(pcm, &sparams.start_threshold); + recalc(pcm, &sparams.stop_threshold); + recalc(pcm, &sparams.silence_threshold); + recalc(pcm, &sparams.silence_size); return snd_pcm_sw_params(slave, &sparams); } @@ -409,12 +448,8 @@ static int snd_pcm_rate_init(snd_pcm_t *pcm) for (k = 0; k < pcm->channels; ++k) { rate->states[k].sum = 0; rate->states[k].sample = 0; - if (rate->func == snd_pcm_rate_expand) { - /* Get a sample on entry */ - rate->states[k].pos = rate->pitch; - } else { - rate->states[k].pos = 0; - } + rate->states[k].pos = 0; + rate->states[k].init = 0; } return 0; } -- 2.47.1