[alsa-devel] [PATCH] ALSA: usb-audio: support delay calculation on capture streams

Takashi Iwai tiwai at suse.de
Fri Dec 21 12:06:51 CET 2012


At Wed, 19 Dec 2012 11:39:05 -0600,
Pierre-Louis Bossart wrote:
> 
> Enable delay report on capture path. The delay is reset when an
> URB is retired and increment at each call to .pointer based
> on frame counter changes. The precision of the delay
> information is limited to 1ms as in the playback case.
> 
> This reverts commit 3f94fad09538ec988919ec3f371841182df71d04.
> 
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart at linux.intel.com>

Thanks, I'll queue this once after 3.8-rc1 is released.


Takashi

> ---
>  sound/usb/pcm.c |   23 ++++++++++++++++++++---
>  1 file changed, 20 insertions(+), 3 deletions(-)
> 
> diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
> index c659310..3a38447 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;
> @@ -78,8 +83,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
>  		return SNDRV_PCM_POS_XRUN;
>  	spin_lock(&subs->lock);
>  	hwptr_done = subs->hwptr_done;
> -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> -		substream->runtime->delay = snd_usb_pcm_delay(subs,
> +	substream->runtime->delay = snd_usb_pcm_delay(subs,
>  						substream->runtime->rate);
>  	spin_unlock(&subs->lock);
>  	return hwptr_done / (substream->runtime->frame_bits >> 3);
> @@ -1147,6 +1151,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 +1188,15 @@ 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) {
> -- 
> 1.7.9.5
> 


More information about the Alsa-devel mailing list