Apply by doing:
	cd /usr/src
	patch -p0 < 005_audio.patch

Then build and install a new kernel.

Index: sys/dev/audio.c
===================================================================
RCS file: /cvs/src/sys/dev/audio.c,v
retrieving revision 1.101
diff -u -p sys/dev/audio.c
--- sys/dev/audio.c	16 Jan 2009 23:07:33 -0000	1.101
+++ sys/dev/audio.c	24 Apr 2009 13:54:02 -0000
@@ -860,8 +860,6 @@ audio_init_ringbuffer(struct audio_ringbuffer *rp)
 	rp->stamp_last = 0;
 	rp->drops = 0;
 	rp->pdrops = 0;
-	rp->copying = 0;
-	rp->needfill = 0;
 	rp->mmapped = 0;
 }
 
@@ -1138,12 +1136,6 @@ audio_drain(struct audio_softc *sc)
 	 * XXX This should be done some other way to avoid
 	 * playing silence.
 	 */
-#ifdef DIAGNOSTIC
-	if (cb->copying) {
-		printf("audio_drain: copying in progress!?!\n");
-		cb->copying = 0;
-	}
-#endif
 	drops = cb->drops;
 	error = 0;
 	s = splaudio();
@@ -1233,7 +1225,7 @@ audio_read(dev_t dev, struct uio *uio, int ioflag)
 	struct audio_softc *sc = audio_cd.cd_devs[unit];
 	struct audio_ringbuffer *cb = &sc->sc_rr;
 	u_char *outp;
-	int error, s, used, cc, n;
+	int error, s, cc, n, resid;
 
 	if (cb->mmapped)
 		return EINVAL;
@@ -1279,7 +1271,7 @@ audio_read(dev_t dev, struct uio *uio, int ioflag)
 		}
 		return (error);
 	}
-	while (uio->uio_resid > 0 && !error) {
+	while (uio->uio_resid > 0) {
 		s = splaudio();
 		while (cb->used <= 0) {
 			if (!sc->sc_rbus && !sc->sc_rr.pause) {
@@ -1302,34 +1294,28 @@ audio_read(dev_t dev, struct uio *uio, int ioflag)
 				return error;
 			}
 		}
-		used = cb->used;
+		resid = uio->uio_resid * sc->sc_rparams.factor;
 		outp = cb->outp;
-		cb->copying = 1;
-		splx(s);
-		cc = used - cb->usedlow; /* maximum to read */
+		cc = cb->used - cb->usedlow; /* maximum to read */
 		n = cb->end - outp;
-		if (n < cc)
-			cc = n;	/* don't read beyond end of buffer */
-
-		 /* and no more than we want */
-		if (uio->uio_resid < cc / sc->sc_rparams.factor)
-			cc = uio->uio_resid * sc->sc_rparams.factor;
-
+		if (cc > n)
+			cc = n;		/* don't read beyond end of buffer */
+		
+		if (cc > resid)
+			cc = resid;	/* and no more than we want */
+		cb->used -= cc;
+		cb->outp += cc;
+		if (cb->outp >= cb->end)
+			cb->outp = cb->start;
+		splx(s);
+		DPRINTFN(1,("audio_read: outp=%p, cc=%d\n", outp, cc));
 		if (sc->sc_rparams.sw_code)
 			sc->sc_rparams.sw_code(sc->hw_hdl, outp, cc);
-		DPRINTFN(1,("audio_read: outp=%p, cc=%d\n", outp, cc));
 		error = uiomove(outp, cc / sc->sc_rparams.factor, uio);
-		used -= cc;
-		outp += cc;
-		if (outp >= cb->end)
-			outp = cb->start;
-		s = splaudio();
-		cb->outp = outp;
-		cb->used = used;
-		cb->copying = 0;
-		splx(s);
+		if (error)
+			return error;
 	}
-	return (error);
+	return 0;
 }
 
 void
@@ -1473,8 +1459,8 @@ audio_write(dev_t dev, struct uio *uio, int ioflag)
 	int unit = AUDIOUNIT(dev);
 	struct audio_softc *sc = audio_cd.cd_devs[unit];
 	struct audio_ringbuffer *cb = &sc->sc_pr;
