Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Jul 2008 17:24:04 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 145900 for review
Message-ID:  <200807251724.m6PHO4Nc019818@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=145900

Change 145900 by hselasky@hselasky_laptop001 on 2008/07/25 17:23:56

	
	Significantly improve USB audio playback and recording latency.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb2/sound/uaudio2.c#8 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb2/sound/uaudio2.c#8 (text+ko) ====

@@ -95,7 +95,7 @@
 #define	UAUDIO_NCHANBUFS        2	/* number of outstanding request */
 #define	UAUDIO_NFRAMES         25	/* ms of sound in each request */
 #define	UAUDIO_RECURSE_LIMIT   24	/* rounds */
-#define	UAUDIO_DEFAULT_BUFSZ  (16*1024)	/* bytes */
+#define	UAUDIO_DEFAULT_BUFSZ  ((2 * 96000 * 4 * 2) / (1000 / UAUDIO_NCHANBUFS))	/* bytes */
 
 #define	MAKE_WORD(h,l) (((h) << 8) | (l))
 #define	BIT_TEST(bm,bno) (((bm)[(bno) / 8] >> (7 - ((bno) % 8))) & 1)
@@ -223,7 +223,6 @@
 	struct uaudio_mixer_node *sc_mixer_root;
 	struct uaudio_mixer_node *sc_mixer_curr;
 
-	uint32_t sc_buffer_size;
 	uint32_t sc_mix_info;
 	uint32_t sc_recsrc_info;
 
@@ -694,11 +693,9 @@
 	struct uaudio_softc *sc = device_get_softc(device_get_parent(dev));
 	char status[SND_STATUSLEN];
 
-	sc->sc_buffer_size = pcm_getbuffersize(dev, 4096, UAUDIO_DEFAULT_BUFSZ, 65536);
-
 	if (bootverbose) {
 		device_printf(dev, "using a default buffer "
-		    "size of %u bytes\n", sc->sc_buffer_size);
+		    "size of %u bytes\n", UAUDIO_DEFAULT_BUFSZ);
 	}
 	uaudio_mixer_init(sc);
 
@@ -1134,10 +1131,29 @@
 {
 	struct uaudio_chan *ch = xfer->priv_sc;
 	uint32_t *p_len = xfer->frlengths;
+	uint32_t total = (sndbuf_getblkcnt(ch->pcm_buf) *
+	    sndbuf_getblksz(ch->pcm_buf)) / 2;
+	uint32_t blockcount;
 	uint32_t n;
-	uint32_t total = (ch->bytes_per_frame * xfer->nframes);
 	uint32_t offset;
 
+	/* allow dynamic sizing of play buffer */
+	blockcount = total / ch->bytes_per_frame;
+
+	/* align to 8 units */
+	blockcount &= ~7;
+
+	/* range check - min */
+	if (blockcount == 0) {
+		blockcount = 8;
+	}
+	/* range check - max */
+	if (blockcount > xfer->max_frame_count) {
+		blockcount = xfer->max_frame_count;
+	}
+	/* compute the total length */
+	total = blockcount * ch->bytes_per_frame;
+
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
 tr_transferred:
@@ -1153,15 +1169,17 @@
 			    "exceeds maximum, %d!\n",
 			    ch->bytes_per_frame,
 			    xfer->max_frame_size);
-			return;
+			break;
 		}
-		for (n = 0; n < xfer->nframes; n++) {
+		/* setup frame length */
+		xfer->nframes = blockcount;
+		for (n = 0; n != blockcount; n++) {
 			p_len[n] = ch->bytes_per_frame;
 		}
 
 		if (ch->end == ch->start) {
 			DPRINTF(0, "no buffer!\n");
-			return;
+			break;
 		}
 		DPRINTF(5, "transfer %d bytes\n", total);
 
@@ -1185,14 +1203,15 @@
 		}
 
 		usb2_start_hardware(xfer);
-		return;
+		break;
 
 	default:			/* Error */
 		if (xfer->error == USB_ERR_CANCELLED) {
-			return;
+			break;
 		}
 		goto tr_transferred;
 	}
