summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2007-10-28 13:23:02 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2007-10-28 13:23:02 +0000
commit195759fd6ed67016b72aab3e8906fdddb34585bc (patch)
tree73ee647343dece6619b9912e5c1bc1f55b91e945
parentda8fed6a65f5ec09523534b36b00dcb08b449763 (diff)
the pointer we give to audio_fill_silence() may point in the middle of a
sample (eg. if write(2) have written an odd number of bytes and 16bit encoding is used), so we'll not properly write silence. To fix this, round start pointer to fill with silence uncomplete samples too. ok jakemsr@
-rw-r--r--sys/dev/audio.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/sys/dev/audio.c b/sys/dev/audio.c
index fa5819223e0..ef4dd0503cb 100644
--- a/sys/dev/audio.c
+++ b/sys/dev/audio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: audio.c,v 1.86 2007/10/27 08:52:47 ratchov Exp $ */
+/* $OpenBSD: audio.c,v 1.87 2007/10/28 13:23:01 ratchov Exp $ */
/* $NetBSD: audio.c,v 1.119 1999/11/09 16:50:47 augustss Exp $ */
/*
@@ -129,7 +129,7 @@ int audio_check_params(struct audio_params *);
void audio_set_blksize(struct audio_softc *, int, int);
void audio_calc_blksize(struct audio_softc *, int);
-void audio_fill_silence(struct audio_params *, u_char *, int);
+void audio_fill_silence(struct audio_params *, u_char *, u_char *, int);
int audio_silence_copyout(struct audio_softc *, int, struct uio *);
void audio_init_ringbuffer(struct audio_ringbuffer *);
@@ -1066,10 +1066,10 @@ audio_drain(struct audio_softc *sc)
cc = cb->blksize - (inp - cb->start) % cb->blksize;
if (sc->sc_pparams.sw_code) {
int ncc = cc / sc->sc_pparams.factor;
- audio_fill_silence(&sc->sc_pparams, inp, ncc);
+ audio_fill_silence(&sc->sc_pparams, cb->start, inp, ncc);
sc->sc_pparams.sw_code(sc->hw_hdl, inp, ncc);
} else
- audio_fill_silence(&sc->sc_pparams, inp, cc);
+ audio_fill_silence(&sc->sc_pparams, cb->start, inp, cc);
inp += cc;
if (inp >= cb->end)
inp = cb->start;
@@ -1342,11 +1342,21 @@ audio_calc_blksize(struct audio_softc *sc, int mode)
}
void
-audio_fill_silence(struct audio_params *params, u_char *p, int n)
+audio_fill_silence(struct audio_params *params, u_char *start, u_char *p, int n)
{
+ size_t rounderr;
u_char auzero0, auzero1 = 0; /* initialize to please gcc */
int nfill = 1;
+ /*
+ * p may point the middle of a sample; round it to the
+ * beginning of the sample, so we overwrite partially written
+ * ones.
+ */
+ rounderr = (p - start) % (params->precision / 8);
+ p -= rounderr;
+ n += rounderr;
+
switch (params->encoding) {
case AUDIO_ENCODING_ULAW:
auzero0 = 0x7f;
@@ -1403,7 +1413,7 @@ audio_silence_copyout(struct audio_softc *sc, int n, struct uio *uio)
int k;
u_char zerobuf[128];
- audio_fill_silence(&sc->sc_rparams, zerobuf, sizeof zerobuf);
+ audio_fill_silence(&sc->sc_rparams, zerobuf, zerobuf, sizeof zerobuf);
error = 0;
while (n > 0 && uio->uio_resid > 0 && !error) {
@@ -1568,10 +1578,10 @@ audio_write(dev_t dev, struct uio *uio, int ioflag)
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, einp, ncc);
+ 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, einp, cc);
+ audio_fill_silence(&sc->sc_pparams, cb->start, einp, cc);
}
}
return (error);
@@ -1859,7 +1869,7 @@ audio_mmap(dev_t dev, off_t off, int prot)
if (!cb->mmapped) {
cb->mmapped = 1;
if (cb == &sc->sc_pr) {
- audio_fill_silence(&sc->sc_pparams, cb->start, cb->bufsize);
+ audio_fill_silence(&sc->sc_pparams, cb->start, cb->start, cb->bufsize);
s = splaudio();
if (!sc->sc_pbus && !sc->sc_pr.pause)
(void)audiostartp(sc);
@@ -1963,10 +1973,10 @@ audio_pint_silence(struct audio_softc *sc, struct audio_ringbuffer *cb,
if (sc->sc_pparams.sw_code) {
int ncc = cc / sc->sc_pparams.factor;
- audio_fill_silence(&sc->sc_pparams, inp, ncc);
+ audio_fill_silence(&sc->sc_pparams, cb->start, inp, ncc);
sc->sc_pparams.sw_code(sc->hw_hdl, inp, ncc);
} else
- audio_fill_silence(&sc->sc_pparams, inp, cc);
+ audio_fill_silence(&sc->sc_pparams, cb->start, inp, cc);
} else {
DPRINTFN(5, ("audio_pint_silence: already silent cc=%d inp=%p\n", cc, inp));
@@ -1980,10 +1990,10 @@ audio_pint_silence(struct audio_softc *sc, struct audio_ringbuffer *cb,
if (sc->sc_pparams.sw_code) {
int ncc = cc / sc->sc_pparams.factor;
- audio_fill_silence(&sc->sc_pparams, inp, ncc);
+ audio_fill_silence(&sc->sc_pparams, cb->start, inp, ncc);
sc->sc_pparams.sw_code(sc->hw_hdl, inp, ncc);
} else
- audio_fill_silence(&sc->sc_pparams, inp, cc);
+ audio_fill_silence(&sc->sc_pparams, cb->start, inp, cc);
}
}