-	u_char *inp, *einp;
-	int saveerror, error, s, n, cc, used;
+	u_char *inp;
+	int error, s, n, cc, resid, avail;
 
 	DPRINTFN(2, ("audio_write: sc=%p(unit=%d) count=%d used=%d(hi=%d)\n", sc, unit,
 		 uio->uio_resid, sc->sc_pr.used, sc->sc_pr.usedhigh));
@@ -1513,12 +1499,18 @@ audio_write(dev_t dev, struct uio *uio, int ioflag)
 	    sc->sc_pparams.precision, sc->sc_pparams.channels,
 	    sc->sc_pparams.sw_code, sc->sc_pparams.factor));
 
-	error = 0;
-	while (uio->uio_resid > 0 && !error) {
+	while (uio->uio_resid > 0) {
 		s = splaudio();
 		while (cb->used >= cb->usedhigh) {
 			DPRINTFN(2, ("audio_write: sleep used=%d lowat=%d hiwat=%d\n",
 				 cb->used, cb->usedlow, cb->usedhigh));
+			if (!sc->sc_pbus && !cb->pause) {
+				error = audiostartp(sc);
+				if (error) {
+					splx(s);
+					return error;
+				}
+			}
 			if (ioflag & IO_NDELAY) {
 				splx(s);
 				return (EWOULDBLOCK);
@@ -1531,103 +1523,36 @@ audio_write(dev_t dev, struct uio *uio, int ioflag)
 				return error;
 			}
 		}
-		used = cb->used;
+		resid = uio->uio_resid * sc->sc_pparams.factor;
+		avail = cb->end - cb->inp;
 		inp = cb->inp;
-		cb->copying = 1;
-		splx(s);
-		cc = cb->usedhigh - used;	/* maximum to write */
-		n = cb->end - inp;
-		if (sc->sc_pparams.factor != 1) {
-			/* Compensate for software coding expansion factor. */
-			n /= sc->sc_pparams.factor;
-			cc /= sc->sc_pparams.factor;
-		}
-		if (n < cc)
-			cc = n;			/* don't write beyond end of buffer */
-		if (uio->uio_resid < cc)
-			cc = uio->uio_resid;	/* and no more than we have */
-
-#ifdef DIAGNOSTIC
+		cc = cb->usedhigh - cb->used;
+		if (cc > resid)
+			cc = resid;
+		if (cc > avail)
+			cc = avail;
+		cb->inp += cc;
+		if (cb->inp >= cb->end)
+			cb->inp = cb->start;
+		cb->used += cc;
 		/*
-		 * This should never happen since the block size and and
-		 * block pointers are always nicely aligned.
+		 * This is a very suboptimal way of keeping track of
+		 * silence in the buffer, but it is simple.
 		 */
-		if (cc == 0) {
-			printf("audio_write: cc == 0, swcode=%p, factor=%d\n",
-			    sc->sc_pparams.sw_code, sc->sc_pparams.factor);
-			cb->copying = 0;
-			return EINVAL;
-		}
-#endif
+		sc->sc_sil_count = 0;
+		splx(s);
+		cc /= sc->sc_pparams.factor;
 		DPRINTFN(1, ("audio_write: uiomove cc=%d inp=%p, left=%d\n",
 		    cc, inp, uio->uio_resid));
-		n = uio->uio_resid;
 		error = uiomove(inp, cc, uio);
-		cc = n - uio->uio_resid; /* number of bytes actually moved */
-#ifdef AUDIO_DEBUG
 		if (error)
-			printf("audio_write:(1) uiomove failed %d; cc=%d inp=%p\n",
-			    error, cc, inp);
-#endif
-		/*
-		 * Continue even if uiomove() failed because we may have
-		 * gotten a partial block.
-		 */
-
+			return 0;
 		if (sc->sc_pparams.sw_code) {
 			sc->sc_pparams.sw_code(sc->hw_hdl, inp, cc);
-			/* Adjust count after the expansion. */
-			cc *= sc->sc_pparams.factor;
 			DPRINTFN(1, ("audio_write: expanded cc=%d\n", cc));
 		}
-
-		einp = cb->inp + cc;
-		if (einp >= cb->end)
-			einp = cb->start;
-
-		s = splaudio();
-		/*
-		 * This is a very suboptimal way of keeping track of
-		 * silence in the buffer, but it is simple.
-		 */
-		sc->sc_sil_count = 0;
-
-		cb->inp = einp;
-		cb->used += cc;
-		/* If the interrupt routine wants the last block filled AND
-		 * the copy did not fill the last block completely it needs to
-		 * be padded.
-		 */
-		if (cb->needfill &&
-		    (inp  - cb->start) / cb->blksize ==
-		    (einp - cb->start) / cb->blksize) {
-			/* Figure out how many bytes there is to a block boundary. */
-			cc = cb->blksize - (einp - cb->start) % cb->blksize;
-			DPRINTF(("audio_write: partial fill %d\n", cc));
-		} else
-			cc = 0;
-		cb->needfill = 0;
-		cb->copying = 0;
-		if (!sc->sc_pbus && !cb->pause) {
-			saveerror = error;
-			error = audiostartp(sc);
-			if (saveerror != 0) {
-				/* Report the first error that occurred. */
-				error = saveerror;
-			}
-		}
-		splx(s);
-		if (cc) {
-			DPRINTFN(1, ("audio_write: fill %d\n", cc));
-			if (sc->sc_pparams.sw_code) {
-				int ncc = cc / sc->sc_pparams.factor;
-				audio_fill_silence(&sc->sc_pparams, cb->start, einp, ncc);
-				sc->sc_pparams.sw_code(sc->hw_hdl, einp, ncc);
-			} else
-				audio_fill_silence(&sc->sc_pparams, cb->start, einp, cc);
-		}
 	}
-	return (error);
+	return 0;
 }
 
 int
