On Wed, 24 Oct 2018 at 18:13, Takashi Iwai tiwai@suse.de wrote:
On Tue, 23 Oct 2018 16:08:22 +0200, Pierre-Louis Bossart wrote:
Linux 4.17.14, Class Compliant Mode (snd-usb-audio, ALSA backend): 16/2 32 + 80 ~ 2.333 ms
What are these numbers? Are these lines supposed to in the format expressed by the first formula above? If they are, how come "block_size/periods" shows up as a pair of numbers "16/2" but "block_size*periods" shows up as a single number "32"?
To interpret "16/2 32 + 80 ~ 2.333 ms" Block size: 16 samples Periods: 2 (one period for playback + one period for recording when determining round trip latency) The minimum round trip latency is: 16 * 2 = 32 samples However, I measured 112 samples round trip latency which is an additional delay of 80 samples (32 + 80 = 112). 112 samples at 48000 Hz is 112 / 48000 * 1000 is approximately 2.333 ms measured round trip latency.
ok, so what problem are you trying to fix?
Are you concerned about the latency numbers (but then they seem lower on Linux and latency concerns with large buffers are a self-negating proposition)? are you concerned about the variable delay that doesn't seem to exist on MacOS or Windows? Are you trying to match the performance of the RME driver on MacOS?
I am not sure how this comparison is done btw, the delay includes both buffering on the device side before reaching the analog parts as well as buffering on the OS side. While the former should be constant, the latter depends a great deal on implementation, not sure there are direct lessons to be applied to ALSA. I also see inconsistent/non-linear results where with a larger block size the delay is smaller, e.g.
256/2 512 + 650 ~ 24.208 ms 2048/3 6144 + 633 ~ 141.188 ms
Independently from the measurement done in this thread, actually, there is a known latency source in the playback path in USB-audio driver code -- which I mentioned in the audio mini conf in the last year: namely, the USB-audio driver starts streaming at prepare time for playback, not at the trigger-START time. This is a sort of workaround to make the device looking similar to the standard ring-buffer behavior.
Maybe moving the start at trigger (like the capture direction) would reduce this artificial latency, but it makes the driver behaving in an unexpected manner. Then it may wake up for period_elapsed soon after the stream start with a large runtime->delay value, as the data in in-flight URBs are seen as already "processed".
I observed that snd_usb_pcm_prepare calls start_endpoints which ends up submitting silent urbs (prepared by prepare_silent_urb) until ep->prepare_data_urb is set by SNDRV_PCM_TRIGGER_START in snd_usb_substream_playback_trigger.
I tried to moving the start_endpoints call from snd_usb_pcm_prepare to snd_usb_substream_playback trigger's SNDRV_PCM_TRIGGER_START case (see https://github.com/net147/linux/commit/276eae5481653a2d4034fbae56f0d5bc579ec... - it is enabled using start_playback_on_prepare=0 module option for snd-usb-audio) but I get a kernel stall in some cases with the following call trace: _raw_spin_lock+0x2c/0x30 _snd_pcm_stream_lock_irqsave+0x31/0x60 [snd_pcm] snd_pcm_period_elapsed+0x26/0xb0 [snd_pcm] prepare_playback_urb+0x368/0x640 [snd_usb_audio] ? usb_submit_urb+0x3cb/0x590 snd_usb_endpoint_start+0x148/0x300 [snd_usb_audio] start_endpoints+0x36/0x160 [snd_usb_audio] snd_usb_substream_playback_trigger+0x152/0x1a0 [snd_usb_audio] snd_pcm_action+0x117/0x150 [snd_pcm] snd_pcm_common_ioctl+0x588/0xdb0 [snd_pcm] ? mprotect_fixup+0x1ec/0x2f0 snd_pcm_ioctl+0x23/0x30 [snd_pcm] do_vfs_ioctl+0xa6/0x760 ? syscall_trace_enter+0x1be/0x2b0 __x64_sys_ioctl+0x62/0x90 do_syscall_64+0x5b/0x170 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Any ideas?
Thanks.
Regards, Jonathan