[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