@@ -2115,30 +2040,24 @@ audio_pint(void *v)
 	cb->used -= blksize;
 	if (cb->used < blksize) {
 		/* we don't have a full block to use */
-		if (cb->copying) {
-			/* writer is in progress, don't disturb */
-			cb->needfill = 1;
-			DPRINTFN(1, ("audio_pint: copying in progress\n"));
-		} else {
-			inp = cb->inp;
-			cc = blksize - (inp - cb->start) % blksize;
-			if (cb->pause)
-				cb->pdrops += cc;
-			else {
-				cb->drops += cc;
-				sc->sc_playdrop += cc;
-			}
-			audio_pint_silence(sc, cb, inp, cc);
-			inp += cc;
-			if (inp >= cb->end)
-				inp = cb->start;
-			cb->inp = inp;
-			cb->used += cc;
-
-			/* Clear next block so we keep ahead of the DMA. */
-			if (cb->used + cc < cb->usedhigh)
-				audio_pint_silence(sc, cb, inp, blksize);
+		inp = cb->inp;
+		cc = blksize - (inp - cb->start) % blksize;
+		if (cb->pause)
+			cb->pdrops += cc;
+		else {
+			cb->drops += cc;
+			sc->sc_playdrop += cc;
 		}
+		audio_pint_silence(sc, cb, inp, cc);
+		inp += cc;
+		if (inp >= cb->end)
+			inp = cb->start;
+		cb->inp = inp;
+		cb->used += cc;
+
+		/* Clear next block so we keep ahead of the DMA. */
+		if (cb->used + cc < cb->usedhigh)
+			audio_pint_silence(sc, cb, inp, blksize);
 	}
 
 	DPRINTFN(5, ("audio_pint: outp=%p cc=%d\n", cb->outp, blksize));
@@ -2232,7 +2151,7 @@ audio_rint(void *v)
 		if (cb->outp >= cb->end)
 			cb->outp = cb->start;
 		cb->used -= blksize;
-	} else if (cb->used >= cb->usedhigh && !cb->copying) {
+	} else if (cb->used >= cb->usedhigh) {
 		DPRINTFN(1, ("audio_rint: drops %lu\n", cb->drops));
 		cb->drops += blksize;
 		cb->outp += blksize;