+	return;
 }
 
 static void
@@ -1202,10 +1221,29 @@
 	uint32_t *p_len = xfer->frlengths;
 	uint32_t n;
 	uint32_t m;
-	uint32_t total = (xfer->nframes * ch->bytes_per_frame);
+	uint32_t total = (sndbuf_getblkcnt(ch->pcm_buf) *
+	    sndbuf_getblksz(ch->pcm_buf)) / 2;
+	uint32_t blockcount;
 	uint32_t offset0;
 	uint32_t offset1;
 
+	/* allow dynamic sizing of play buffer */
+	blockcount = total / ch->bytes_per_frame;
+
+	/* align to 8 units */
+	blockcount &= ~7;
+
+	/* range check - min */
+	if (blockcount == 0) {
+		blockcount = 8;
+	}
+	/* range check - max */
+	if (blockcount > xfer->max_frame_count) {
+		blockcount = xfer->max_frame_count;
+	}
+	/* compute the total length */
+	total = blockcount * ch->bytes_per_frame;
+
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
 tr_transferred:
@@ -1218,7 +1256,7 @@
 
 		offset0 = 0;
 
-		for (n = 0; n < xfer->nframes; n++) {
+		for (n = 0; n != xfer->nframes; n++) {
 
 			offset1 = offset0;
 
@@ -1253,7 +1291,8 @@
 			    xfer->max_frame_size);
 			return;
 		}
-		for (n = 0; n < xfer->nframes; n++) {
+		xfer->nframes = blockcount;
+		for (n = 0; n != xfer->nframes; n++) {
 			p_len[n] = ch->bytes_per_frame;
 		}
 
@@ -1283,16 +1322,16 @@
 	uint8_t alt_index;
 	usb2_error_t err;
 
-	ch->buf = malloc(sc->sc_buffer_size, M_DEVBUF, M_WAITOK | M_ZERO);
+	ch->buf = malloc(UAUDIO_DEFAULT_BUFSZ, M_DEVBUF, M_WAITOK | M_ZERO);
 
 	if (ch->buf == NULL) {
 		goto error;
 	}
-	if (sndbuf_setup(b, ch->buf, sc->sc_buffer_size) != 0) {
+	if (sndbuf_setup(b, ch->buf, UAUDIO_DEFAULT_BUFSZ) != 0) {
 		goto error;
 	}
 	ch->start = ch->buf;
-	ch->end = ch->buf + sc->sc_buffer_size;
+	ch->end = ch->buf + UAUDIO_DEFAULT_BUFSZ;
 	ch->cur = ch->buf;
 	ch->pcm_ch = c;
 	ch->pcm_mtx = c->lock;
@@ -1380,11 +1419,7 @@
 int
 uaudio_chan_set_param_blocksize(struct uaudio_chan *ch, uint32_t blocksize)
 {
-	uint32_t max = sndbuf_getmaxsize(ch->pcm_buf);
-
-	RANGE(blocksize, 128, max / 2);
-
-	uaudio_chan_set_param_fragments(ch, blocksize, max / blocksize);
+	uaudio_chan_set_param_fragments(ch, blocksize, 0 - 1);
 
 	return (ch->block_size);
 }
@@ -1396,17 +1431,10 @@
 	uint32_t max = sndbuf_getmaxsize(ch->pcm_buf);
 
 	RANGE(blocksize, 128, max / 2);
+
+	blockcount = max / blocksize;
 	RANGE(blockcount, 2, 512);
 
-	while ((blocksize * blockcount) > max) {
-		if ((blockcount >> 1) >= 2)
-			blockcount >>= 1;
-		else if ((blocksize >> 1) >= 128)
-			blocksize >>= 1;
-		else
-			break;
-	}
-
 	if ((sndbuf_getblksz(ch->pcm_buf) != blocksize) ||
 	    (sndbuf_getblkcnt(ch->pcm_buf) != blockcount)) {
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807251724.m6PHO4Nc019818>