- /* Compute lip desynchronization */
- delta = vlc_pa_get_latency(aout, sys->context, s);
- if (delta == VLC_TS_INVALID)
- return;
-
- delta = (sys->pts - mdate()) - delta;
- change = delta - sys->desync;
- sys->desync = delta;
- //msg_Dbg(aout, "desync: %+"PRId64" us (variation: %+"PRId64" us)",
- // delta, change);
-
- const unsigned inrate = aout->format.i_rate;
- unsigned outrate = sys->rate;
- bool sync = false;
-
- if (delta < -AOUT_MAX_PTS_DELAY)
- msg_Warn(aout, "too late by %"PRId64" us", -delta);
- else if (delta > +AOUT_MAX_PTS_ADVANCE)
- msg_Warn(aout, "too early by %"PRId64" us", delta);
- else if (outrate == inrate)
- return; /* In sync, do not add unnecessary disturbance! */
- else
- sync = true;
-
- /* Compute playback sample rate */
- /* This is empirical. Feel free to define something smarter. */
- int adj = sync ? (outrate - inrate)
- : outrate * (delta + change) / (CLOCK_FREQ << 4);
- /* This avoids too quick rate variation. It sounds really bad and
- * causes unstability (e.g. oscillation around the correct rate). */
- int limit = inrate >> 10;
- /* However, to improve stability and try to converge, closing to the
- * nominal rate is favored over drifting from it. */
- if ((adj > 0) == (sys->rate > inrate))
- limit *= 2;
- if (adj > +limit)
- adj = +limit;
- if (adj < -limit)
- adj = -limit;
- outrate -= adj;
-
- /* This keeps the effective rate within specified range
- * (+/-AOUT_MAX_RESAMPLING% - see <vlc_aout.h>) of the nominal rate. */
- limit = inrate * AOUT_MAX_RESAMPLING / 100;
- if (outrate > inrate + limit)
- outrate = inrate + limit;
- if (outrate < inrate - limit)
- outrate = inrate - limit;
-
- /* Apply adjusted sample rate */
- if (outrate == sys->rate)
- return;
- pa_operation *op = pa_stream_update_sample_rate(s, outrate, NULL, NULL);
- if (unlikely(op == NULL)) {
- vlc_pa_error(aout, "cannot change sample rate", sys->context);
- return;
- }
- pa_operation_unref(op);
- msg_Dbg(aout, "changed sample rate to %u Hz",outrate);
- sys->rate = outrate;