Date: Sun, 28 Oct 2001 19:40:03 -0800 (PST) From: Ted Faber <faber@lunabase.org> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/31445: cat sound.au > /dev/audio fails for sounds < 4KB Message-ID: <200110290340.f9T3e3M59538@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/31445; it has been noted by GNATS. From: Ted Faber <faber@lunabase.org> To: freebsd-gnats-submit@FreeBSD.org Cc: faber@lunabase.org Subject: Re: kern/31445: cat sound.au > /dev/audio fails for sounds < 4KB Date: Sun, 28 Oct 2001 19:29:39 -0800 This may be a resumbission. I sent it once PGP signed, and that may not fly. I've got a fix for this. It may not be ideal, but I think it characterizes the problem well enough that someone who cares can fine tune it. The problem is that if a sound is small enough, it never apsses the low water mark in chn_start to start the playout process. This patch looks for small sounds in chn_flush. If it detects such a sound (a partially filled soft output buffer when the channel is not triggered), it pads the output buffer with silence and starts it playing. A patch follows, relative to /sys/dev/sound/pcm --- buffer.c.orig Sun Oct 28 18:31:14 2001 +++ buffer.c Sun Oct 28 18:33:09 2001 @@ -218,6 +218,28 @@ } void +sndbuf_padsilence(struct snd_dbuf *b, unsigned int length) +{ + int i; + u_char data, *p; + unsigned int len = length; + + if (b->fmt & AFMT_SIGNED) + data = 0x00; + else + data = 0x80; + + i = sndbuf_getfreeptr(b); + p = sndbuf_getbuf(b); + while (len) { + p[i++] = data; + len--; + if ( i >= b->bufsize ) i = 0; + } + b->rl += length; +} + +void sndbuf_reset(struct snd_dbuf *b) { b->hp = 0; --- buffer.h.orig Sun Oct 28 18:31:19 2001 +++ buffer.h Sun Oct 28 18:32:15 2001 @@ -45,6 +45,7 @@ int sndbuf_remalloc(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz); void sndbuf_reset(struct snd_dbuf *b); void sndbuf_clear(struct snd_dbuf *b, unsigned int length); +void sndbuf_padsilence(struct snd_dbuf *b, unsigned int length); void sndbuf_fillsilence(struct snd_dbuf *b); u_int32_t sndbuf_getfmt(struct snd_dbuf *b); --- channel.c.orig Sun Oct 28 18:31:05 2001 +++ channel.c Sun Oct 28 18:41:40 2001 @@ -555,8 +555,17 @@ CHN_LOCKASSERT(c); KASSERT(c->direction == PCMDIR_PLAY, ("chn_wrupdate on bad channel")); DEB(printf("chn_flush c->flags 0x%08x\n", c->flags)); - if (!(c->flags & CHN_F_TRIGGERED)) - return 0; + if (!(c->flags & CHN_F_TRIGGERED)) + if ( sndbuf_getready(bs) > 0 && + sndbuf_getready(bs) < sndbuf_getfree(b) ) { + /* this is probably a short sound, pad it out with + silence and start the driver playing it. */ + sndbuf_padsilence(bs, sndbuf_getfree(b)); + chn_start(c, 1); + chn_sleep(c, "pcmflu", hz / 10); + } + else + return 0; c->flags |= CHN_F_CLOSING; resid = sndbuf_getready(bs) + sndbuf_getready(b); To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200110290340.f9T3e3M59538>