[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