From alsa-devel-owner@alsa.jcu.cz  Sat Oct 31 00:15:02 1998
Received: from entry.jcu.cz (IDENT:perex@entry.jcu.cz [160.217.1.111])
	by marvin.jcu.cz (8.9.1a/8.9.1) with SMTP id AAA32750;
	Sat, 31 Oct 1998 00:13:40 +0100
Date: Sat, 31 Oct 1998 00:13:40 +0100 (CET)
From: Jaroslav Kysela <perex@jcu.cz>
To: Fred Floberg <emng@geocities.com>
cc: alsa-devel@jcu.cz
Subject: Re: ES1371 Bugs again..
In-Reply-To: <Pine.LNX.3.95.981030153900.23828A-100000@cyphyn.219.org>
Message-ID: <Pine.LNX.3.96.981030234433.30707E-100000@entry.jcu.cz>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
Reply-To: alsa-devel@alsa.jcu.cz
Sender: alsa-devel-owner@alsa.jcu.cz
Precedence: list

On Fri, 30 Oct 1998, Fred Floberg wrote:

> 
> Hi all,
> 
> I've downloaded the CVS tree with the ES1371 'codec write timeout' bugfix
> and compiled it with full debugging enabled. I'm now getting these errors:
> 
> snd: snd_pcm_interrupt_record: Oops, record interrupt when record isn't
> active!!!
> 
> snd: snd_pcm_interrupt_playback: Oops, playback interrupt when playback isn't
> active!!!

Looks that ES1371 have some small bugs... I'm sorry, but I don't have
ES1371 soundcard, thus this bug must be debugged with someone another.

> These occur at random times (I haven't been able to nail down precisely
> when the occur during program execution yet) when running my full-duplex
> test program. I've put the source code for that program up on my web
> page for your inspection at
> 
> http://www.geocities.com/Area51/Chamber/5555/duplex.c.gz
> 
> It is very possible that I'm doing something wrong in this test program,
> but I've tried everything I can think of to prevent playback underruns, etc.
> (which I've managed to minimize). I still get quite a delay between record
> and playback (on the SB16 this delay only occured after accessing the mixer
> during program run), and it seems to get much worse after an underrun occurs.

I looked to your code and it seems to be totaly broken. Variable nbytes
isn't initialized at begin of loop and you don't ensure that input byte
count must match output byte count. You must also using at minimum two
record buffers to avoid playback underruns. If you are using this simple
algorithm:

	while(1) {
	  x=snd_pcm_read();
	  snd_pcm_write(x);
	}

driver shouldn't get next playback data in right time (you must assume
that system can get time between read/write to another application).

This algorithm should work well (if playback underrun doesn't occurs):

	x=snd_pcm_read();	/* read first fragment */
	y=snd_pcm_read();	/* read second fragment */
	snd_pcm_write(x);
	snd_pcm_write(y);
	while(1) {
	  x = snd_pcm_read();
	  snd_pcm_write(x);
	}

This does mean, that playback is always 2 fragments after record. If you
want get smaller latency, you should decrease fragment size... If playback
underrun will occur, then some record data must be lost by algorithm to
minimize latency between record and playback...

> I've been working quite a bit on the ALSA support in Csound, moving it from
> a simple hack job to a more cleanly written public release. This support
> worked fine for my SB16, but I'm getting nowhere with my ES1371 AudioPCI
> card. Hence the reason for the full-duplex test program.

While looking and testing your code I found stupid bug in ALSA driver.
Here is fix for record status count variable (which should be negative in
previous code):

Index: pcm1_native.c
===================================================================
RCS file: /home/alsa/cvsroot/alsa-driver/kernel/pcm1/pcm1_native.c,v
retrieving revision 1.10
diff -u -r1.10 pcm1_native.c
--- pcm1_native.c       1998/09/15 09:12:01     1.10
+++ pcm1_native.c       1998/10/30 22:43:25
@@ -1229,11 +1229,11 @@
   } else {
     ptr = 0;
   }
-  if ( !pchn -> used )
+  if ( !pchn -> used ) {
     status.count = 0;
-   else
-    status.count = (pchn -> used - 1) * pchn -> block_size -
-                   (pchn -> block_size - pchn -> frag_size);
+  } else {
+    status.count = (pchn -> used - 1) * pchn -> block_size + pchn -> frag_size;
+  }
   status.free = ((pchn -> blocks - pchn -> used) * pchn -> block_size) - ptr;
   status.overrun = pchn -> xruns & 0x7fffffff; pchn -> xruns = 0;
   status.scount = pchn -> processed_bytes + ptr;


-----
Jaroslav Kysela <perex@jcu.cz>
Academic Computer Centre, University of South Bohemia
Branisovska 31, C. Budejovice, CZ-370 05 Czech Republic



