On Fri, 26 Jul 2013, Clemens Ladisch wrote: > Alan Stern wrote: > > On Thu, 25 Jul 2013, James Stone wrote: > >> The only slight difference I can see is that maybe the 3.10 uses > >> slightly higher CPU load than 3.5 at the ridiculously low latency of > >> 64 frames/period duplex. > > > > With the new patch, what you actually get is 44.1 frames/period (on > > average). > > In ALSA, the number of frames per period is a constant integer, and Jack > requires it to be a power of two. (Where "frame" is an audio frame, and > "period" is the interval between interrupts reported to user space.) > > With a sample rate of 44100 Hz and a packet rate of 8000 Hz, there > should be about 5.5 samples per packet. With a period size of 64 audio > frames, this results in about 11.6 packets per period. > > The driver does not completely fill URBs to ensure that interrupts > happen at period boundaries. Oho! I missed all that period_elapsed stuff in prepare_playback_urb()! But you don't do the same thing for recording URBs -- presumably because you can't tell in advance how many samples the device will send. This makes the calculation of the number of URBs more complicated. Revised patch below. James, can you try this out and send me the usbmon trace? At 64 frames/period this should end up using 4 URBs, which is the minimum requirement if there are no more than 8 packets per URB and an incompletely filled URB can contain as few as 1 packets. With this patch, there should be no difficulty going down to 32 or maybe even 16 frames/period. One more thing: I don't understand the calculations involving delay, est_delay, last_delay, and so on in pcm.c. Regardless, they appear not to be as good as they could be, because they don't use urb->start_frame. > > Another problem, not necessarily a bad one: The feedback data from the > > sound device indicates that its internal clock is actually running at > > 45168 Hz, even though it claims to be running at 44100. > > The feedback data is not measured in "real Hz" (wall clock time) but > relatively to the 8 kHz bus clock. Furthermore, it does not show the > device's internal clock but the rate at which the device wants to > receive frames; this can be higher at the beginning of a stream if the > device has an empty FIFO and wants to fill it up. Sorry, this was a miscalculation on my part. I divided the value from the device by 8000 instead of 8192. The correct calculation shows the internal clock is running at 44109 Hz. Close enough. 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_queued_packs, max_packs; int is_playback = usb_pipeout(ep->pipe); int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels; @@ -608,11 +609,21 @@ 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 + + /* high speed needs 10 USB uframes on the queue at all times */ + min_queued_packs = DIV_ROUND_UP(10, 8 / packs_per_ms); + max_packs = MAX_PACKS_HS; + } else { packs_per_ms = 1; + /* full speed needs one USB frame on the queue at all times */ + min_queued_packs = 1; + max_packs = MAX_PACKS; + } + max_packs = min(max_packs, MAX_QUEUE * packs_per_ms); + if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) { urb_packs = max(ep->chip->nrpacks, 1); urb_packs = min(urb_packs, (unsigned int) MAX_PACKS); @@ -625,42 +636,46 @@ 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); + /* each URB must fit into one period */ + urb_packs = min(urb_packs, period_bytes / maxsize); + urb_packs = max(1u, urb_packs); + + if (is_playback) { + unsigned int min_packs_per_period, urbs_per_period; + unsigned int queued_periods, leftover_packs; + + /* + * Allocate one more URB than needed to fill the minimum + * USB queue. The calculation is complicated because URBs + * don't always have the same number of packets. At the + * end of a period, the number of packets is reduced so + * that the URB just reaches the period's end. + */ + + /* how few packets and URBs can fill out a period? */ + min_packs_per_period = max(1u, period_bytes / maxsize); + urbs_per_period = DIV_ROUND_UP(min_packs_per_period, urb_packs); + + /* how many periods in the minimum queue size? */ + queued_periods = min_queued_packs / min_packs_per_period; + leftover_packs = min_queued_packs % min_packs_per_period; + + /* at least one more URB than needed for the minimum queue */ + ep->nurbs = 1 + queued_periods * urbs_per_period; + if (leftover_packs > 0) { + /* the queue might begin with a one-packet URB */ + ep->nurbs += 1 + DIV_ROUND_UP(leftover_packs - 1, + urb_packs); } } else { - while (urb_packs > 1 && urb_packs * maxsize >= period_bytes) - urb_packs >>= 1; - total_packs = MAX_URBS * urb_packs; + ep->nurbs = 1 + DIV_ROUND_UP(min_queued_packs, urb_packs); } - ep->nurbs = (total_packs + urb_packs - 1) / 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 - * to ensure contiguous playback/capture - */ - ep->nurbs = 2; + if (ep->nurbs * urb_packs > max_packs) { + /* too much -- URBs have too many packets */ + urb_packs = max_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