[EMAIL PROTECTED] said:
> there are a number of ways of fixing this.
> my favorite method is to fill the buffer with silence, then start it
> via SND_PCM_START_GO and an explicit start call.

I understand perfectly what you mean. Thanks. I fixed ALSArtaudio-block.c 
according to your suggestion with the SND_PCM_START_GO and this. It works 
perfectly now (at least for me). I call snd_pcm_go() after writing the first 
fragment for playback, so I don't need the silence filled in the buffer, (and 
before getting the first fragment for capture). That way I get exactly what I 
wanted: transfer started immediately after writing the first fragment.

[EMAIL PROTECTED] said:
> Btw, it appears that we can have the ALSA driver or OSS-RTAUDIO but
> not both. I compiled using both options, and the test files defaulted
> to the OSS i/o even with incard/outcard (adc/dac).

you mean you did --with-OSS *and* --with-ALSA (or similar, you know what I 
mean:-)). Yes, you can't select both. I've attached the new working 
ALSArtaudio-block.c. Try it. It should consume less cpu time.

Markus
/* ALSArtaudio.c - hacked version of rtaudio.c to enable realtime full-duplex
 audio support for csound under Linux/ALSA.
This file incorporates the functions from LINUXaudio.c (with the exception of
sndsetvolume() which isn't used in this hacked version) so that file is no
longer needed  - fcf */
/*
 * $Id: ALSArtaudio.c,v 1.6 1999/06/23 18:23:57 nicb Exp $
 */

/*  This module is included when RTAUDIO is defined at compile time.
    It provides an interface between Csound realtime record/play calls
    and the device-driver code that controls the actual hardware.
*/

/* This is an updated version of the csound to ALSA interface,
   and works with latest ALSA 0.5.8.
   The code in this file (ALSArtaudio-block.c) uses the ALSA block transfer
   mode. You may want to use stream transfer mode (look at
   ALSArtaudio-stream.c), which is faster (much less latency = much more
   realtime than the block mode version used in this file).
   -
   Markus Gruber <[EMAIL PROTECTED]>
   */

#include <sys/asoundlib.h>
#include "cs.h"
#include "soundio.h"

static snd_pcm_t *capture_handle = NULL, *playback_handle = NULL;

extern  long    nrecs;
extern  OPARMS  O;

#ifdef PIPES
extern FILE* Linepipe;
#define _pclose pclose
#endif

char errorstring[1024];

int playback_go = 1;
int capture_go  = 1;

