[pulseaudio-discuss] [PATCH v6 20/25] loopback: Add latency prediction and Kalman filter

Tanu Kaskinen tanuk at iki.fi
Wed Aug 24 19:12:42 UTC 2016


On Sun, 2016-06-05 at 21:05 +0200, Georg Chini wrote:
> @@ -261,6 +267,7 @@ static void adjust_rates(struct userdata *u) {
>      int32_t latency_difference;
>      pa_usec_t current_buffer_latency, snapshot_delay, current_source_sink_latency, current_latency, latency_at_optimum_rate;
>      pa_usec_t final_latency;
> +    double filtered_latency, current_latency_error, latency_correction, base_rate_with_drift;
>  
>      pa_assert(u);
>      pa_assert_ctl_context();
> @@ -321,6 +328,23 @@ static void adjust_rates(struct userdata *u) {
>      final_latency = PA_MAX(u->latency, u->minimum_latency + u->extra_latency);
>      latency_difference = (int32_t)((int64_t)current_latency - final_latency);
>  
> +    /* Do not filter or calculate error if source or sink changed or if there was an underrun */
> +    if (u->source_sink_changed || u->underrun_occured) {
> +        /* Initial conditions are very unsure, so use a high variance */
> +        u->kalman_variance = 10000000;

Should u->latency_variance be reset too?

> +        filtered_latency = latency_at_optimum_rate;
> +        u->next_latency_at_optimum_rate_with_drift = latency_at_optimum_rate;
> +        u->next_latency_with_drift = current_latency;
> +
> +    } else {
> +        /* Low pass filtered latency variance */
> +        current_latency_error = (double)abs((int32_t)(latency_at_optimum_rate - u->next_latency_at_optimum_rate_with_drift));

The (int32_t) cast should be applied to the individual terms, not to
the result of the substraction.

> @@ -338,6 +362,30 @@ static void adjust_rates(struct userdata *u) {
>      u->source_sink_changed = false;
>      u->underrun_occured = false;
>  
> +    /* Predicton of next latency */
> +
> +    /* Evaluate optimum rate */
> +    base_rate_with_drift = u->drift_compensation_rate + base_rate;
> +
> +    /* Latency correction on next iteration */
> +    latency_correction = (base_rate_with_drift - new_rate) * (int64_t)u->real_adjust_time / new_rate;
> +
> +    if ((int)new_rate != (int)base_rate_with_drift || new_rate != old_rate) {

new_rate is already an integer, no need to cast it.

-- 
Tanu


More information about the pulseaudio-discuss mailing list