From c1b10d55375dd8ecdf7b223d1f12541983422764 Mon Sep 17 00:00:00 2001 From: Miller Puckette Date: Sat, 18 Aug 2007 23:32:44 +0000 Subject: Download and adjust sources for new portaudio, portmidi. Add experimental callback scheduling. svn path=/trunk/; revision=8657 --- pd/src/s_audio_pa.c | 157 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 137 insertions(+), 20 deletions(-) (limited to 'pd/src/s_audio_pa.c') diff --git a/pd/src/s_audio_pa.c b/pd/src/s_audio_pa.c index 627b0015..f05c41d8 100644 --- a/pd/src/s_audio_pa.c +++ b/pd/src/s_audio_pa.c @@ -23,22 +23,138 @@ static PABLIO_Stream *pa_stream; static int pa_inchans, pa_outchans; static float *pa_soundin, *pa_soundout; +static t_audiocallback pa_callback; #define MAX_PA_CHANS 32 #define MAX_SAMPLES_PER_FRAME MAX_PA_CHANS * DEFDACBLKSIZE -#ifndef PA19 -#define Pa_GetDeviceCount Pa_CountDevices -#endif +static int pa_lowlevel_callback(const void *inputBuffer, + void *outputBuffer, unsigned long framesPerBuffer, + const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags, + void *userData) +{ + int i; + unsigned int j; + float *fbuf, *fp2, *fp3, *soundiop; + if (framesPerBuffer != DEFDACBLKSIZE) + { + fprintf(stderr, "ignoring buffer size %d\n", framesPerBuffer); + return; + } + if (inputBuffer != NULL) + { + fbuf = (float *)inputBuffer; + soundiop = pa_soundin; + for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++) + for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_inchans) + *soundiop++ = *fp3; + } + else memset((void *)pa_soundin, 0, + framesPerBuffer * pa_inchans * sizeof(float)); + (*pa_callback)(); + if (outputBuffer != NULL) + { + fbuf = (float *)outputBuffer; + soundiop = pa_soundout; + for (i = 0, fp2 = fbuf; i < pa_outchans; i++, fp2++) + for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_outchans) + *fp3 = *soundiop++; + } + + return 0; +} + +PaError pa_open_callback(double sampleRate, int inchannels, int outchannels, + int framesperbuf, int nbuffers, int indeviceno, int outdeviceno) +{ + long bytesPerSample; + PaError err; + PABLIO_Stream *pastream; + long numFrames; + PaStreamParameters instreamparams, outstreamparams; + + if (indeviceno < 0) + { + indeviceno = Pa_GetDefaultInputDevice(); + fprintf(stderr, "using default input device number: %d\n", indeviceno); + } + if (outdeviceno < 0) + { + outdeviceno = Pa_GetDefaultOutputDevice(); + fprintf(stderr, "using default output device number: %d\n", outdeviceno); + } + /* fprintf(stderr, "nchan %d, flags %d, bufs %d, framesperbuf %d\n", + nchannels, flags, nbuffers, framesperbuf); */ + + /* Allocate PABLIO_Stream structure for caller. */ + pastream = (PABLIO_Stream *)malloc( sizeof(PABLIO_Stream)); + if (pastream == NULL) + return (1); + memset(pastream, 0, sizeof(PABLIO_Stream)); + + /* Determine size of a sample. */ + bytesPerSample = Pa_GetSampleSize(paFloat32); + if (bytesPerSample < 0) + { + err = (PaError) bytesPerSample; + goto error; + } + pastream->insamplesPerFrame = inchannels; + pastream->inbytesPerFrame = bytesPerSample * pastream->insamplesPerFrame; + pastream->outsamplesPerFrame = outchannels; + pastream->outbytesPerFrame = bytesPerSample * pastream->outsamplesPerFrame; + + numFrames = nbuffers * framesperbuf; + + instreamparams.device = indeviceno; + instreamparams.channelCount = inchannels; + instreamparams.sampleFormat = paFloat32; + instreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate; + instreamparams.hostApiSpecificStreamInfo = 0; + + outstreamparams.device = outdeviceno; + outstreamparams.channelCount = outchannels; + outstreamparams.sampleFormat = paFloat32; + outstreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate; + outstreamparams.hostApiSpecificStreamInfo = 0; + + err = Pa_OpenStream( + &pastream->stream, + (inchannels ? &instreamparams : 0), + (outchannels ? &outstreamparams : 0), + sampleRate, + DEFDACBLKSIZE, + paNoFlag, /* portaudio will clip for us */ + pa_lowlevel_callback, + pastream); + if (err != paNoError) + goto error; + + err = Pa_StartStream(pastream->stream); + if (err != paNoError) + { + fprintf(stderr, "Pa_StartStream failed; closing audio stream...\n"); + CloseAudioStream( pastream ); + goto error; + } + pa_stream = pastream; + return paNoError; +error: + pa_stream = NULL; + return err; +} int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin, t_sample *soundout, int framesperbuf, int nbuffers, - int indeviceno, int outdeviceno) + int indeviceno, int outdeviceno, t_audiocallback callbackfn) { PaError err; static int initialized; int j, devno, pa_indev = 0, pa_outdev = 0; - + + pa_callback = callbackfn; + if (callbackfn) + fprintf(stderr, "callback enabled\n"); if (!initialized) { /* Initialize PortAudio */ @@ -105,26 +221,34 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin, post("output device %d, channels %d", pa_outdev, outchans); post("framesperbuf %d, nbufs %d", framesperbuf, nbuffers); } - if (inchans || outchans) + pa_inchans = inchans; + pa_outchans = outchans; + pa_soundin = soundin; + pa_soundout = soundout; + if (! inchans && !outchans) + return(0); + if (callbackfn) + { + pa_callback = callbackfn; + err = pa_open_callback(rate, inchans, outchans, + framesperbuf, nbuffers, pa_indev, pa_outdev); + } + else + { err = OpenAudioStream( &pa_stream, rate, paFloat32, inchans, outchans, framesperbuf, nbuffers, pa_indev, pa_outdev); - else err = 0; + } if ( err != paNoError ) { - fprintf( stderr, "Error number %d occured opening portaudio stream\n", + fprintf(stderr, "Error number %d opening portaudio stream\n", err); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); Pa_Terminate(); - sys_inchannels = sys_outchannels = 0; return (1); } else if (sys_verbose) post("... opened OK."); - pa_inchans = inchans; - pa_outchans = outchans; - pa_soundin = soundin; - pa_soundout = soundout; return (0); } @@ -235,17 +359,10 @@ void pa_listdevs(void) /* lifted from pa_devs.c in portaudio */ fprintf(stderr, " %s;", pdi->name ); fprintf(stderr, "%d inputs, ", pdi->maxInputChannels ); fprintf(stderr, "%d outputs", pdi->maxOutputChannels ); -#ifdef PA19 if ( i == Pa_GetDefaultInputDevice() ) fprintf(stderr, " (Default Input)"); if ( i == Pa_GetDefaultOutputDevice() ) fprintf(stderr, " (Default Output)"); -#else - if ( i == Pa_GetDefaultInputDeviceID() ) - fprintf(stderr, " (Default Input)"); - if ( i == Pa_GetDefaultOutputDeviceID() ) - fprintf(stderr, " (Default Output)"); -#endif fprintf(stderr, "\n"); } -- cgit v1.2.1