-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Content-Type: multipart/mixed ; boundary="==_Exmh_-8349501610" This is a multipart MIME message. - --==_Exmh_-8349501610 Content-Type: text/plain; charset=iso-8859-1 Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable dlphilp_AT_bright.net said: > The unofficial Csound package includes Fred Floberg's code for > supporting the ALSA drivers. The code enabled two soundcards to be > used for separated i/o, but alas the code no longer works. = > The ALSA API has changed quite a bit since Fred's original work. > I've made some of the necessary updates, and I can get it to compile, > but Csound dies with the informative message "Input/output error" when > I try to run it. ALSA OSS emulation works perfectly (i.e., if you > don't select --with-ALSA as a configuration option). I've hacked Fred Flobergs code to work with my ALSA installation, which i= s = 0.5.8. I've tested both ALSA interfaces, the "block mode" = (ALSArtaudio-block.c) and "stream mode" (ALSArtaudio-stream.c), both with= the = mode to start transfer, when data is written to the buffer. I use "stream mode" ALSArtaudio-stream.c, because transfer starts immedia= tely = without hearable latency, when data is written to the buffer, whereas wit= h = "block mode" ALSArtaudio-block.c, sound comes from the speaker with a del= ay = approximately around half a second. Is this the right behaviour of block = mode = with start_mode=3DSND_PCM_START_DATA ? Shouldn't transfer start after wri= ting = the first fragment to the buffer. It seems that transfer starts, when the= = whole buffer is filled, thus causing the latency. With ALSArtaudio-stream.c I'm able to record sound, do some reverbs or = something like that on it and immediately play it back with very low late= ncy = (I don't hear it). This "stream mode" works well with my trident-4dwave-nx card. Using "stre= am = mode" with my ess solo1 card hangs up my machine, but block mode works wi= th = rather low latency, because the transfer buffer is small :-) Markus - --==_Exmh_-8349501610 Content-Type: text/plain ; name="ALSArtaudio-block.c"; charset=iso-8859-1 Content-Description: ALSArtaudio-block.c Content-Disposition: attachment; filename="ALSArtaudio-block.c" Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable /* ALSArtaudio.c - hacked version of rtaudio.c to enable realtime full-du= plex audio support for csound under Linux/ALSA. This file incorporates the functions from LINUXaudio.c (with the exceptio= n of sndsetvolume() which isn't used in this hacked version) so that file is n= o 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 transf= er mode. You may want to use stream transfer mode (look at ALSArtaudio-stream.c), which is faster (much less latency =3D much mor= e realtime than the block mode version used in this file). - Markus Gruber */ #include #include "cs.h" #include "soundio.h" static snd_pcm_t *capture_handle =3D NULL, *playback_handle =3D NULL; extern long nrecs; extern OPARMS O; #ifdef PIPES extern FILE* Linepipe; #define _pclose pclose #endif char errorstring[1024]; static int getformat() { int p =3D 0; switch ( O.informat ) { case AE_UNCH: /* unsigned char - standard Linux 8-bit format */ p =3D SND_PCM_SFMT_U8; break; case AE_CHAR: /* signed char. supported by ALSA */ p =3D SND_PCM_SFMT_S8; break; case AE_ULAW: p =3D SND_PCM_SFMT_MU_LAW; = break; case AE_ALAW: p =3D SND_PCM_SFMT_A_LAW; break; case AE_SHORT: p =3D 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 =3D 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 =3D snd_pcm_open(&capture_handle, incard, 0, SND_PCM_OPEN_CAPTUR= E))){ sprintf(errorstring, "Opening CAPTURE channel: %s\n", snd_strerror(err)= ); die(errorstring); } memset(¶ms, 0, sizeof(snd_pcm_channel_params_t)); = params.channel =3D SND_PCM_CHANNEL_CAPTURE; params.mode =3D SND_PCM_MODE_BLOCK; = params.format.interleave =3D 1; params.format.format =3D getformat(); params.format.rate =3D (int)esr; params.format.voices =3D nchnls; /* digital */ params.start_mode =3D SND_PCM_START_DATA; params.stop_mode =3D SND_PCM_STOP_ROLLOVER; params.buf.block.frag_size =3D O.outbufsamps * O.outsampsiz; = params.buf.block.frags_min =3D 1; params.buf.block.frags_max =3D -1; = if ((err =3D snd_pcm_plugin_params(capture_handle, ¶ms))) { sprintf(errorstring, "CAPTURE channel parameterizing error: %s\n", snd_= strerror(err)); die(errorstring); } if ((err =3D snd_pcm_plugin_prepare(capture_handle, SND_PCM_CHANNEL_CAPT= URE))) { sprintf(errorstring, "CAPTURE channel prepare error: %s\n", snd_strerro= r(err)); die(errorstring); } fprintf(stderr, "Running CAPTURE mode at %d hz on card #%d\n", params.fo= rmat.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 =3D 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 =3D snd_pcm_open(&playback_handle, outcard, 0, SND_PCM_OP= EN_PLAYBACK))){ sprintf(errorstring, "Opening PLAYBACK channel: %s\n", sn= d_strerror(err)); die(errorstring); } memset(¶ms, 0, sizeof(snd_pcm_channel_params_t)); = params.channel =3D SND_PCM_CHANNEL_PLAYBACK; params.mode =3D SND_PCM_MODE_BLOCK; = params.format.interleave =3D 1; params.format.format =3D getformat(); params.format.rate =3D (int)esr; params.format.voices =3D nchnls; /* digital */ params.start_mode =3D SND_PCM_START_DATA; params.stop_mode =3D SND_PCM_STOP_ROLLOVER; = params.buf.block.frag_size =3D O.outbufsamps * O.outsampsiz; params.buf.block.frags_min =3D 1; params.buf.block.frags_max =3D -1; = if ((err =3D snd_pcm_plugin_params(playback_handle, ¶ms))) { sprintf(errorstring, "PLAYBACK channel parameterizing error: %s\n", snd= _strerror(err)); die(errorstring); } if ((err =3D snd_pcm_plugin_prepare(playback_handle, SND_PCM_CHANNEL_PLA= YBACK))) { sprintf(errorstring, "PLAYBACK channel prepare error: %s\n", snd_strerr= or(err)); die(errorstring); } = fprintf(stderr, "Running PLAYBACK mode at %d hz on card #%d\n", params.f= ormat.rate, outcard); #ifdef HIPRI setscheduler(); #endif } int rtrecord(char *inbuf, int nbytes) /* get samples from ADC */ { int fragsize, count, x=3D0, i, limit; char *buf; /* fprintf(stderr, "reading %d bytes from DAC\n", nbytes); */ fragsize =3D O.outbufsamps * O.outsampsiz; if (fragsize > nbytes) { x =3D 1; buf =3D (char *)alloca(fragsize); } else { buf =3D inbuf; } if((count =3D snd_pcm_plugin_read(capture_handle, (void *)buf, (size_t)f= ragsize)) < 0) { sprintf(errorstring, "Capture error: %s", snd_strerror(count)); die(errorstring); } limit =3D (count > nbytes ? nbytes : count); if (x) { for (i=3D0; i nbytes) { buf =3D (char *)alloca(fragsize); memset(buf, 0, fragsize); for (i=3D0; i */ #include #include "cs.h" #include "soundio.h" #include static snd_pcm_t *capture_handle =3D NULL, *playback_handle =3D NULL; extern long nrecs; static int processed =3D 0; extern OPARMS O; #ifdef PIPES extern FILE* Linepipe; #define _pclose pclose #endif char errorstring[1024]; static int getformat() { int p =3D 0; switch ( O.informat ) { case AE_UNCH: /* unsigned char - standard Linux 8-bit format */ p =3D SND_PCM_SFMT_U8; break; case AE_CHAR: /* signed char. supported by ALSA */ p =3D SND_PCM_SFMT_S8; break; case AE_ULAW: p =3D SND_PCM_SFMT_MU_LAW; = break; case AE_ALAW: p =3D SND_PCM_SFMT_A_LAW; break; case AE_SHORT: p =3D 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 =3D 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 =3D snd_pcm_open(&capture_handle, incard, 0, SND_PCM_OPEN_CAPTUR= E))){ sprintf(errorstring, "Opening CAPTURE channel: %s\n", snd_strerror(err)= ); die(errorstring); } //snd_pcm_channel_flush(capture_handle, SND_PCM_CHANNEL_CAPTURE); /* be = in right state */ = memset(¶ms, 0, sizeof(snd_pcm_channel_params_t)); = params.channel =3D SND_PCM_CHANNEL_CAPTURE; params.mode =3D SND_PCM_MODE_STREAM; = params.format.interleave =3D 1; params.format.format =3D getformat(); params.format.rate =3D (int)esr; params.format.voices =3D nchnls; /* digital */ params.start_mode =3D SND_PCM_START_GO; params.stop_mode =3D SND_PCM_STOP_ROLLOVER; = params.buf.stream.queue_size =3D 1024*1024;/* maximum for smooth action shorter queue would cause less latency, but is more choppy */ params.buf.stream.fill =3D SND_PCM_FILL_SILENCE_WHOLE; params.buf.stream.max_fill =3D 1024; = if ((err =3D snd_pcm_plugin_params(capture_handle, ¶ms))) { sprintf(errorstring, "CAPTURE channel parameterizing error: %s\n", snd_= strerror(err)); die(errorstring); } if ((err =3D snd_pcm_plugin_prepare(capture_handle, SND_PCM_CHANNEL_CAPT= URE))) { sprintf(errorstring, "CAPTURE channel prepare error: %s\n", snd_strerro= r(err)); die(errorstring); } if ((err =3D snd_pcm_channel_go(capture_handle, SND_PCM_CHANNEL_CAPTURE)= )) { sprintf(errorstring, "CAPTURE channel go error: %s\n", snd_strerror(err= )); die(errorstring); } = fprintf(stderr, "Running CAPTURE mode at %d hz on card #%d\n", params.fo= rmat.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 =3D 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 =3D snd_pcm_open(&playback_handle, outcard, 0, SND_PCM_OP= EN_PLAYBACK))){ sprintf(errorstring, "Opening PLAYBACK channel: %s\n", sn= d_strerror(err)); die(errorstring); } //snd_pcm_channel_flush(playback_handle, SND_PCM_CHANNEL_PLAYBACK); /* b= e in right state */ memset(¶ms, 0, sizeof(snd_pcm_channel_params_t)); = params.channel =3D SND_PCM_CHANNEL_PLAYBACK; params.mode =3D SND_PCM_MODE_STREAM; = params.format.interleave =3D 1; params.format.format =3D getformat(); params.format.rate =3D (int)esr; params.format.voices =3D nchnls; /* digital */ params.start_mode =3D SND_PCM_START_GO; params.stop_mode =3D SND_PCM_STOP_ROLLOVER; = params.buf.stream.queue_size =3D 1024*1024; /* see recopen */ = params.buf.stream.fill =3D SND_PCM_FILL_SILENCE_WHOLE; params.buf.stream.max_fill =3D 1024; = if ((err =3D snd_pcm_plugin_params(playback_handle, ¶ms))) { sprintf(errorstring, "PLAYBACK channel parameterizing error: %s\n", snd= _strerror(err)); die(errorstring); } if ((err =3D snd_pcm_plugin_prepare(playback_handle, SND_PCM_CHANNEL_PLA= YBACK))) { sprintf(errorstring, "PLAYBACK channel prepare error: %s\n", snd_strerr= or(err)); die(errorstring); } if ((err =3D snd_pcm_channel_go(playback_handle, SND_PCM_CHANNEL_PLAYBAC= K))) { sprintf(errorstring, "PLAYBACK channel go error: %s\n", snd_strerror(er= r)); die(errorstring); } = fprintf(stderr, "Running PLAYBACK mode at %d hz on card #%d\n", params.f= ormat.rate, outcard); #ifdef HIPRI setscheduler(); #endif } int rtrecord(char *inbuf, int nbytes) { int count; while (1) { if ((count =3D snd_pcm_plugin_read(capture_handle, (void *)inbuf, (size= _t)nbytes)) < 0) { if (count =3D=3D -EAGAIN) { usleep(10000); continue; } sprintf(errorstring, "Capture error: %s", snd_strerror(count)); die(errorstring); } break; } return(count); } void rtplay(char *outbuf, int nbytes) { int count, pos =3D 0; do { if ((count =3D snd_pcm_plugin_write(playback_handle, (void *)(&outbuf[p= os]), (size_t)nbytes)) < 0) { if (count =3D=3D -EAGAIN) { usleep(10000); continue; } sprintf(errorstring, "Playback error: %s\n", snd_strerror(count)); die(errorstring); } nbytes -=3D count; pos +=3D count; //fprintf(stderr, "bytes =3D %d, count written =3D %d\n", nbytes, count= ); } while (nbytes); nrecs++; } void rtclose(void) /* close the I/O device entirely */ { /* called only when both complete */ int err; if(capture_handle) { snd_pcm_channel_flush(capture_handle, SND_PCM_CHANNEL_CAPTURE); if ((err =3D snd_pcm_close(capture_handle))) { sprintf(errorstring, "CAPTURE channel close error: %s\n", snd_strerror= (err)); die(errorstring); } } if(playback_handle) { if ((err =3D snd_pcm_plugin_playback_drain(playback_handle))) { sprintf(errorstring, "PLAYBACK channel drain error: %s\n", snd_strerro= r(err)); die(errorstring); } snd_pcm_channel_flush(capture_handle, SND_PCM_CHANNEL_CAPTURE); if ((err =3D snd_pcm_close(playback_handle))) { sprintf(errorstring, "PLAYBACK channel close error: %s\n", snd_strerro= r(err)); die(errorstring); } } if (O.Linein) { #ifdef PIPES if (O.Linename[0]=3D=3D'|') _pclose(Linepipe); #endif } } - --==_Exmh_-8349501610-- -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.0 (GNU/Linux) Comment: Exmh version 2.1.1 10/15/1999 iD8DBQE5vhwp9ysZ6vgtOOARAkl4AKDvn2eWMwNqTMPWyc70V5cKdPPgFACg3y6b To6WLgtVm5rl9GGQVtZSRjM= =zBLD -----END PGP SIGNATURE-----