Bruce Paterson wrote:
> 

I got zero feedback on the problem below, so I thought I'd add the code
segment and see
if anyone can tell me what I'm doing wrong !
See code below.

> HELP !
> I've tried everything I can think of and I'm at a loss.
> 
> Setup:
> alsa 0.9.0rc2
> soundcard Terratec EWS88 (ice1712 driver)
> direct hw:0,0 using snd_pcm_readi & writei with descriptor polling.
> length approx 50s similtaneous read & write. read from all channels.
> modified 'envy24setup' to preset hardware levels on startup
> full restart of sound system each 'pass' (new handles etc.)
> 
> Problem:
> The first pass works fine with beautiful audio.
> The next pass the output is badly distorted (sounds like an incomplete
> buffer or something), but
> no errors reported, no under/overruns.... only evidence that something
> is wrong is to listen to it.
> 
> What fixes it:
> Waiting. Yup...if I wait > 1 minute before the 2nd pass then that is
> also fine. Something 'happens'
> in that time to make it all ok again.
> This is why it's taken me ages to actually notice the problem at all !
> (program has been running
> for months).
> 
> What *doesn't* help:
> Not doing a full sound restart between passes (ie. merely doing a drop
> afterwards, then restart with
> prepare & start, leaving pcm handles alive).
> Playing a wav file with 'aplay' in between passes.
> Exiting from my program and starting again between passes.
> adding hw_free commands prior to close of the in & out handles.

Recent observations: The distortion (buffer problem ?) seems to occur a
fixed interval after
the sound is started after a good delay then stopped, then started
again. ie. If I send shorter bursts
I can get two good ones in beofre a bad one (quite consistantly),
whereas only 1 good longer burst.

Also, if I send a really really long burst (ie continueous) the problem
never occurs. It's only if I stop
then start again !

