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;