mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-12-16 08:56:42 -05: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)
|
#define DIV (1<<16)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
int init;
|
||||||
int16_t sample;
|
int16_t sample;
|
||||||
int sum;
|
int sum;
|
||||||
unsigned int pos;
|
unsigned int pos;
|
||||||
|
|
@ -69,6 +70,22 @@ typedef struct {
|
||||||
snd_pcm_rate_state_t *states;
|
snd_pcm_rate_state_t *states;
|
||||||
} snd_pcm_rate_t;
|
} 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,
|
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,
|
snd_pcm_uframes_t dst_offset, snd_pcm_uframes_t *dst_framesp,
|
||||||
const snd_pcm_channel_area_t *src_areas,
|
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);
|
dst_step = snd_pcm_channel_area_step(dst_area);
|
||||||
src_frames1 = 0;
|
src_frames1 = 0;
|
||||||
dst_frames1 = 0;
|
dst_frames1 = 0;
|
||||||
|
if (states->init) {
|
||||||
|
old_sample = initial_sample(src, getidx);
|
||||||
|
states->init = 0;
|
||||||
|
}
|
||||||
while (dst_frames1 < dst_frames) {
|
while (dst_frames1 < dst_frames) {
|
||||||
if (pos >= get_threshold) {
|
if (pos >= get_threshold) {
|
||||||
int16_t new_sample;
|
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;
|
int src_step, dst_step;
|
||||||
sum = states->sum;
|
sum = states->sum;
|
||||||
pos = states->pos;
|
pos = states->pos;
|
||||||
|
states->init = 0;
|
||||||
src = snd_pcm_channel_area_addr(src_area, src_offset);
|
src = snd_pcm_channel_area_addr(src_area, src_offset);
|
||||||
dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
|
dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
|
||||||
src_step = snd_pcm_channel_area_step(src_area);
|
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;
|
snd_pcm_rate_t *rate = pcm->private_data;
|
||||||
if (rate->states) {
|
if (rate->states) {
|
||||||
free(rate->states);
|
free(rate->states);
|
||||||
rate->states = 0;
|
rate->states = NULL;
|
||||||
}
|
}
|
||||||
return snd_pcm_hw_free(rate->plug.slave);
|
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)
|
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_rate_t *rate = pcm->private_data;
|
||||||
snd_pcm_t *slave = rate->plug.slave;
|
snd_pcm_t *slave = rate->plug.slave;
|
||||||
snd_pcm_sw_params_t sparams;
|
snd_pcm_sw_params_t sparams;
|
||||||
sparams = *params;
|
sparams = *params;
|
||||||
sparams.avail_min = muldiv_near(sparams.avail_min, slave->rate, pcm->rate);
|
recalc(pcm, &sparams.avail_min);
|
||||||
sparams.xfer_align = muldiv_near(sparams.xfer_align, slave->rate, pcm->rate);
|
recalc(pcm, &sparams.xfer_align);
|
||||||
sparams.silence_threshold = muldiv_near(sparams.silence_threshold, slave->rate, pcm->rate);
|
recalc(pcm, &sparams.start_threshold);
|
||||||
sparams.silence_size = muldiv_near(sparams.silence_size, slave->rate, pcm->rate);
|
recalc(pcm, &sparams.stop_threshold);
|
||||||
sparams.start_threshold = muldiv_near(sparams.start_threshold, slave->rate, pcm->rate);
|
recalc(pcm, &sparams.silence_threshold);
|
||||||
sparams.stop_threshold = muldiv_near(sparams.stop_threshold, slave->rate, pcm->rate);
|
recalc(pcm, &sparams.silence_size);
|
||||||
return snd_pcm_sw_params(slave, &sparams);
|
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) {
|
for (k = 0; k < pcm->channels; ++k) {
|
||||||
rate->states[k].sum = 0;
|
rate->states[k].sum = 0;
|
||||||
rate->states[k].sample = 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue