[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(¶ms, 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, ¶ms))) {
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(¶ms, 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, ¶ms))) {
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