Bug 80770

Summary: module-loopback ignores latency_msec option
Product: PulseAudio Reporter: ifyoudieinthegameyoudieforreal
Component: modulesAssignee: pulseaudio-bugs
Status: RESOLVED FIXED QA Contact: pulseaudio-bugs
Severity: major    
Priority: medium CC: johnbanderson, lennart
Version: unspecified   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Attachments: Verbose log of loading and unloading module-loopback w/ different latencies

Description ifyoudieinthegameyoudieforreal 2014-07-01 20:35:36 UTC
My latency using module-loopback is unacceptable for playing video games through it (video game hardware connected to analog input). After I couldn't get any better using the module's latency_msec option, I dinked around all that I could with possible priority problems, realtime problems... Now, though, I see that my latency is exactly the same whether I set latency_msec=1 or latency_msec=2000, and 'pactl list sink-inputs' reflects that:

[david@delphinium pulse]$ pactl load-module module-loopback latency_msec=1   
38
[david@delphinium pulse]$ pactl list sink-inputs
Sink Input #10
	Driver: module-loopback.c
	Owner Module: 38
	Client: n/a
	Sink: 0
	Sample Specification: s16le 2ch 44011Hz
	Channel Map: front-left,front-right
	Format: pcm
	Corked: no
	Mute: no
	Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 200767 usec
	Sink Latency: 99891 usec
	Resample method: speex-float-1
	Properties:
		media.role = "abstract"
		module-stream-restore.id = "sink-input-by-media-role:abstract"
		media.name = "Loopback from CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar DX)) Analog Stereo"
[david@delphinium pulse]$ pactl unload-module module-loopback
[david@delphinium pulse]$ pactl load-module module-loopback latency_msec=2000
39
[david@delphinium pulse]$ pactl list sink-inputs
Sink Input #11
	Driver: module-loopback.c
	Owner Module: 39
	Client: n/a
	Sink: 0
	Sample Specification: s16le 2ch 44011Hz
	Channel Map: front-left,front-right
	Format: pcm
	Corked: no
	Mute: no
	Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
	        balance 0.00
	Buffer Latency: 197905 usec
	Sink Latency: 99844 usec
	Resample method: speex-float-1
	Properties:
		media.role = "abstract"
		module-stream-restore.id = "sink-input-by-media-role:abstract"
		media.name = "Loopback from CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar DX)) Analog Stereo"

No matter what I set latency_msec to, 'Buffer Latency' is ~200ms, which is latency_msec's default value. It appears that this option is being ignored, which is a huge pain, obviously.
Comment 1 Raymond 2014-07-02 15:53:51 UTC
any reason not using line playback volume of your onboard sound card or analog input monitor of your oxygen mixer instead of the software loopback which have high latency  at least one capture period and one plpayback period ?
Comment 2 ifyoudieinthegameyoudieforreal 2014-07-02 20:37:59 UTC
(In reply to comment #1)
> any reason not using line playback volume of your onboard sound card or
> analog input monitor of your oxygen mixer instead of the software loopback
> which have high latency  at least one capture period and one plpayback
> period ?

Yes, there's a reason that I'm using PulseAudio's loopback module instead of the ALSA monitor, directly. That doesn't have anything to do with this bug, though.

Since I last commented, I was able to reduce the 'Sink Latency' (and the module-loopback 'buffer latency') dramatically by correcting my PulseAudio default fragment size from the default 25 down to a more suitable 3.

Although the 'Buffer Latency' value is no longer ~200ms, which defeats my theory that module-loopback always uses the recorded default value of 200ms, the latencies are still exactly the same regardless of whether I supply latency_msec=1 or latency_msec=2000. I'm not sure of exactly how module-loopback settles on its latency, but it still appears that the latency_msec option is ignored, as far as I can tell.
Comment 4 Tanu Kaskinen 2014-07-07 12:09:44 UTC
module-loopback doesn't ignore the option, there's a different explanation for the observations. If changing the default fragment size has some effect, then it means that the sink (and probably source too if they're the same card) are not using timer-based scheduling, and hence don't support dynamic latency. Without dynamic latency, module-loopback can't control the overall latency. Or more specifically, it can't make the latency smaller than what the sink and source allow; it can be considered a bug that latency_msec=2000 doesn't make the latency higher, because that should be possible to do.
Comment 5 ifyoudieinthegameyoudieforreal 2014-07-07 17:14:20 UTC
(In reply to comment #4)
> module-loopback doesn't ignore the option, there's a different explanation
> for the observations. If changing the default fragment size has some effect,
> then it means that the sink (and probably source too if they're the same
> card) are not using timer-based scheduling, and hence don't support dynamic
> latency. Without dynamic latency, module-loopback can't control the overall
> latency. Or more specifically, it can't make the latency smaller than what
> the sink and source allow; it can be considered a bug that latency_msec=2000
> doesn't make the latency higher, because that should be possible to do.

Thank you for the insight. It does seem like module-loopback isn't conrolling the overall latency, as you say, since its latency seems tied to the latency of my sink (and source, since they are indeed on the same card). That being said, I'm able to get less latency using pacat (record at 1ms, playback at 1ms. I don't know if the actual latency is as low as that request, but it's quite a bit faster than module-loopback, anyway). I'm not an engineer, but it seems like module-loopback would be doing something similar to what I'm doing with pacat (recording from an input and playing that back to an output in real time, unless it uses some kind of lower-level, less-intensive means), and, although it would arguably be difficult on many systems to have that running in the background at all times, I don't see why it wouldn't be possible by user request if it's possible for pacat.

If it should be possible to add ~more~ latency, anyway, then I'm not going to change the title of this bug, since changing the value of latency_msec has no effect one way or the other. Also, as far as I've read, the manual doesn't give any warning about soundcards that don't support dynamic latency; I think that I rightfully expected that changing the option value would do something, but it's ineffectual and no message is produced, so it's effectively being ignored.

Also, I can set arbitrarily high latencies using pacat, and they're accurately reproduced. For the record, and in case this helps anyone else, here's the pacat command that I'm using:

pacat -r --latency-msec=1 -d alsa_input.pci-0000_08_04.0.analog-stereo | pacat -p --latency-msec=1 -d alsa_output.pci-0000_08_04.0.analog-stereo

where "alsa_input.pci-0000_08_04.0.analog-stereo" and "alsa_output.pci-0000_08_04.0.analog-stereo" are my input and output devices, respectfully; anyone else's will be different.

Does anyone know of a command or option that I can use to make module-loopback produce valuable messages? It'd be interesting to see what it has to say for itself when it's ignoring or failing to implement my latency requests.
Comment 6 Raymond 2014-07-08 11:52:18 UTC
https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/pci/oxygen/oxygen_pcm.c?id=93943beb29be7084afb61556e96bc454079bfb0e

only a few sound cards support disable period wakeup

seem have lower period bytes minimum 64 than hda-Intel 128


err = snd_pcm_hw_constraint_step(runtime, 0,
					 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
	if (err < 0)
		return err;
	err = snd_pcm_hw_constraint_step(runtime, 0,
					 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);


https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/pci/hda/hda_intel.c?id=2ae66c26550cd94b0e2606a9275eb0ab7070ad0e

does intel hda really support arbitrary period sizes since Fifo size is fixed
Comment 7 Tanu Kaskinen 2014-07-08 11:54:34 UTC
Can you attach a verbose log for a run where you just load module-loopback with latency_msec=1, so that we can figure out if the sink is really not using timer-based scheduling? Here are instructions: https://wiki.ubuntu.com/PulseAudio/Log

Looping back the audio with pacat shouldn't have any lower latency, unless the sink is slow to start so some audio gets received from the source before the sink starts to consume it (module-loopback doesn't handle that case well, a known issue).
Comment 8 Raymond 2014-07-08 11:57:10 UTC
what is the meaning of 1ms latency for 44100Hz as it contain 44.1 samples ?
Comment 9 Tanu Kaskinen 2014-07-08 12:00:24 UTC
The meaning of "1 ms" in this case is "as low as the sink can go". It probably can't provide that low latency.
Comment 10 Raymond 2014-07-09 04:55:25 UTC
(   0.138|   0.000) I: [pulseaudio] alsa-source.c: Using 4.0 fragments of size 2398 bytes (24.98ms), buffer size is 9594 bytes (99.94ms)
(   0.138|   0.000) D: [pulseaudio] alsa-source.c: hwbuf_unused=0
(   0.138|   0.000) D: [pulseaudio] alsa-source.c: setting avail_min=1
(   0.138|   0.000) D: [pulseaudio] alsa-util.c: snd_pcm_dump():
(   0.138|   0.000) D: [pulseaudio] alsa-util.c: Plug PCM: Hardware PCM card 2 'USB Device 0x46d:0x805' device 0 subdevice 0
(   0.138|   0.000) D: [pulseaudio] alsa-util.c: Its setup is:
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   stream       : CAPTURE
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   access       : MMAP_INTERLEAVED
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   format       : S16_LE
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   subformat    : STD
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   channels     : 1
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   rate         : 48000
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   exact rate   : 48000 (48000/1)
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   msbits       : 16
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   buffer_size  : 4797
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   period_size  : 1199
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   period_time  : 24979
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   tstamp_mode  : ENABLE
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   period_step  : 1
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   avail_min    : 1199
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   period_event : 1
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   start_threshold  : -1
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   stop_threshold   : 5400941853124067328
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   silence_threshold: 0
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   silence_size : 0
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   boundary     : 5400941853124067328
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   appl_ptr     : 0
(   0.138|   0.000) D: [pulseaudio] alsa-util.c:   hw_ptr       : 0


it strange that USB audio update in 1 ms interval for 48000Hz but pulseaudio  still  cannot set 25ms period time
Comment 11 ifyoudieinthegameyoudieforreal 2014-07-09 20:31:15 UTC
Created attachment 102503 [details]
Verbose log of loading and unloading module-loopback w/ different latencies
Comment 12 ifyoudieinthegameyoudieforreal 2014-07-09 20:32:33 UTC
(In reply to comment #7)
> Can you attach a verbose log for a run where you just load module-loopback
> with latency_msec=1, so that we can figure out if the sink is really not
> using timer-based scheduling? Here are instructions:
> https://wiki.ubuntu.com/PulseAudio/Log
> 
> Looping back the audio with pacat shouldn't have any lower latency, unless
> the sink is slow to start so some audio gets received from the source before
> the sink starts to consume it (module-loopback doesn't handle that case
> well, a known issue).

Thank you for your response. I've generated the preceding log using the instructions provided at your link. I loaded module-loopback with latency_msec=1, first, and then I unloaded it and re-loaded it with latency_msec=1000, both of which sound like the same latency, to me.

When I pacat my input to my output, both pacat's running with a specified 1ms latency, the latency is much less than when using module-loopback, perhaps for the reason that you provided. On the other hand, when I run the pacat's with 1000 msec or more of latency, I can actually delay the sound by seconds at a time, which is what I would expect. This doesn't appear to be possible with module-loopback; specifying large latencies up to 2000ms (the maximum supported latency, according to the manual) appears to have no effect on the latency, which stays the same as latency_msec=1.
Comment 13 Raymond 2014-07-09 23:57:36 UTC

.735|   0.000) I: [pulseaudio] source.c:     device.vendor.name = "C-Media Electronics Inc"
(   0.735|   0.000) I: [pulseaudio] source.c:     device.product.id = "8788"
(   0.735|   0.000) I: [pulseaudio] source.c:     device.product.name = "CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar DX))"
(   0.735|   0.000) I: [pulseaudio] source.c:     device.string = "2"
(   0.735|   0.000) I: [pulseaudio] source.c:     module-udev-detect.discovered = "1"
(   0.735|   0.000) I: [pulseaudio] source.c:     device.icon_name = "audio-card-pci"
(   0.735|   0.000) I: [pulseaudio] alsa-sink.c: Using 3.9 fragments of size 544 bytes (3.08ms), buffer size is 2112 bytes (11.97ms)

do the driver really support 3.9 fragments ?
Comment 14 Raymond 2014-07-10 02:52:06 UTC
|   0.000) D: [pulseaudio] alsa-mixer.c: Probe of element 'Hardware Master' succeeded (volume=0, switch=0, enumeration=0).
(   0.715|   0.000) W: [pulseaudio] alsa-mixer.c: Volume element Master has 8 channels. That's too much! I can't handle that!
(   0.715|   0.000) D: [pulseaudio] alsa-mixer.c: Probe of element 'Master' failed.

pulseaudio does not support 8 channels playback volume control


what hardware requiremen t are necessary for supporting dynamic latency ?


https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/pci/oxygen/oxygen_pcm.c?id=075140ea8bf1405057c072a84ccf4e0d3f2c76f5

disable period wake-up 

pointer callback is accurate 

arbitrary period size 



time scheduling seem disabled by pulseaudio found  usb audio device
Comment 15 Raymond 2014-07-10 03:05:37 UTC
seem missing this constraints

snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);

when common sample rate 44100 and 48000 Hz are multiple of three

latency time in ms may have rounding problems
Comment 16 Raymond 2014-07-10 05:41:07 UTC
https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/pci/hda/hda_intel.c?id=7bfe059e38b06a0d813d92b9b3e500455f6a2c99

nvidia controllers have 128 bytes alignment,

it strange that the period size is not multiple of 32


167|   0.000) D: [pulseaudio] alsa-util.c: Trying hdmi:4 with SND_PCM_NO_AUTO_FORMAT ...
(   0.167|   0.000) D: [pulseaudio] alsa-util.c: Managed to open hdmi:4
(   0.167|   0.000) D: [pulseaudio] alsa-util.c: Maximum hw buffer size is 7925 ms
(   0.200|   0.032) D: [pulseaudio] alsa-util.c: Set buffer size first (to 528 samples), period size second (to 132 samples).
Comment 17 Raymond 2014-07-11 02:33:34 UTC
0.849|   0.000) D: [pulseaudio] module-loopback.c: Loopback overall latency is 17.31 ms + 0.72 ms + 0.03 ms = 18.07 ms
(   0.849|   0.000) D: [pulseaudio] module-loopback.c: Should buffer 4224 bytes, buffered at minimum 128 bytes
(   0.849|   0.000) I: [pulseaudio] module-loopback.c: New rate of 43998 Hz not within 2鈥� of 44100 Hz, forcing smaller adjustment
(   0.849|   0.000) D: [pulseaudio] module-loopback.c: [alsa_output.pci-0000_08_04.0.analog-stereo] Updated sampling rate to 44011 Hz.

what  do 0.03ms mean ? 

there is rounding bug if it mean one sample time
Comment 18 Raymond 2014-07-13 02:42:36 UTC
https://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/commit/sound/pci/oxygen/oxygen_pcm.c?id=d55d7a1cbbd069f8368ec5c67480d319e7b227b9

in theory pcie those oxygen cards should use 128 as  period byte min and only those pci oxygen cards can use 64 as period byte min
Comment 19 Alexander E. Patrakov 2016-12-14 13:52:06 UTC
I believe this is fixed now in git?
Comment 20 Tanu Kaskinen 2016-12-14 18:41:12 UTC
(In reply to Alexander E. Patrakov from comment #19)
> I believe this is fixed now in git?

I don't think so. msec_latency=2000 still results in much too low latency.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.