From owner-freebsd-current Sun Jun 11 13:27:20 2000 Delivered-To: freebsd-current@freebsd.org Received: from ns.tar.com (ns.tar.com [204.95.187.2]) by hub.freebsd.org (Postfix) with ESMTP id 51B8837B8E4; Sun, 11 Jun 2000 13:27:09 -0700 (PDT) (envelope-from dick@tar.com) Received: from test.tar.com (test [204.95.187.4]) by ns.tar.com (8.9.3/8.9.3) with ESMTP id PAA34200; Sun, 11 Jun 2000 15:26:58 -0500 (CDT) (envelope-from dick@tar.com) Received: by test.tar.com (Postfix, from userid 1000) id 2B25181D07; Sun, 11 Jun 2000 15:26:57 -0500 (CDT) Date: Sun, 11 Jun 2000 15:26:56 -0500 From: "Richard Seaman, Jr." To: "Jordan K. Hubbard" Cc: Brian Somers , Cameron Grant , current@FreeBSD.org Subject: PCM problems (was Re: cvs commit: src/sys/dev/sound/pcm channel.c) Message-ID: <20000611152656.A516@tar.com> References: <20000609144558.B566@tar.com> <66833.960646558@localhost> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="wRRV7LY7NUeQGEoC" X-Mailer: Mutt 1.0.1i In-Reply-To: <66833.960646558@localhost>; from jkh@zippy.cdrom.com on Sat, Jun 10, 2000 at 07:15:58AM -0700 Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG --wRRV7LY7NUeQGEoC Content-Type: text/plain; charset=us-ascii Note: CC list has been trimmed, and moved to -current from -committers as there are related comments on this issue on -current. On Sat, Jun 10, 2000 at 07:15:58AM -0700, Jordan K. Hubbard wrote: > I'm also finding that applications like mpg123 don't play audio > anymore whereas that very application does with a May 15th kernel, > that being the most recent "old" kernel I have lying around on this > laptop. If I play a WAV file with waveplay, it works fine. That > does tend to suggest that the speed at which you can cram data down > the audio subsystem's throat is a factor. > > - Jordan > > > On Fri, Jun 09, 2000 at 02:11:29PM -0500, Richard Seaman, Jr. wrote: > > > > > > If I just cat a .au file into /dev/audio, I get about 1/4 of a second > > > > of plan and then silence, with & without the patch. > > > > > > Your symptoms are different then. Don't know if the cause is the > > > same. > > > > Thinking about this some more, and as a followup to my last message, here's > > what I'm guessing is happening to you. > > > > You fill the device buffers very rapidly. Since chn_wrintr is not getting > > called as dma activity occurs, the only time the dma pointers can get updated > > and therefore indicate that the buffers aren't full is when you write to > > the buffers -- but you can't because they're already marked full. ie. > > you're deadlocked. The sound you hear is the dma buffers emptying, but your > > app never knows it happened because the buffers are still marked full. > > > > My case is the opposite side of the problem. My app doesn't always fill the > > buffers fast enough, and the dma pointers get corruped. > > > > I'd guess that those that don't have problems either a) are getting > > dma interrupts, or b) manage to fill the buffers at a rate that is > > neither too fast nor too slow. I don't know if all the reported pcm problems are related. In my case it appears that the pcm driver expects to get dma interrupts, but isn't getting them. Don't know if thats a hardware problem that is unique to my old Gus PnP Pro that I just recently pulled off the scrap heap and installed. However, a number of the problems others have reported were reproducable here. I've been running the attached patch to channel.c in sys/dev/sound/pcm. With this, I am able to play mp3 files with both mpq123 and RealPlayer7, wav files with waveplay, and 'cat XXX.au > /dev/audio' works fine. These patches don't solve the lack of dma interrupts, but appear to work around them. If you are getting dma interrupts, you will get a flood of "chn_wrintr" messages, and you will probably want to disable the related printf in this case. Also, your problem in this case is probably different than mine. Also, the "DEB(x) x" statement will generate some debugging junk in your log files, so you might want to comment this out if you don't want it. I haven't tried these for recording, so I have no idea if they work for recording. From comments Brian Somers has made, I gather this will probably still not solve his problems. I wonder if Cameron Grant could confirm whether the driver expects dma interrupts in all cases? -- Richard Seaman, Jr. email: dick@tar.com 5182 N. Maple Lane phone: 262-367-5450 Nashotah WI 53058 fax: 262-367-5852 --wRRV7LY7NUeQGEoC Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=diffs Index: channel.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/channel.c,v retrieving revision 1.28 diff -u -r1.28 channel.c --- channel.c 2000/06/06 22:30:22 1.28 +++ channel.c 2000/06/11 16:25:26 @@ -35,10 +35,10 @@ #define ISA_DMA(b) (((b)->chan >= 0 && (b)->chan != 4 && (b)->chan < 8)) #define CANCHANGE(c) (!(c)->buffer.dl) -/* + #define DEB(x) x -*/ -static void buf_clear(snd_dbuf *b, u_int32_t fmt, int length); + +static void buf_clear(snd_dbuf *b, u_int32_t fmt, int start, int length); static void chn_dmaupdate(pcm_channel *c); static void chn_wrintr(pcm_channel *c); static void chn_rdintr(pcm_channel *c); @@ -187,15 +187,20 @@ hwptr = chn_getptr(c); if (c->direction == PCMDIR_PLAY) { delta = (b->bufsize + hwptr - b->rp) % b->bufsize; + buf_clear(b, b->fmt, b->rp, delta); b->rp = hwptr; b->rl -= delta; b->fl += delta; - if (b->rl < 0) { + b->rl = 0; + b->fl = b->bufsize; + } + if (b->rl < 0) { DEB(printf("OUCH!(%d) rl %d(%d) delta %d bufsize %d hwptr %d rp %d(%d)\n", chn_updatecount++, b->rl, b_rl, delta, b->bufsize, hwptr, b->rp, b_rp)); } } else { delta = (b->bufsize + hwptr - b->fp) % b->bufsize; + buf_clear(b, b->fmt, b->fp, delta); b->fp = hwptr; b->rl += delta; b->fl -= delta; @@ -233,7 +238,7 @@ b->fl = b->bufsize - b->rl; b->underflow = 0; } else { - /* chn_dmaupdate(c); */ + chn_dmaupdate(c); } } @@ -275,7 +280,7 @@ b->fl -= l; b->fp = (b->fp + l) % b->bufsize; /* Clear the new space in the secondary buffer. */ - buf_clear(bs, bs->fmt, l); + /* buf_clear(bs, bs->fmt, l); */ /* Accumulate the total bytes of the moved samples. */ lacc += l; /* A feed to the DMA buffer is equivalent to an interrupt. */ @@ -340,7 +345,8 @@ chn_wrintr(pcm_channel *c) { snd_dbuf *b = &c->buffer; - + + printf ("chn_wrintr hit\n"); if (b->underflow && !(c->flags & CHN_F_MAPPED)) { /* printf("underflow return\n"); */ return; /* nothing new happened */ @@ -369,7 +375,7 @@ chn_wrfeed(c); else { while (chn_wrfeed(c) > 0); - buf_clear(b, b->fmt, b->fl); + /*buf_clear(b, b->fmt, b->fp, b->fl);*/ } chn_dmawakeup(c); if (c->flags & CHN_F_TRIGGERED) { @@ -394,7 +400,7 @@ * we are near to underflow condition, so to prevent * audio 'clicks' clear next b->fl bytes */ - buf_clear(b, b->fmt, b->fl); + buf_clear(b, b->fmt, b->fp, b->fl); if (b->rl < DMA_ALIGN_THRESHOLD) b->underflow = 1; } @@ -403,7 +409,7 @@ DEB(printf("underflow, flags 0x%08x rp %d rl %d\n", c->flags, b->rp, b->rl)); if (b->dl) { /* DMA was active */ b->underflow = 1; /* set underflow flag */ - buf_clear(b, b->fmt, b->bufsize); + buf_clear(b, b->fmt, 0, b->bufsize); } } } @@ -498,8 +504,9 @@ if (ret == EINTR || ret == ERESTART) break; } - } else + } /* else ret = 0; + */ c->flags &= ~CHN_F_WRITING; splx(s); return ret; @@ -611,7 +618,7 @@ bs->rl -= w; bs->rp = (bs->rp + w) % bs->bufsize; /* Clear the new space in the secondary buffer. */ - buf_clear(bs, bs->fmt, l); + /*buf_clear(bs, bs->fmt, bs->fp, l);*/ /* Accumulate the total bytes of the moved samples. */ bs->total += w; wacc += w; @@ -823,7 +830,7 @@ } static void -buf_clear(snd_dbuf *b, u_int32_t fmt, int length) +buf_clear(snd_dbuf *b, u_int32_t fmt, int start, int length) { int i; u_int16_t data, *p; @@ -846,8 +853,8 @@ if (fmt & AFMT_BIGENDIAN) data = ((data >> 8) & 0x00ff) | ((data << 8) & 0xff00); - i = b->fp; - p = (u_int16_t *)(b->buf + b->fp); + i = start; + p = (u_int16_t *)(b->buf + start); while (length > 0) { *p++ = data; length -= 2; @@ -873,7 +880,7 @@ b->prev_int_count = b->int_count = 0; b->underflow = 0; if (b->buf && b->bufsize > 0) - buf_clear(b, b->fmt, b->bufsize); + buf_clear(b, b->fmt, b->fp, b->bufsize); bs->rp = bs->fp = 0; bs->dl = bs->rl = 0; @@ -882,7 +889,7 @@ bs->prev_int_count = bs->int_count = 0; bs->underflow = 0; if (bs->buf && bs->bufsize > 0) - buf_clear(bs, bs->fmt, bs->bufsize); + buf_clear(bs, bs->fmt, bs->fp, bs->bufsize); } void @@ -1214,7 +1221,7 @@ bs->bufsize = bufsz; bs->rl = bs->rp = bs->fp = 0; bs->fl = bs->bufsize; - buf_clear(bs, bs->fmt, bs->bufsize); + buf_clear(bs, bs->fmt, bs->fp, bs->bufsize); bs->blkcnt = blkcnt; bs->blksz = blksz; b->blksz = c->setblocksize(c->devinfo, blksz); --wRRV7LY7NUeQGEoC-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message