[vlc-commits] PulseAudio: more stable resampling scheme

Rémi Denis-Courmont git at videolan.org
Sun Jul 31 21:31:42 CEST 2011


vlc/vlc-1.1 | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Jul 23 20:14:18 2011 +0300| [bc317a623a9029e2c7ca774de1c2568a03d2af0c] | committer: Rémi Denis-Courmont

PulseAudio: more stable resampling scheme

(cherry picked from commit 37d21af0eb0be93fead5b91fa63e99c01fc9994d)
(cherry picked from commit a21dd90dfd943e6ff6d04fbf8508bef01a38e22d)

Conflicts:

	modules/audio_output/pulse.c

> http://git.videolan.org/gitweb.cgi/vlc/vlc-1.1.git/?a=commit;h=bc317a623a9029e2c7ca774de1c2568a03d2af0c
---

 modules/audio_output/pulse.c |   61 ++++++++++++++++++++++++------------------
 1 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/modules/audio_output/pulse.c b/modules/audio_output/pulse.c
index 2534ae6..f9c175d 100644
--- a/modules/audio_output/pulse.c
+++ b/modules/audio_output/pulse.c
@@ -162,34 +162,41 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
     //msg_Dbg(aout, "desync: %+"PRId64" us (variation: %+"PRId64" us)",
     //        delta, change);
 
-    /* Compute playback sample rate */
-    const unsigned inrate = aout->output.output.i_rate;
-    /* NOTE: AOUT_MAX_RESAMPLING (10%) is way too high... */
-    const int limit = inrate >> 6;
-
-    if (delta < -AOUT_LATE_TOLERANCE) {
+    if (delta < -AOUT_LATE_TOLERANCE)
         msg_Warn(aout, "too late by %"PRId64" us", -delta);
-        if (change < 0)
-            delta += change; /* be more severe if really out of sync */
-    } else if (delta > +AOUT_EARLY_TOLERANCE) {
+    else if (delta > +AOUT_EARLY_TOLERANCE)
         msg_Warn(aout, "too early by %"PRId64" us", delta);
-        if (change > 0)
-            delta += change;
-    }
 
+    /* Compute playback sample rate */
+    const unsigned inrate = aout->output.output.i_rate;
+
+#define ADJUST_FACTOR 4
+#define ADJUST_MAX    1000 /* Hz (max rate variation per call) */
     /* This is empirical. Feel free to define something smarter. */
-    int outrate = inrate * delta / -(CLOCK_FREQ * 10);
-    if (16 * abs(outrate) < limit)
-        outrate = inrate; /* favor native rate to avoid resampling */
-    else if (outrate > limit)
+    int adj = sys->rate * (delta + change) / (CLOCK_FREQ * ADJUST_FACTOR);
+
+    /* This avoids too fast rate variation. They sound ugly as hell and they
+     * make the algorithm unstable (e.g. oscillation around inrate). */
+    if (adj > +ADJUST_MAX)
+        adj = +ADJUST_MAX;
+    if (adj < -ADJUST_MAX)
+        adj = -ADJUST_MAX;
+
+    unsigned outrate = sys->rate - adj;
+    /* Favor native rate to avoid resampling (FIXME: really a good idea?) */
+    if (abs(outrate - inrate) < (inrate >> 10))
+        outrate = inrate;
+
+    /* This keeps the effective rate within specified range
+     * (+/-AOUT_MAX_RESAMPLING% - see <vlc_aout.h>) of the nominal rate. */
+    const int limit = inrate * AOUT_MAX_RESAMPLING / 100;
+    if (outrate > inrate + limit)
         outrate = inrate + limit;
-    else if (outrate < -limit)
+    if (outrate < inrate - limit)
         outrate = inrate - limit;
-    else
-        outrate += inrate;
 
     /* Apply adjusted sample rate */
-    if (outrate == (int)sys->rate)
+    if (outrate == sys->rate)
         return;
     pa_operation *op = pa_stream_update_sample_rate(s, outrate, NULL, NULL);
     if (unlikely(op == NULL)) {
@@ -197,7 +204,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
         return;
     }
     pa_operation_unref(op);
-    msg_Dbg(aout, "changed sample rate to %d Hz", outrate);
+    msg_Dbg(aout, "changed sample rate to %u Hz",outrate);
     sys->rate = outrate;
 }
 
@@ -334,11 +341,13 @@ static void Play(aout_instance_t *aout)
             float *zeroes = calloc (nb, size);
 
             msg_Dbg(aout, "prepending %zu zeroes", nb);
+#if 0 /* Fault injector: add delay */
+            pa_stream_write(s, zeroes, nb * size, NULL, 0, PA_SEEK_RELATIVE);
+            pa_stream_write(s, zeroes, nb * size, NULL, 0, PA_SEEK_RELATIVE);
+#endif
             if (likely(zeroes != NULL))
-#if 1 /* Fault injection: remove this to be too early */
                 if (pa_stream_write(s, zeroes, nb * size, free, 0,
                                     PA_SEEK_RELATIVE) < 0)
-#endif
                     free(zeroes);
         }
 
@@ -351,9 +360,9 @@ static void Play(aout_instance_t *aout)
         msg_Dbg(aout, "uncorking");
     }
 
-#if 0 /* Fault injector to be too late / test underrun recovery */
-    static unsigned u = 0;
-    if ((++u % 500) == 0) {
+#if 0 /* Fault injector to test underrun recovery */
+    static volatile unsigned u = 0;
+    if ((++u % 1000) == 0) {
         msg_Err(aout, "fault injection");
         pa_operation_unref(pa_stream_flush(s, NULL, NULL));
     }



More information about the vlc-commits mailing list