]> code.delx.au - pulseaudio/commitdiff
add rewind-safeguard parameter
authorPierre-Louis Bossart <pierre-louis.bossart@intel.com>
Thu, 29 Apr 2010 15:48:11 +0000 (10:48 -0500)
committerLennart Poettering <lennart@poettering.net>
Fri, 7 May 2010 23:38:25 +0000 (01:38 +0200)
Rewinding the ring buffer completely causes audible issues with DMAs.
Previous solution didn't work with tsched=0, and used tsched_watermark
for guardband, which isn't linked to hardware and could become really high
if underflows occurred.

Added separate parameter that can be tuned to hardware limitations and size
of DMA bursts.

src/modules/alsa/alsa-sink.c
src/modules/alsa/module-alsa-sink.c

index 687a830029e7d4a309f399ab5765c123d7e0a4d1..ce7970b23362a4696ea7eda5b1d6a089033c708b 100644 (file)
@@ -83,6 +83,8 @@
 
 #define VOLUME_ACCURACY (PA_VOLUME_NORM/100)  /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */
 
+#define DEFAULT_REWIND_SAFEGUARD_BYTES (256) /* 1.33ms @48kHz, should work for most hardware */
+
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -112,7 +114,8 @@ struct userdata {
         watermark_inc_step,
         watermark_dec_step,
         watermark_inc_threshold,
-        watermark_dec_threshold;
+        watermark_dec_threshold,
+        rewind_safeguard;
 
     pa_usec_t watermark_dec_not_before;
 
@@ -1312,8 +1315,8 @@ static int process_rewind(struct userdata *u) {
 
     unused_nbytes = (size_t) unused * u->frame_size;
 
-    if (u->use_tsched)
-        unused_nbytes += u->tsched_watermark;
+    /* make sure rewind doesn't go too far, can cause issues with DMAs */
+    unused_nbytes += u->rewind_safeguard;
 
     if (u->hwbuf_size > unused_nbytes)
         limit_nbytes = u->hwbuf_size - unused_nbytes;
@@ -1668,7 +1671,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     pa_channel_map map;
     uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
     snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
-    size_t frame_size;
+    size_t frame_size, rewind_safeguard;
     pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE;
     pa_sink_new_data data;
     pa_alsa_profile_set *profile_set = NULL;
@@ -1722,6 +1725,12 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
         goto fail;
     }
 
+    rewind_safeguard = DEFAULT_REWIND_SAFEGUARD_BYTES;
+    if (pa_modargs_get_value_u32(ma, "rewind_safeguard", &rewind_safeguard) < 0) {
+        pa_log("Failed to parse rewind_safeguard argument");
+        goto fail;
+    }
+
     use_tsched = pa_alsa_may_tsched(use_tsched);
 
     u = pa_xnew0(struct userdata, 1);
@@ -1730,6 +1739,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     u->use_mmap = use_mmap;
     u->use_tsched = use_tsched;
     u->first = TRUE;
+    u->rewind_safeguard = rewind_safeguard;
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
index 3aa89b2aaf672ab8e53424026b19d991bd514e26..a73274fdb151b8f43c72271bd18a22430526bbca 100644 (file)
@@ -54,7 +54,8 @@ PA_MODULE_USAGE(
         "tsched_buffer_size=<buffer size when using timer based scheduling> "
         "tsched_buffer_watermark=<lower fill watermark> "
         "ignore_dB=<ignore dB information from the device?> "
-        "control=<name of mixer control>");
+        "control=<name of mixer control>"
+        "rewind_safeguard=<number of bytes that cannot be rewound");
 
 static const char* const valid_modargs[] = {
     "name",
@@ -74,6 +75,7 @@ static const char* const valid_modargs[] = {
     "tsched_buffer_watermark",
     "ignore_dB",
     "control",
+    "rewind_safeguard",
     NULL
 };