mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-31 22:25:35 -04:00
Fix noisy output of dmix with two periods
Fixed the noisy output of dmix with two (or less) periods. The dmix tends to give noise or XRUN when running with two periods because of its implementation nature. To avoid this, the start position is aligned to the period size, so that the updates are synced with interrupts of slave PCM.
This commit is contained in:
parent
1a9c520529
commit
09c5db44a4
2 changed files with 23 additions and 6 deletions
|
|
@ -713,8 +713,11 @@ int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
int changed;
|
int changed;
|
||||||
do {
|
do {
|
||||||
changed = 0;
|
changed = 0;
|
||||||
|
/* Set min/max size to [2:1024] since INT_MAX as the
|
||||||
|
* upper-limit results in a too big buffer on some apps.
|
||||||
|
*/
|
||||||
err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_PERIODS,
|
err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_PERIODS,
|
||||||
2, INT_MAX);
|
2, 1024);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
changed |= err;
|
changed |= err;
|
||||||
|
|
|
||||||
|
|
@ -484,21 +484,35 @@ static int snd_pcm_dmix_prepare(snd_pcm_t *pcm)
|
||||||
return snd_pcm_direct_set_timer_params(dmix);
|
return snd_pcm_direct_set_timer_params(dmix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix)
|
||||||
|
{
|
||||||
|
dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
|
||||||
|
if (! dmix->variable_buffer_size ||
|
||||||
|
pcm->buffer_size > pcm->period_size * 2)
|
||||||
|
return;
|
||||||
|
/* If we have too litte periods, better to align the start position
|
||||||
|
* to the period boundary so that the interrupt can be handled properly
|
||||||
|
* at the right time.
|
||||||
|
*/
|
||||||
|
dmix->slave_appl_ptr = ((dmix->slave_appl_ptr + dmix->slave_period_size - 1)
|
||||||
|
/ dmix->slave_period_size) * dmix->slave_period_size;
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_dmix_reset(snd_pcm_t *pcm)
|
static int snd_pcm_dmix_reset(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_direct_t *dmix = pcm->private_data;
|
snd_pcm_direct_t *dmix = pcm->private_data;
|
||||||
dmix->hw_ptr %= pcm->period_size;
|
dmix->hw_ptr %= pcm->period_size;
|
||||||
dmix->appl_ptr = dmix->last_appl_ptr = dmix->hw_ptr;
|
dmix->appl_ptr = dmix->last_appl_ptr = dmix->hw_ptr;
|
||||||
dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
|
reset_slave_ptr(pcm, dmix);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_dmix_start_timer(snd_pcm_direct_t *dmix)
|
static int snd_pcm_dmix_start_timer(snd_pcm_t *pcm, snd_pcm_direct_t *dmix)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
snd_pcm_hwsync(dmix->spcm);
|
snd_pcm_hwsync(dmix->spcm);
|
||||||
dmix->slave_appl_ptr = dmix->slave_hw_ptr = *dmix->spcm->hw.ptr;
|
reset_slave_ptr(pcm, dmix);
|
||||||
err = snd_timer_start(dmix->timer);
|
err = snd_timer_start(dmix->timer);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -521,7 +535,7 @@ static int snd_pcm_dmix_start(snd_pcm_t *pcm)
|
||||||
else if (avail < 0)
|
else if (avail < 0)
|
||||||
return 0;
|
return 0;
|
||||||
else {
|
else {
|
||||||
if ((err = snd_pcm_dmix_start_timer(dmix)) < 0)
|
if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
|
||||||
return err;
|
return err;
|
||||||
snd_pcm_dmix_sync_area(pcm);
|
snd_pcm_dmix_sync_area(pcm);
|
||||||
}
|
}
|
||||||
|
|
@ -664,7 +678,7 @@ static snd_pcm_sframes_t snd_pcm_dmix_mmap_commit(snd_pcm_t *pcm,
|
||||||
return 0;
|
return 0;
|
||||||
snd_pcm_mmap_appl_forward(pcm, size);
|
snd_pcm_mmap_appl_forward(pcm, size);
|
||||||
if (dmix->state == STATE_RUN_PENDING) {
|
if (dmix->state == STATE_RUN_PENDING) {
|
||||||
if ((err = snd_pcm_dmix_start_timer(dmix)) < 0)
|
if ((err = snd_pcm_dmix_start_timer(pcm, dmix)) < 0)
|
||||||
return err;
|
return err;
|
||||||
} else if (dmix->state == SND_PCM_STATE_RUNNING ||
|
} else if (dmix->state == SND_PCM_STATE_RUNNING ||
|
||||||
dmix->state == SND_PCM_STATE_DRAINING)
|
dmix->state == SND_PCM_STATE_DRAINING)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue