Skip site navigation (1)Skip section navigation (2)
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>