static int getformat()
{
        int p = 0;

        switch ( O.informat ) {
                case AE_UNCH:  /* unsigned char - standard Linux 8-bit format */
                        p = SND_PCM_SFMT_U8;
                        break;
                case AE_CHAR:  /* signed char. supported by ALSA */
                        p = SND_PCM_SFMT_S8;
                        break;
                case AE_ULAW:
                        p = SND_PCM_SFMT_MU_LAW; 
                        break;
                case AE_ALAW:
                        p = SND_PCM_SFMT_A_LAW;
                        break;
                case AE_SHORT:
                        p = SND_PCM_SFMT_S16_LE; /* Linux on Intel x86 is 
little-endian */
                        break;
                case AE_LONG:
                        die("ALSA sound driver does not (yet) support long integer 
samples");
                case AE_FLOAT:
                        die("ALSA sound driver does not (yet) support floating-point 
samples");
                default:
                        die("unknown sample format");
        }
        return (p);
}

void recopen(int nchnls, int dsize, FLOAT esr, int scale)
                                /* open for audio input */
{
        extern int incard;
        static snd_pcm_channel_params_t params;
        int err;
        char *cardname;

        if ((err = snd_card_get_longname(incard, &cardname))) {
                sprintf(errorstring, "%s\n", snd_strerror(err));
                die(errorstring);
        }
        fprintf(stderr, "ALSA incard: %s\n", cardname);

        /* Open ALSA audio driver, card #incard, device #0 in CAPTURE mode */
        if((err = snd_pcm_open(&capture_handle, incard, 0, SND_PCM_OPEN_CAPTURE))){
                sprintf(errorstring, "Opening CAPTURE channel: %s\n", 
snd_strerror(err));
                die(errorstring);
        }

        memset(&params, 0, sizeof(snd_pcm_channel_params_t));
        
        params.channel = SND_PCM_CHANNEL_CAPTURE;
        params.mode    = SND_PCM_MODE_BLOCK;
        
        params.format.interleave = 1;
        params.format.format     = getformat();
        params.format.rate       = (int)esr;
        params.format.voices     = nchnls;

        /* digital */
        params.start_mode = SND_PCM_START_GO;
        params.stop_mode  = SND_PCM_STOP_ROLLOVER;
        params.buf.block.frag_size = O.outbufsamps * O.outsampsiz;
        
        params.buf.block.frags_min = 1;
        params.buf.block.frags_max = -1;
        
        if ((err = snd_pcm_plugin_params(capture_handle, &params))) {
                sprintf(errorstring, "CAPTURE channel parameterizing error: %s\n", 
snd_strerror(err));
                die(errorstring);
        }
        if ((err = snd_pcm_plugin_prepare(capture_handle, SND_PCM_CHANNEL_CAPTURE))) {
                sprintf(errorstring, "CAPTURE channel prepare error: %s\n", 
snd_strerror(err));
                die(errorstring);
        }

        fprintf(stderr, "Running CAPTURE mode at %d hz on card #%d\n", 
params.format.rate, incard);
}

void playopen(int nchnls, int dsize, FLOAT esr, int scale)
                                /* open for audio output */
{
        extern int outcard;
        static snd_pcm_channel_params_t params;
        int err;
        char *cardname;

        if ((err = snd_card_get_longname(outcard, &cardname))) {
                sprintf(errorstring, "%s\n", snd_strerror(err));
                die(errorstring);
        }
        fprintf(stderr, "ALSA outcard: %s\n", cardname);

        /* Open ALSA audio driver, card # outcard, device #0 in PLAYBACK mode */
        if((err = snd_pcm_open(&playback_handle, outcard, 0, SND_PCM_OPEN_PLAYBACK))){
                sprintf(errorstring, "Opening PLAYBACK channel: %s\n", 
snd_strerror(err));
                die(errorstring);
        }

        memset(&params, 0, sizeof(snd_pcm_channel_params_t));
        
        params.channel = SND_PCM_CHANNEL_PLAYBACK;
        params.mode    = SND_PCM_MODE_BLOCK;
        
        params.format.interleave = 1;
        params.format.format     = getformat();
        params.format.rate       = (int)esr;
        params.format.voices     = nchnls;

        /* digital */
        params.start_mode = SND_PCM_START_GO;
        params.stop_mode  = SND_PCM_STOP_ROLLOVER;
        
        params.buf.block.frag_size = O.outbufsamps * O.outsampsiz;
        params.buf.block.frags_min = 1;
        params.buf.block.frags_max = -1;
        
        if ((err = snd_pcm_plugin_params(playback_handle, &params))) {
                sprintf(errorstring, "PLAYBACK channel parameterizing error: %s\n", 
snd_strerror(err));
                die(errorstring);
        }
        if ((err = snd_pcm_plugin_prepare(playback_handle, SND_PCM_CHANNEL_PLAYBACK))) 
{
                sprintf(errorstring, "PLAYBACK channel prepare error: %s\n", 
snd_strerror(err));
                die(errorstring);
        }
        
        fprintf(stderr, "Running PLAYBACK mode at %d hz on card #%d\n", 
params.format.rate, outcard);

#ifdef HIPRI
        setscheduler();
#endif
}

int rtrecord(char *inbuf, int nbytes) /* get samples from ADC */
{
        int fragsize, count, x=0, i, limit, err;
        char *buf;
        /* fprintf(stderr, "reading %d bytes from DAC\n", nbytes); */
        fragsize = O.outbufsamps * O.outsampsiz;
        if (fragsize > nbytes) {
                x = 1;
                buf = (char *)alloca(fragsize);
        } else {
                buf = inbuf;
        }
        if (capture_go) {
                if ((err = snd_pcm_channel_go(capture_handle, 
SND_PCM_CHANNEL_CAPTURE))) {
                        sprintf(errorstring, "CAPTURE channel go error: %s\n", 
snd_strerror(err));
                        die(errorstring);
                }
                capture_go = 0;
        }
        if((count = snd_pcm_plugin_read(capture_handle, (void *)buf, 
(size_t)fragsize)) < 0) {
                sprintf(errorstring, "Capture error: %s", snd_strerror(count));
                die(errorstring);
        }
        limit = (count > nbytes ? nbytes : count);
        if (x) {
                for (i=0; i<limit ; i++) {
                        inbuf[i] = buf[i];
                }
        }
        return(limit);
}

void rtplay(char *outbuf, int nbytes) /* put samples to DAC - see notes in rtaudio.c */
{
        int err, fragsize, i;
        char *buf;
        /* fprintf(stderr, "writing %d bytes to DAC\n", nbytes); */
        fragsize = O.outbufsamps * O.outsampsiz;
        if (fragsize > nbytes) {
                buf = (char *)alloca(fragsize);
                memset(buf, 0, fragsize);
                for (i=0; i<nbytes; i++) {
                    buf[i] = outbuf[i];
                }
        } else {
                buf = outbuf;
        }
        if ((err = snd_pcm_plugin_write(playback_handle, (void *)buf, 
(size_t)fragsize)) < fragsize) {
                sprintf(errorstring, "Playback error: %s\n", snd_strerror(err));
                die(errorstring);
        }
        if (playback_go) {
                if ((err = snd_pcm_channel_go(playback_handle, 
SND_PCM_CHANNEL_PLAYBACK))) {
                        sprintf(errorstring, "PLAYBACK channel go error: %s\n", 
snd_strerror(err));
                        die(errorstring);
                }
        }
        playback_go = 0;
        nrecs++;
}

void rtclose(void)              /* close the I/O device entirely  */
{                               /* called only when both complete */
        int err;
        if(capture_handle) {
                if ((err = snd_pcm_close(capture_handle))) {
                        sprintf(errorstring, "CAPTURE channel close error: %s\n", 
snd_strerror(err));
                        die(errorstring);
                }
        }
        if(playback_handle) {
                if ((err = snd_pcm_plugin_playback_drain(playback_handle))) {
                        sprintf(errorstring, "PLAYBACK channel drain error: %s\n", 
snd_strerror(err));
                        die(errorstring);
                }
                if ((err = snd_pcm_close(playback_handle))) {
                        sprintf(errorstring, "PLAYBACK channel close error: %s\n", 
snd_strerror(err));
                        die(errorstring);
                }
        }
        if (O.Linein) {
#ifdef PIPES
          if (O.Linename[0]=='|') _pclose(Linepipe);
#endif
        }
}

PGP signature

Reply via email to