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) {