[pulseaudio-discuss] [PATCH 09/13] loopback: Track the amount of jitter

Georg Chini georg at chini.tk
Wed Feb 25 10:43:21 PST 2015


---
 src/modules/module-loopback.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index cbd0ac9..b733663 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -95,6 +95,8 @@ struct userdata {
 
     pa_usec_t source_latency_sum;
     pa_usec_t sink_latency_sum;
+    pa_usec_t next_latency;
+    double latency_error;
 
     bool in_pop;
     bool pop_called;
@@ -263,15 +265,22 @@ static void adjust_rates(struct userdata *u) {
                 (double) current_latency / PA_USEC_PER_MSEC,
                 (double) corrected_latency / PA_USEC_PER_MSEC,
                 ((double) u->latency_snapshot.sink_latency + current_buffer_latency + u->latency_snapshot.source_latency) / PA_USEC_PER_MSEC);
-    pa_log_debug("Latency difference: %0.2f ms, rate difference: %i Hz",
+    pa_log_debug("Latency difference: %0.2f ± %0.2f ms, rate difference: %i Hz",
                 (double) latency_difference / PA_USEC_PER_MSEC,
+                (double) 2.5 * u->latency_error * final_latency / PA_USEC_PER_MSEC,
                 (int32_t)(old_rate - base_rate));
 
+    /* Low pass filtered difference between expectation value and observed latency */
+    if (!u->source_sink_changed)
+        u->latency_error = (4 * u->latency_error + (double)abs((int32_t)(current_latency - u->next_latency)) / final_latency) / 5;
     u->source_sink_changed = false;
 
     /* Calculate new rate */
     new_rate = rate_controller(base_rate, u->adjust_time, latency_difference);
 
+    /* Predictor */
+    u->next_latency = (corrected_latency * base_rate + (int32_t)(base_rate - new_rate) * (int64_t)u->adjust_time) / new_rate;
+
     /* Set rate */
     pa_sink_input_set_rate(u->sink_input, new_rate);
     pa_log_debug("[%s] Updated sampling rate to %lu Hz.", u->sink_input->sink->name, (unsigned long) new_rate);
@@ -551,6 +560,8 @@ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
        sink_latency = PA_CLIP_SUB(sink_latency, pa_source_get_latency(dest));
     memblockq_adjust(u, sink_latency, true);
 
+    u->latency_error = 400.0 / get_requested_latency(u);
+
     if (pa_source_get_state(dest) == PA_SOURCE_SUSPENDED)
         pa_sink_input_cork(u->sink_input, true);
     else
@@ -868,6 +879,8 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
        source_latency += pa_bytes_to_usec(u->send_counter - u->recv_counter, &u->sink_input->sample_spec);
     memblockq_adjust(u, source_latency, true);
 
+    u->latency_error = 400.0 / get_requested_latency(u);
+
     if (pa_sink_get_state(dest) == PA_SINK_SUSPENDED)
         pa_source_output_cork(u->source_output, true);
     else
@@ -1191,6 +1204,9 @@ int pa__init(pa_module *m) {
     else
         memblockq_adjust(u, (int32_t)(-u->configured_sink_latency / 4), true);
 
+    /* Initialize latency error (allow at least 1 ms latency offset) */
+    u->latency_error = 400.0 / get_requested_latency(u);
+
     u->asyncmsgq = pa_asyncmsgq_new(0);
 
     if (!pa_proplist_contains(u->source_output->proplist, PA_PROP_MEDIA_NAME))
-- 
2.1.4



More information about the pulseaudio-discuss mailing list