From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Re: snd-usb-audio Buffer Sizes and Round Trip Latency Date: Wed, 24 Apr 2019 16:05:53 +0200 Message-ID: References: <5fb8650f-5a55-d895-f7b3-bc8a3b1af31b@linux.intel.com> <928c8739-f0bc-339c-f951-6eb6bd001cf4@linux.intel.com> Mime-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mx1.suse.de (mx2.suse.de [195.135.220.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 9C6F6F8065B for ; Wed, 24 Apr 2019 16:05:54 +0200 (CEST) In-Reply-To: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" To: Jonathan Liu Cc: Clemens Ladisch , ALSA development , Alan Stern , Pierre-Louis Bossart List-Id: alsa-devel@alsa-project.org On Mon, 22 Apr 2019 12:50:15 +0200, Jonathan Liu wrote: > > On Wed, 24 Oct 2018 at 18:13, Takashi Iwai 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/276eae5481653a2d4034fbae56f0d5bc579ecf67 > - 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? This is because snd_pcm_period_elapsed() is called from prepare_data_urb callback that is called also at start_endpoints(). I guess we'd need to move the hwptr accounting and snd_pcm_period_elapsed() call into retire_data_urb callback in the case of start-at-trigger for playback. thanks, Takashi