[pulseaudio-discuss] [PATCH 10/13] loopback: Added a deadband to reduce rate hunting

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


With USB or Bluetooth sources, the controller exhibited random
deviations of new_rate around the correct value, due to latency jitter.
Use the already-known latency error due to jitter, and assume that there
is no latency difference if the difference is below that error margin.
---
 src/modules/module-loopback.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index b733663..6b48fc6 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -183,12 +183,12 @@ static void teardown(struct userdata *u) {
 /* rate controller
  * - maximum deviation from base rate is less than 1%
  * - can create audible artifacts by changing the rate too quickly
- * - exhibits hunting with USB or Bluetooth sources
+ * - deadband to handle error of latency measurement
  */
 static uint32_t rate_controller(
                 uint32_t base_rate,
                 pa_usec_t adjust_time,
-                int32_t latency_difference_usec) {
+                int32_t latency_difference_usec, pa_usec_t latency_error_usec) {
 
     uint32_t new_rate;
     double min_cycles;
@@ -198,6 +198,10 @@ static uint32_t rate_controller(
     min_cycles = (double)abs(latency_difference_usec) / adjust_time / 0.0095 + 1;
     new_rate = base_rate * (1.0 + (double)latency_difference_usec / min_cycles / adjust_time);
 
+    /* Adjust as good as physics allows (with some safety margin) */
+    if (abs(latency_difference_usec) <= 2.5 * latency_error_usec + adjust_time / 2 / base_rate + 100)
+       new_rate = base_rate;
+
     return new_rate;
 }
 
@@ -276,7 +280,7 @@ static void adjust_rates(struct userdata *u) {
     u->source_sink_changed = false;
 
     /* Calculate new rate */
-    new_rate = rate_controller(base_rate, u->adjust_time, latency_difference);
+    new_rate = rate_controller(base_rate, u->adjust_time, latency_difference, u->latency_error * final_latency);
 
     /* Predictor */
     u->next_latency = (corrected_latency * base_rate + (int32_t)(base_rate - new_rate) * (int64_t)u->adjust_time) / new_rate;
-- 
2.1.4



More information about the pulseaudio-discuss mailing list