mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
alsa: dynamically adjust the DLL bandwidth
Keep a running average and variance of the error. Use this to periodically update the DLL bandwidth. When the variance gets smaller, we update the DLL more slowly to stay closer to the ideal rate. This seems to improve the rate stability.
This commit is contained in:
parent
d1efc9c2c6
commit
0db2171cd9
2 changed files with 17 additions and 5 deletions
|
|
@ -2746,7 +2746,7 @@ static int get_status(struct state *state, uint64_t current_time, snd_pcm_uframe
|
|||
static int update_time(struct state *state, uint64_t current_time, snd_pcm_sframes_t delay,
|
||||
snd_pcm_sframes_t target, bool follower)
|
||||
{
|
||||
double err, corr;
|
||||
double err, corr, avg;
|
||||
int32_t diff;
|
||||
|
||||
if (state->disable_tsched && !follower) {
|
||||
|
|
@ -2784,10 +2784,16 @@ static int update_time(struct state *state, uint64_t current_time, snd_pcm_sfram
|
|||
err = -state->max_error;
|
||||
}
|
||||
|
||||
if (!follower || state->matching)
|
||||
if (!follower || state->matching) {
|
||||
corr = spa_dll_update(&state->dll, err);
|
||||
else
|
||||
|
||||
avg = (state->err_avg * state->err_wdw + (err - state->err_avg)) / (state->err_wdw + 1.0);
|
||||
state->err_var = (state->err_var * state->err_wdw +
|
||||
(err - state->err_avg) * (err - avg)) / (state->err_wdw + 1.0);
|
||||
state->err_avg = avg;
|
||||
} else {
|
||||
corr = 1.0;
|
||||
}
|
||||
|
||||
if (diff < 0)
|
||||
state->next_time += (uint64_t)(diff / corr * 1e9 / state->rate);
|
||||
|
|
@ -2796,10 +2802,14 @@ static int update_time(struct state *state, uint64_t current_time, snd_pcm_sfram
|
|||
state->base_time = state->next_time;
|
||||
|
||||
spa_log_debug(state->log, "%s: follower:%d match:%d rate:%f "
|
||||
"bw:%f thr:%u del:%ld target:%ld err:%f max:%f",
|
||||
"bw:%f thr:%u del:%ld target:%ld err:%f max:%f var:%f:%f:%f",
|
||||
state->name, follower, state->matching,
|
||||
corr, state->dll.bw, state->threshold, delay, target,
|
||||
err, state->max_error);
|
||||
err, state->max_error, state->err_avg, state->err_var, state->err_wdw);
|
||||
|
||||
spa_dll_set_bw(&state->dll,
|
||||
SPA_CLAMPD(sqrt(state->err_var)/1000.0, 0.001, SPA_DLL_BW_MAX),
|
||||
state->threshold, state->rate);
|
||||
}
|
||||
|
||||
if (state->rate_match) {
|
||||
|
|
@ -2904,6 +2914,7 @@ static inline int check_position_config(struct state *state, bool starting)
|
|||
state->threshold = SPA_SCALE32_UP(state->driver_duration, state->rate, state->driver_rate.denom);
|
||||
state->max_error = SPA_MAX(256.0f, state->threshold / 2.0f);
|
||||
state->max_resync = SPA_MIN(state->threshold, state->max_error);
|
||||
state->err_wdw = (double)state->driver_rate.denom/state->driver_duration;
|
||||
state->resample = !state->pitch_elem &&
|
||||
(((uint32_t)state->rate != state->driver_rate.denom) || state->matching);
|
||||
state->alsa_sync = true;
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@ struct state {
|
|||
struct spa_dll dll;
|
||||
double max_error;
|
||||
double max_resync;
|
||||
double err_avg, err_var, err_wdw;
|
||||
|
||||
struct spa_latency_info latency[2];
|
||||
struct spa_process_latency_info process_latency;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue