mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Added proper initialization for expand, added corrections for sw_params (checks for period_size and buffer_size)
This commit is contained in:
parent
c31a3bff06
commit
22bd1c328a
1 changed files with 48 additions and 13 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue