diff mbox

pulseaudio: reduce 24s recording latency

Message ID 55F3259D.3000309@t-online.de
State New
Headers show

Commit Message

Volker Rümelin Sept. 11, 2015, 7:03 p.m. UTC
Current code doesn't provide pulseaudio buffer attributes for
recording. Without buffer attributes pulseaudio uses a default
buffer of 4MB. 4MB is approximately 24s 16bit stereo audio
data at 44.1kHz.

This patch fixes bug #1492649

|Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>|
---
 audio/paaudio.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

Comments

Marc-André Lureau Sept. 11, 2015, 11:22 p.m. UTC | #1
Hi

On Fri, Sep 11, 2015 at 9:03 PM, Volker Rümelin <vr_qemu@t-online.de> wrote:
> Current code doesn't provide pulseaudio buffer attributes for
> recording. Without buffer attributes pulseaudio uses a default
> buffer of 4MB. 4MB is approximately 24s 16bit stereo audio
> data at 44.1kHz.

Why isn't the buffer processed as soon as some data is available?
Volker Rümelin Sept. 12, 2015, 11:23 a.m. UTC | #2
Hi,

Am 12.09.2015 um 01:22 schrieb Marc-André Lureau:

>> Current code doesn't provide pulseaudio buffer attributes for
>> recording. Without buffer attributes pulseaudio uses a default
>> buffer of 4MB. 4MB is approximately 24s 16bit stereo audio
>> data at 44.1kHz.
> Why isn't the buffer processed as soon as some data is available?
>
>

On start up qemu opens a connection to pulseaudio in function 
qpa_init_in and pulseaudio immediately starts recording to the 4MB 
ringbuffer. The qemu guest, Windows 8.1 in my case, doesn't consume that 
data if there is no process listening on the audio interface. Now if the 
guest starts recording, it will see audio data which was recorded 24s ago.

Regards,
Volker
Marc-André Lureau Sept. 12, 2015, 12:07 p.m. UTC | #3
Hi

