[alsa-devel] [PATCH 1/2] ALSA: usb-audio: ignore delay calculation for capture stream

Takashi Iwai tiwai at suse.de
Wed Dec 12 12:26:24 CET 2012


At Mon, 10 Dec 2012 15:33:56 -0600,
Pierre-Louis Bossart wrote:
> 
> 
> >> Shouldn't we add support for delay on the capture path instead? We could
> >> use the same frame counter to report the delay and resync when the urb
> >> is retired.
> >
> > Sure, it must be possible like that way.
> > Wouldn't you like to volunteer? ;)
> 
> here's a suggestion. Since we don't submit multiple URBs as in the 
> playback case, we can only track the delay using the frame counter for a 
> single URB, and we reset the counters when the URB is retired.
> Did a couple of tests, seems to work ok.

Looks good, but I'd like to merge this after 3.8 merge window.
It's no urgent fix, so better to have a long test for 3.9.

> I couldn't figure out if the related patches are already in git, I 
> didn't find them. Takashi, did you merge them already?

Yes, these have been already queued for 3.8.
See for-next branch of sound git tree.


thanks,

Takashi

> -Pierre
> 
> 
> [2 usb_delay.patch <text/x-patch (7bit)>]
> diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
> index c659310..65dc53e 100644
> --- a/sound/usb/pcm.c
> +++ b/sound/usb/pcm.c
> @@ -59,7 +59,12 @@ snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
>  
>  	/* Approximation based on number of samples per USB frame (ms),
>  	   some truncation for 44.1 but the estimate is good enough */
> -	est_delay =  subs->last_delay - (frame_diff * rate / 1000);
> +	est_delay =  frame_diff * rate / 1000;
> +	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
> +		est_delay = subs->last_delay - est_delay;
> +	else
> +		est_delay = subs->last_delay + est_delay;
> +
>  	if (est_delay < 0)
>  		est_delay = 0;
>  	return est_delay;
> @@ -1147,6 +1152,10 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
>  	int i, period_elapsed = 0;
>  	unsigned long flags;
>  	unsigned char *cp;
> +	int current_frame_number;
> +
> +	/* read frame number here, update pointer in critical section */
> +	current_frame_number = usb_get_current_frame_number(subs->dev);
>  
>  	stride = runtime->frame_bits >> 3;
>  
> @@ -1180,6 +1189,13 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
>  			subs->transfer_done -= runtime->period_size;
>  			period_elapsed = 1;
>  		}
> +		/* capture delay is by construction limited to one URB, reset delays here */
> +		runtime->delay = subs->last_delay = 0;
> +
> +		/* realign last_frame_number */
> +		subs->last_frame_number = current_frame_number;
> +		subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
> +
>  		spin_unlock_irqrestore(&subs->lock, flags);
>  		/* copy a data chunk */
>  		if (oldptr + bytes > runtime->buffer_size * stride) {


More information about the Alsa-devel mailing list