[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