On Fri, Sep 11, 2015 at 9:03 PM, Volker Rümelin <vr_qemu@t-online.de> wrote:
> Current code doesn't provide pulseaudio buffer attributes for
> recording. Without buffer attributes pulseaudio uses a default
> buffer of 4MB. 4MB is approximately 24s 16bit stereo audio
> data at 44.1kHz.
>
> This patch fixes bug #1492649
>
> |Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>|
> ---
>  audio/paaudio.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/audio/paaudio.c b/audio/paaudio.c
> index fea6071..c1169d4 100644
> --- a/audio/paaudio.c
> +++ b/audio/paaudio.c
> @@ -608,6 +608,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
>  {
>      int error;
>      pa_sample_spec ss;
> +    pa_buffer_attr ba;
>      struct audsettings obt_as = *as;
>      PAVoiceIn *pa = (PAVoiceIn *) hw;
>      paaudio *g = pa->g = drv_opaque;
> @@ -616,6 +617,12 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
>      ss.channels = as->nchannels;
>      ss.rate = as->freq;
>
> +    ba.fragsize = pa_frame_size (&ss) * g->conf.samples;
> +    ba.maxlength = 5 * ba.fragsize;

This 5 value is a bit arbitrary, I suppose it may increase max latency
up to 5 times the g->conf.samples. (what about using
PA_STREAM_ADJUST_LATENCY?)

Otherwise, the change looks good to me.

> +    ba.tlength = -1;
> +    ba.prebuf = -1;
> +    ba.minreq = -1;
> +
>      obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
>
>      pa->stream = qpa_simple_new (
> @@ -625,7 +632,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
>          g->conf.source,
>          &ss,
>          NULL,                   /* channel map */
> -        NULL,                   /* buffering attributes */
> +        &ba,                    /* buffering attributes */
>          &error
>          );
>      if (!pa->stream) {
> --
> 1.8.4.5
>
>
=?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= Sept. 12, 2015, 2:35 p.m. UTC | #4
2015-09-12 13:23 keltezéssel, Volker Rümelin írta:
> Hi,
>
> Am 12.09.2015 um 01:22 schrieb Marc-André Lureau:
>
>>> Current code doesn't provide pulseaudio buffer attributes for
>>> recording. Without buffer attributes pulseaudio uses a default
>>> buffer of 4MB. 4MB is approximately 24s 16bit stereo audio
>>> data at 44.1kHz.
>> Why isn't the buffer processed as soon as some data is available?
>>
>>
>
> On start up qemu opens a connection to pulseaudio in function
> qpa_init_in and pulseaudio immediately starts recording to the 4MB
> ringbuffer. The qemu guest, Windows 8.1 in my case, doesn't consume that
> data if there is no process listening on the audio interface. Now if the
> guest starts recording, it will see audio data which was recorded 24s ago.

Weird, pulseaudio shouldn't delay the input more than 2 seconds in the 
default config.  Maybe PA_STREAM_EARLY_REQUESTS help.  See my patch at 
[1].  Alternatively we should maybe call pa_stream_flush when enabling 
the input to tell pulseaudio to drop previously recorded samples.

[1]: https://lists.gnu.org/archive/html/qemu-devel/2015-08/msg02455.html

Zoltan
Volker Rümelin Sept. 12, 2015, 7:55 p.m. UTC | #5
Am 12.09.2015 um 16:35 schrieb Kővágó Zoltán:
> 2015-09-12 13:23 keltezéssel, Volker Rümelin írta:
>>
>> On start up qemu opens a connection to pulseaudio in function
>> qpa_init_in and pulseaudio immediately starts recording to the 4MB
>> ringbuffer. The qemu guest, Windows 8.1 in my case, doesn't consume that
>> data if there is no process listening on the audio interface. Now if the
>> guest starts recording, it will see audio data which was recorded 24s 
>> ago.
>
> Weird, pulseaudio shouldn't delay the input more than 2 seconds in the 
> default config.  Maybe PA_STREAM_EARLY_REQUESTS help.  See my patch at 
> [1].  Alternatively we should maybe call pa_stream_flush when enabling 
> the input to tell pulseaudio to drop previously recorded samples.
>
> [1]: https://lists.gnu.org/archive/html/qemu-devel/2015-08/msg02455.html
>

Hi Zoltan,

I tested your suggestions.

There was the same 24s latency when I replaced PA_STREAM_ADJUST_LATENCY 
with PA_STREAM_EARLY_REQUESTS in function pa_stream_connect_record. This 
was to be expected, because the pulseaudio documentation only mentions 
playback there.

A call to pa_stream_flush in qpa_ctl_in in case VOICE_ENABLE: also 
didn't solve the problem.

But when I replaced pa_stream_flush with a repeated call to 
pa_stream_peek and pa_stream_drop things started to improve. Now I 
experience the 1-2s recording latency mentioned in the pulseaudio 
documentation. But this is still much higher than the latency I see with 
my old patch.

Regards,
Volker
diff mbox

Patch

diff --git a/audio/paaudio.c b/audio/paaudio.c
index fea6071..c1169d4 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -608,6 +608,7 @@  static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 {
     int error;
     pa_sample_spec ss;
+    pa_buffer_attr ba;
     struct audsettings obt_as = *as;
     PAVoiceIn *pa = (PAVoiceIn *) hw;
     paaudio *g = pa->g = drv_opaque;
@@ -616,6 +617,12 @@  static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
     ss.channels = as->nchannels;
     ss.rate = as->freq;
 
+    ba.fragsize = pa_frame_size (&ss) * g->conf.samples;
+    ba.maxlength = 5 * ba.fragsize;
+    ba.tlength = -1;
+    ba.prebuf = -1;
+    ba.minreq = -1;
+
     obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
 
     pa->stream = qpa_simple_new (
@@ -625,7 +632,7 @@  static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
         g->conf.source,
         &ss,
         NULL,                   /* channel map */
-        NULL,                   /* buffering attributes */
+        &ba,                    /* buffering attributes */
         &error
         );
     if (!pa->stream) {