[pulseaudio-commits] [Git][pulseaudio/pulseaudio][master] loopback: Add option fast_adjust_threshold_msec

Arun Raghavan gitlab at gitlab.freedesktop.org
Mon Mar 25 04:50:47 UTC 2019


Arun Raghavan pushed to branch master at PulseAudio / pulseaudio


Commits:
e794d0a2 by Georg Chini at 2019-03-25T04:46:07Z
loopback: Add option fast_adjust_threshold_msec

After a suspend/resume cycle of a system, it may be possible that module-loopback
accumulates several seconds of audio in the memblockq before the alsa sink becomes
active again. Also it may be possible for other reasons that the actual loopback
latency is too different from the target latency to be adjusted in a reasonable
time by the normal rate controller.
This patch adds the option fast_adjust_threshold_msec to module-loopback. If set,
the latency will be forcefully adjusted to the target latency by dropping or
inserting samples if the actual latency differs more than fast_adjust_threshold_msec
from the target latency.
Also the calculation of the real adjust time would fail when the system was
suspended because that case was not considered. Now the real adjust time
calculation is skipped if the time passed between two calls of adjust_rates()
appears significantly too long.

- - - - -


1 changed file:

- src/modules/module-loopback.c


Changes:

=====================================
src/modules/module-loopback.c
=====================================
@@ -46,6 +46,7 @@ PA_MODULE_USAGE(
         "adjust_time=<how often to readjust rates in s> "
         "latency_msec=<latency in ms> "
         "max_latency_msec=<maximum latency in ms> "
+        "fast_adjust_threshold_msec=<threshold for fast adjust in ms> "
         "format=<sample format> "
         "rate=<sample rate> "
         "channels=<number of channels> "
@@ -92,6 +93,7 @@ struct userdata {
     pa_usec_t latency;
     pa_usec_t max_latency;
     pa_usec_t adjust_time;
+    pa_usec_t fast_adjust_threshold;
 
     /* Latency boundaries and current values */
     pa_usec_t min_source_latency;
@@ -161,6 +163,7 @@ static const char* const valid_modargs[] = {
     "adjust_time",
     "latency_msec",
     "max_latency_msec",
+    "fast_adjust_threshold_msec",
     "format",
     "rate",
     "channels",
@@ -180,6 +183,7 @@ enum {
     SINK_INPUT_MESSAGE_SOURCE_CHANGED,
     SINK_INPUT_MESSAGE_SET_EFFECTIVE_SOURCE_LATENCY,
     SINK_INPUT_MESSAGE_UPDATE_MIN_LATENCY,
+    SINK_INPUT_MESSAGE_FAST_ADJUST,
 };
 
 enum {
@@ -316,7 +320,7 @@ static void adjust_rates(struct userdata *u) {
     int32_t latency_difference;
     pa_usec_t current_buffer_latency, snapshot_delay;
     int64_t current_source_sink_latency, current_latency, latency_at_optimum_rate;
-    pa_usec_t final_latency, now;
+    pa_usec_t final_latency, now, time_passed;
 
     pa_assert(u);
     pa_assert_ctl_context();
@@ -351,11 +355,15 @@ static void adjust_rates(struct userdata *u) {
         pa_log_info("Underrun counter: %u", u->underrun_counter);
     }
 
-    /* Calculate real adjust time */
+    /* Calculate real adjust time if source or sink did not change and if the system has
+     * not been suspended. If the time between two calls is more than 5% longer than the
+     * configured adjust time, we assume that the system has been sleeping and skip the
+     * calculation for this iteration. */
     now = pa_rtclock_now();
-    if (!u->source_sink_changed) {
+    time_passed = now - u->adjust_time_stamp;
+    if (!u->source_sink_changed && time_passed < u->adjust_time * 1.05) {
         u->adjust_counter++;
-        u->real_adjust_time_sum += now - u->adjust_time_stamp;
+        u->real_adjust_time_sum += time_passed;
         u->real_adjust_time = u->real_adjust_time_sum / u->adjust_counter;
     }
     u->adjust_time_stamp = now;
@@ -391,6 +399,17 @@ static void adjust_rates(struct userdata *u) {
 
     pa_log_debug("Loopback latency at base rate is %0.2f ms", (double)latency_at_optimum_rate / PA_USEC_PER_MSEC);
 
+    /* Drop or insert samples if fast_adjust_threshold_msec was specified and the latency difference is too large. */
+    if (u->fast_adjust_threshold > 0 && abs(latency_difference) > u->fast_adjust_threshold) {
+        pa_log_debug ("Latency difference larger than %lu msec, skipping or inserting samples.", u->fast_adjust_threshold / PA_USEC_PER_MSEC);
+
+        pa_asyncmsgq_send(u->sink_input->sink->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_FAST_ADJUST, NULL, current_source_sink_latency, NULL);
+
+        /* Skip real adjust time calculation on next iteration. */
+        u->source_sink_changed = true;
+        return;
+    }
+
     /* Calculate new rate */
     new_rate = rate_controller(base_rate, u->real_adjust_time, latency_difference);
 
@@ -963,6 +982,12 @@ static int sink_input_process_msg_cb(pa_msgobject *obj, int code, void *data, in
 
             u->output_thread_info.minimum_latency = (pa_usec_t)offset;
 
+            return 0;
+
+        case SINK_INPUT_MESSAGE_FAST_ADJUST:
+
+            memblockq_adjust(u, offset, true);
+
             return 0;
     }
 
@@ -1266,6 +1291,7 @@ int pa__init(pa_module *m) {
     bool source_dont_move;
     uint32_t latency_msec;
     uint32_t max_latency_msec;
+    uint32_t fast_adjust_threshold;
     pa_sample_spec ss;
     pa_channel_map map;
     bool format_set = false;
@@ -1350,6 +1376,12 @@ int pa__init(pa_module *m) {
         goto fail;
     }
 
+    fast_adjust_threshold = 0;
+    if (pa_modargs_get_value_u32(ma, "fast_adjust_threshold_msec", &fast_adjust_threshold) < 0 || (fast_adjust_threshold != 0 && fast_adjust_threshold < 100)) {
+        pa_log("Invalid fast adjust threshold specification");
+        goto fail;
+    }
+
     max_latency_msec = 0;
     if (pa_modargs_get_value_u32(ma, "max_latency_msec", &max_latency_msec) < 0) {
         pa_log("Invalid maximum latency specification");
@@ -1375,6 +1407,7 @@ int pa__init(pa_module *m) {
     u->source_sink_changed = true;
     u->real_adjust_time_sum = 0;
     u->adjust_counter = 0;
+    u->fast_adjust_threshold = fast_adjust_threshold * PA_USEC_PER_MSEC;
 
     adjust_time_sec = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC;
     if (pa_modargs_get_value_u32(ma, "adjust_time", &adjust_time_sec) < 0) {



View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/commit/e794d0a21af24ae3d2afae000ad67b17ef56ada2

-- 
View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/commit/e794d0a21af24ae3d2afae000ad67b17ef56ada2
You're receiving this email because of your account on gitlab.freedesktop.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/pulseaudio-commits/attachments/20190325/ddfd2735/attachment-0001.html>


More information about the pulseaudio-commits mailing list