Re: Audio I/O parameters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 24 Jul 2013, James Stone wrote:

> Ok - this does seem to be a vast improvement over 3.8.x (and even, in
> some ways the 3.6x series) - with the addition of Clemen's patch.
> However, very low realtime latencies (which seemed to be somewhat
> possible - 64 frames/period or lower - in the 3.6x series) will no
> longer work properly. 128 frames/period looks fairly usable. Will
> continue with bisect to see if I can discover anything else.

I suspect this remaining problem is partly caused by the ALSA driver
misinterpreting the parameters.  For example, when you specify 64
frames/period, what you actually get is 41.3 (on average).

The patch below ought to help.  It is certainly not the correct
solution, but try it out anyway with 64 frames/packet to see if it
works.  And collect a usbmon trace, so I can see whether it really does
behave as intended.  (The patch is meant to apply on top of the one
Clemens sent earlier.)

Alan Stern



Index: usb-3.10/sound/usb/endpoint.c
===================================================================
--- usb-3.10.orig/sound/usb/endpoint.c
+++ usb-3.10/sound/usb/endpoint.c
@@ -575,6 +575,7 @@ static int data_ep_set_params(struct snd
 			      struct snd_usb_endpoint *sync_ep)
 {
 	unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms;
+	unsigned int min_urbs, max_packs;
 	int is_playback = usb_pipeout(ep->pipe);
 	int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels;
 
@@ -608,10 +609,15 @@ static int data_ep_set_params(struct snd
 	else
 		ep->curpacksize = maxsize;
 
-	if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL)
+	if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) {
 		packs_per_ms = 8 >> ep->datainterval;
-	else
+		min_urbs = 3;
+		max_packs = MAX_PACKS_HS;
+	} else {
 		packs_per_ms = 1;
+		min_urbs = 2;
+		max_packs = MAX_PACKS;
+	}
 
 	if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
 		urb_packs = max(ep->chip->nrpacks, 1);
@@ -625,42 +631,23 @@ static int data_ep_set_params(struct snd
 	if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
 		urb_packs = min(urb_packs, 1U << sync_ep->syncinterval);
 
-	/* decide how many packets to be used */
-	if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
-		unsigned int minsize, maxpacks;
-		/* determine how small a packet can be */
-		minsize = (ep->freqn >> (16 - ep->datainterval))
-			  * (frame_bits >> 3);
-		/* with sync from device, assume it can be 12% lower */
-		if (sync_ep)
-			minsize -= minsize >> 3;
-		minsize = max(minsize, 1u);
-		total_packs = (period_bytes + minsize - 1) / minsize;
-		/* we need at least two URBs for queueing */
-		if (total_packs < 2) {
-			total_packs = 2;
-		} else {
-			/* and we don't want too long a queue either */
-			maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
-			total_packs = min(total_packs, maxpacks);
-		}
-	} else {
-		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
-			urb_packs >>= 1;
-		total_packs = MAX_URBS * urb_packs;
-	}
+	/* each URB must fit into one period */
+	urb_packs = min(urb_packs, period_bytes / maxsize);
+	urb_packs = max(1u, urb_packs);
 
-	ep->nurbs = (total_packs + urb_packs - 1) / urb_packs;
+	total_packs = min(MAX_QUEUE * packs_per_ms, max_packs);
+	ep->nurbs = total_packs / urb_packs;
 	if (ep->nurbs > MAX_URBS) {
 		/* too much... */
 		ep->nurbs = MAX_URBS;
-		total_packs = MAX_URBS * urb_packs;
-	} else if (ep->nurbs < 2) {
-		/* too little - we need at least two packets
+	} else if (ep->nurbs < min_urbs) {
+		/* too little - we need at least min_urbs URBs
 		 * to ensure contiguous playback/capture
 		 */
-		ep->nurbs = 2;
+		ep->nurbs = min_urbs;
+		urb_packs = total_packs / ep->nurbs;
 	}
+	total_packs = ep->nurbs * urb_packs;
 
 	/* allocate and initialize data urbs */
 	for (i = 0; i < ep->nurbs; i++) {


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux