/* This should be called after stopping or aborting the stream, so that on next start, the buffers will be ready. */ PaError resetBlioRingBuffers( PaMacBlio *blio ) { #ifdef PA_MAC__BLIO_MUTEX int result; #endif blio->statusFlags = 0; if( blio->outputRingBuffer.buffer ) { RingBuffer_Flush( &blio->outputRingBuffer ); bzero( blio->outputRingBuffer.buffer, blio->outputRingBuffer.bufferSize ); /* Advance buffer */ RingBuffer_AdvanceWriteIndex( &blio->outputRingBuffer, blio->outputRingBuffer.bufferSize ); /* Update isOutputFull. */ #ifdef PA_MAC__BLIO_MUTEX result = blioSetIsOutputFull( blio, toAdvance == blio->outputRingBuffer.bufferSize ); if( result ) goto error; #endif /* printf( "------%d\n" , blio->framesPerBuffer ); printf( "------%d\n" , blio->outChan ); printf( "------%d\n" , blio->outputSampleSize ); printf( "------%d\n" , blio->framesPerBuffer*blio->outChan*blio->outputSampleSize ); */ } if( blio->inputRingBuffer.buffer ) { RingBuffer_Flush( &blio->inputRingBuffer ); bzero( blio->inputRingBuffer.buffer, blio->inputRingBuffer.bufferSize ); /* Update isInputEmpty. */ #ifdef PA_MAC__BLIO_MUTEX result = blioSetIsInputEmpty( blio, true ); if( result ) goto error; #endif } return paNoError; #ifdef PA_MAC__BLIO_MUTEX error: return result; #endif }
/*************************************************************************** ** Return bytes written. */ long RingBuffer_Write( RingBuffer *rbuf, void *data, long numBytes ) { long size1, size2, numWritten; void *data1, *data2; numWritten = RingBuffer_GetWriteRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 ); if( size2 > 0 ) { memcpy( data1, data, size1 ); data = ((char *)data) + size1; memcpy( data2, data, size2 ); } else { memcpy( data1, data, size1 ); } RingBuffer_AdvanceWriteIndex( rbuf, numWritten ); return numWritten; }
/************************************************************ * Opens a PortAudio stream with default characteristics. * Allocates PABLIO_Stream structure. * * flags parameter can be an ORed combination of: * PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE */ PaError OpenAudioStream( PABLIO_Stream **rwblPtr, double sampleRate, PaSampleFormat format, int inchannels, int outchannels, int framesperbuf, int nbuffers, int indeviceno, int outdeviceno) /* MSP */ { long bytesPerSample; long doRead = 0; long doWrite = 0; PaError err; PABLIO_Stream *aStream; long minNumBuffers; long numFrames; //#ifdef PA19 // PaStreamParameters instreamparams, outstreamparams; /* MSP */ //#endif /* fprintf(stderr, "open %lf fmt %d flags %d ch: %d fperbuf: %d nbuf: %d devs: %d %d\n", sampleRate, format, flags, nchannels, framesperbuf, nbuffers, indeviceno, outdeviceno); */ if (indeviceno < 0) /* MSP... */ { //#ifdef PA19 // indeviceno = Pa_GetDefaultInputDevice(); //#else indeviceno = Pa_GetDefaultInputDeviceID(); //#endif fprintf(stderr, "using default input device number: %d\n", indeviceno); } if (outdeviceno < 0) { //#ifdef PA19 // outdeviceno = Pa_GetDefaultOutputDevice(); //#else outdeviceno = Pa_GetDefaultOutputDeviceID(); //#endif 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); */ /* ...MSP */ /* Allocate PABLIO_Stream structure for caller. */ aStream = (PABLIO_Stream *) malloc( sizeof(PABLIO_Stream) ); if( aStream == NULL ) return paInsufficientMemory; memset( aStream, 0, sizeof(PABLIO_Stream) ); /* Determine size of a sample. */ bytesPerSample = Pa_GetSampleSize( format ); if( bytesPerSample < 0 ) { fprintf(stderr, "error bytes per sample: %i\n", bytesPerSample); err = (PaError) bytesPerSample; goto error; } aStream->insamplesPerFrame = inchannels; /* MSP */ aStream->inbytesPerFrame = bytesPerSample * aStream->insamplesPerFrame; aStream->outsamplesPerFrame = outchannels; aStream->outbytesPerFrame = bytesPerSample * aStream->outsamplesPerFrame; /* Initialize PortAudio */ err = Pa_Initialize(); if( err != paNoError ) goto error; //#ifdef PA19 // numFrames = nbuffers * framesperbuf; /* ...MSP */ // instreamparams.device = indeviceno; /* MSP... */ // instreamparams.channelCount = inchannels; // instreamparams.sampleFormat = format; // instreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate; // instreamparams.hostApiSpecificStreamInfo = 0; // outstreamparams.device = outdeviceno; // outstreamparams.channelCount = outchannels; // outstreamparams.sampleFormat = format; // outstreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate; // outstreamparams.hostApiSpecificStreamInfo = 0; /* ... MSP */ //#else /* Warning: numFrames must be larger than amount of data processed per interrupt inside PA to prevent glitches. */ /* MSP */ minNumBuffers = Pa_GetMinNumBuffers(framesperbuf, sampleRate); if (minNumBuffers > nbuffers) fprintf(stderr, "warning: number of buffers %d less than recommended minimum %d\n", (int)nbuffers, (int)minNumBuffers); //#endif numFrames = nbuffers * framesperbuf; /* fprintf(stderr, "numFrames %d\n", numFrames); */ /* Initialize Ring Buffers */ doRead = (inchannels != 0); doWrite = (outchannels != 0); if(doRead) { err = PABLIO_InitFIFO( &aStream->inFIFO, numFrames, aStream->inbytesPerFrame ); if( err != paNoError ) { fprintf(stderr, "error doRead PABLIO_InitFIFO \n"); goto error; } } if(doWrite) { long numBytes; err = PABLIO_InitFIFO( &aStream->outFIFO, numFrames, aStream->outbytesPerFrame ); if( err != paNoError ) { fprintf(stderr, "error doWrite PABLIO_InitFIFO \n"); goto error; } /* Make Write FIFO appear full initially. */ numBytes = RingBuffer_GetWriteAvailable( &aStream->outFIFO ); RingBuffer_AdvanceWriteIndex( &aStream->outFIFO, numBytes ); } /* Open a PortAudio stream that we will use to communicate with the underlying * audio drivers. */ //#ifdef PA19 // err = Pa_OpenStream( // &aStream->stream, // (doRead ? &instreamparams : 0), /* MSP */ // (doWrite ? &outstreamparams : 0), /* MSP */ // sampleRate, // framesperbuf, /* MSP */ // paNoFlag, /* MSP -- portaudio will clip for us */ // blockingIOCallback, // aStream ); //#else // err = Pa_OpenStream( // &aStream->stream, // (doRead ? indeviceno : paNoDevice), /* MSP */ // (doRead ? aStream->insamplesPerFrame : 0 ), // format, // NULL, // (doWrite ? outdeviceno : paNoDevice), /* MSP */ // (doWrite ? aStream->outsamplesPerFrame : 0 ), // format, // NULL, // sampleRate, // framesperbuf, /* MSP */ // nbuffers, /* MSP */ // paNoFlag, /* MSP -- portaudio will clip for us */ // blockingIOCallback, // aStream ); // #endif PortAudioStream *stream; err = Pa_OpenDefaultStream( stream, 0, 2, paFloat32, 44100, 256, 0, blockingIOCallback, stream ); if( err != paNoError ){ fprintf(stderr, "error Pa_OpenStream \n"); goto error; } err = Pa_StartStream( aStream->stream ); if( err != paNoError ) /* MSP */ { fprintf(stderr, "Pa_StartStream failed; closing audio stream...\n"); CloseAudioStream( aStream ); goto error; } *rwblPtr = aStream; return paNoError; error: *rwblPtr = NULL; return err; }