Here is the code segment in question. The periodsize is setup to be 1/4
of the buffersize which is set
to the maximum the soundcard will give me. When restarting the soundcard
is initialised from scratch
(new fd's), but I tried without doing this and it makes no difference):

        /* Get one full width buffer, buffersize is in frames. */
        outbuf = (char *)calloc(out_buffer_size * OUTCH,
snd_pcm_format_width(format) / 8);
                /* calloc since we want silence initially on output */
        inbuf = (char *)calloc(in_buffer_size * INCH,
snd_pcm_format_width(format) / 8);

        /* Start the ball rolling */
        snd_pcm_prepare(outhand);
        snd_pcm_prepare(inhand);
        snd_pcm_reset(outhand);
        snd_pcm_reset(inhand);
        snd_pcm_start(inhand);

        /* This is the IO loop */
        outp = a buffer that contains what I want to output;
        outl = length of said buffer;                   
        outs = (QUIET * (Fs/1000));     /* Pre-silence output time */
        Delay *= Fs;                    /* Change to sample count */
        Delay += QUIET * (Fs/1000);     /* Always delay the output quiet period as
well */
        dc = Delay;
        samps = N; 
        ocopy = 0;
        /* inptrs already point to fmptrs */
        for(;;)
        {
                if(outs)
                        out = outs;
                else
                {
                        if(outl)
                        {       
                                if( ocopy == 0 )
                                {
                                        ocopy = 1;
                                        /* Copy from single channel full buffer to 
full width one */
                                        sampl = (long *)outp;
                                        sampm = (long *)outbuf;

                                        for(x=0; x < out_buffer_size; x++)
                                        {
                                                /* only 2 channels output (180 deg out 
of phase) */
                                                *sampm = *sampl++;
                                                sampm += OUTCH;          /* Skip over 
other output channels */
                                                if( x > outl )
                                                        break;
                                        }
                                        out = outl;
                                }
                        }
                        else
                                out = out_buffer_size;          /* Silence after */
                }

                /* See if ready for output data yet */
                poll(outfds, ocount, -1);
                snd_pcm_poll_descriptors_revents(outhand, outfds, ocount,
&revents);
                if (revents & POLLERR)
                {
                        fprintf(stderr, "Tx Poll failed\n");
                        err = -1;
                        break;
                }
                if (revents & POLLOUT)
                {
                        err = snd_pcm_writei(outhand, (void *)outbuf, out > 
out_buffer_size ?
out_buffer_size  : out );
                        if( err < 0 )
                        {
                                /* EAGAIN Shouldn't happen now since we're polling 
first */
                                if( err != -EAGAIN )
                                {
                                        fprintf(stderr, "Write failed %s", 
snd_strerror(err));
                                        break;
                                }
                        }
                        else
                        {
                                if(outs)
                                        outs -= err;
                                else
                                {
                                        if(outl)
                                        {
                                                outl -= err;
                                                outp += err * 
snd_pcm_format_width(format)/8;
                                                ocopy = 0;
                                                if( outl == 0 )
                                                {
                                                        /* Finished actual output. Now 
fill buffer with silence again */
                                                        sampm = (long *)outbuf;
                                                        for(x=0; x < out_buffer_size; 
x++)
                                                        {
                                                                *sampm++ = 0;
                                                                *sampm = 0;
                                                                sampm += OUTCH-1; /* 
Skip over other output channels */
                                                        }
                                                }
                                        }
                                }
                        }       
                }

                /* See if data ready to be read yet... we started sampling earlier. */
                poll(infds, icount, -1);
                snd_pcm_poll_descriptors_revents(inhand, infds, icount,
&revents);
                if (revents & POLLERR)
                {
                        fprintf(stderr, "Rx Poll failed\n");
                        err = -1;
                        break;
                }
                if( !((revents & POLLIN) || (revents & POLLPRI)) )
                        continue;

                if(dc)
                {
                        err = snd_pcm_readi(inhand, inbuf, dc > in_buffer_size ?
in_buffer_size : dc);
                        if(err < 0)
                        {
                                if( err != -EAGAIN )
                                {
                                        fprintf(stderr,"Read error at %ld: %s\n", 
Delay-dc,
snd_strerror(err));
                                        break;
                                }
                        }
                        else
                        {
                                dc -= err;
                                if( dc )
                                        continue;
                        }
                }

                /* Finally actually record some real stuff */
                err = snd_pcm_readi(inhand, inbuf, samps > in_buffer_size ?
in_buffer_size : samps);
                if(err < 0)
                {
                        if( err != -EAGAIN )
                        {
                                /* No point in underrun recovery in this application 
so abort */
                                fprintf(stderr,"Read error at %ld: %s\n", N-samps,
snd_strerror(err));
                                break;
                        }
                }
                else
                {
                        samps -= err;
                        /* Copy from full width buffer to channels */
                        for(y=0; y < channels; y++)
                        {
                                sampl = (long *)inbuf + y;
                                sampm = (long *)inptrs[y];
                                for(x=0; x < err; x++)
                                {
                                        *sampm++ = *sampl;
                                        sampl += INCH;
                                }
                                inptrs[y] += err * snd_pcm_format_width(format)/8;
                        }
                        if( samps <= 0 )
                                break;
                }
        }
        fprintf(stderr,"Sampling Completed\n");
        snd_pcm_unlink(outhand);
        snd_pcm_drop(outhand);
        snd_pcm_drop(inhand);
        snd_pcm_hw_free(outhand);
        snd_pcm_close(outhand);
        snd_pcm_hw_free(inhand);
        snd_pcm_close(inhand);

        /* Free up temporary memory */
        free(inbuf); free(outbuf);

-- 
Cheers,
Bruce
-------------------------------------------------------------------
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom
they are addressed. If you have received this email in error please
notify the system manager.

    /\\\/\\\/\\\    /   /      Bruce Paterson          
   /  \\\ \\\ \\\  /   /    Senior Design Engineer
  /   /\\\/\\\/\\\/   /   87 Peters Ave, Mulgrave, Vic, 3170
 /   /  \\\ \\\ \\\  /  PO Box 4112, Mulgrave, Vic, 3170, Australia
/   /    \\\/\\\ \\\/   Ph: +61 3 8561 4232   Fax: +61 3 9560 9055
      Tele-IP Ltd.      Email: [EMAIL PROTECTED]    Icq: #32015991
                        WWW:   http://www.tele-ip.com       VK3TJN
-------------------------------------------------------------------


-------------------------------------------------------
This sf.net email is sponsored by: Influence the future 
of Java(TM) technology. Join the Java Community 
Process(SM) (JCP(SM)) program now. 
http://ads.sourceforge.net/cgi-bin/redirect.pl?sunm0004en
_______________________________________________
Alsa-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-devel

Reply via email to