static int open_audio(){ /* this will open one circular audio stream */ /* build on top of portaudio routines */ /* implementation based on file pastreamio.c */ int numSamples; int numBytes; int minNumBuffers; int numFrames; minNumBuffers = 2 * Pa_GetMinNumBuffers( FRAMES_PER_BUFFER, vi.rate ); numFrames = minNumBuffers * FRAMES_PER_BUFFER; numFrames = RoundUpToNextPowerOf2( numFrames ); numSamples = numFrames * vi.channels; numBytes = numSamples * sizeof(SAMPLE); samples = (SAMPLE *) malloc( numBytes ); /* store our latency calculation here */ latency_sec = (double) numFrames / vi.rate / vi.channels; printf( "Latency: %.04f\n", latency_sec ); err = OpenAudioStream( &aOutStream, vi.rate, PA_SAMPLE_TYPE, (PASTREAMIO_WRITE | PASTREAMIO_STEREO) ); if( err != paNoError ) goto error; return err; error: CloseAudioStream( aOutStream ); printf( "An error occured while opening the portaudio stream\n" ); printf( "Error number: %d\n", err ); printf( "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
/************************************************************ * Opens a PortAudio stream with default characteristics. * Allocates PABLIO_Stream structure. * */ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr, const PaStreamParameters * inputParameters, const PaStreamParameters * outputParameters, double sampleRate, PaStreamFlags streamFlags, long samples_per_packet, int do_dual) { long bytesPerSample = 2; PaError err; PABLIO_Stream *aStream; long numFrames; //long numBytes; int c = 0; int channels = 1; if (!(inputParameters || outputParameters)) { return -1; } /* Allocate PABLIO_Stream structure for caller. */ aStream = (PABLIO_Stream *) malloc(sizeof(PABLIO_Stream)); switch_assert(aStream); memset(aStream, 0, sizeof(PABLIO_Stream)); if (inputParameters) { channels = inputParameters->channelCount; } else if (outputParameters) { channels = outputParameters->channelCount; } numFrames = RoundUpToNextPowerOf2(samples_per_packet * 5); aStream->bytesPerFrame = bytesPerSample; aStream->channelCount = channels; /* Initialize Ring Buffers */ if (inputParameters) { for (c = 0; c < channels; c++) { err = PABLIO_InitFIFO(&aStream->inFIFOs[c], numFrames, aStream->bytesPerFrame); if (err != paNoError) { goto error; } } aStream->has_in = 1; } if (outputParameters) { for (c = 0; c < channels; c++) { err = PABLIO_InitFIFO(&aStream->outFIFOs[c], numFrames, aStream->bytesPerFrame); if (err != paNoError) { goto error; } } aStream->has_out = 1; } /* Open a PortAudio stream that we will use to communicate with the underlying * audio drivers. */ aStream->do_dual = do_dual; if (aStream->do_dual) { err = Pa_OpenStream(&aStream->istream, inputParameters, NULL, sampleRate, samples_per_packet, streamFlags, iblockingIOCallback, aStream); if (err != paNoError) { goto error; } err = Pa_OpenStream(&aStream->ostream, NULL, outputParameters, sampleRate, samples_per_packet, streamFlags, oblockingIOCallback, aStream); if (err != paNoError) { goto error; } } else { err = Pa_OpenStream(&aStream->iostream, inputParameters, outputParameters, sampleRate, samples_per_packet, streamFlags, ioblockingIOCallback, aStream); } if (err != paNoError) { goto error; } if (aStream->do_dual) { err = Pa_StartStream(aStream->istream); if (err != paNoError) { goto error; } err = Pa_StartStream(aStream->ostream); if (err != paNoError) { goto error; } } else { err = Pa_StartStream(aStream->iostream); } if (err != paNoError) { goto error; } *rwblPtr = aStream; switch_yield(500000); return paNoError; error: CloseAudioStream(aStream); *rwblPtr = NULL; return err; }
/************************************************************ * Opens a PortAudio stream with default characteristics. * Allocates PASTREAMIO_Stream structure. * * flags parameter can be an ORed combination of: * PABLIO_WRITE, * and either PABLIO_MONO or PABLIO_STEREO */ PaError OpenAudioStream( PASTREAMIO_Stream **rwblPtr, double sampleRate, PaSampleFormat format, long flags ) { long bytesPerSample; long doWrite = 0; PaError err; PASTREAMIO_Stream *aStream; long minNumBuffers; long numFrames; /* Allocate PASTREAMIO_Stream structure for caller. */ aStream = (PASTREAMIO_Stream *) malloc( sizeof(PASTREAMIO_Stream) ); if( aStream == NULL ) return paInsufficientMemory; memset( aStream, 0, sizeof(PASTREAMIO_Stream) ); /* Determine size of a sample. */ bytesPerSample = Pa_GetSampleSize( format ); if( bytesPerSample < 0 ) { err = (PaError) bytesPerSample; goto error; } aStream->samplesPerFrame = ((flags&PASTREAMIO_MONO) != 0) ? 1 : 2; aStream->bytesPerFrame = bytesPerSample * aStream->samplesPerFrame; /* Initialize PortAudio */ err = Pa_Initialize(); if( err != paNoError ) goto error; /* Warning: numFrames must be larger than amount of data processed per interrupt * inside PA to prevent glitches. Just to be safe, adjust size upwards. */ minNumBuffers = 2 * Pa_GetMinNumBuffers( FRAMES_PER_BUFFER, sampleRate ); numFrames = minNumBuffers * FRAMES_PER_BUFFER; numFrames = RoundUpToNextPowerOf2( numFrames ); /* Initialize Ring Buffer */ doWrite = ((flags & PASTREAMIO_WRITE) != 0); if(doWrite) { err = PASTREAMIO_InitFIFO( &aStream->outFIFO, numFrames, aStream->bytesPerFrame ); if( err != paNoError ) 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. */ err = Pa_OpenStream( &aStream->stream, paNoDevice, 0 , format, NULL, Pa_GetDefaultOutputDeviceID() , aStream->samplesPerFrame , format, NULL, sampleRate, FRAMES_PER_BUFFER, minNumBuffers, paClipOff, /* we won't output out of range samples so don't bother clipping them */ audioIOCallback, aStream ); if( err != paNoError ) goto error; *rwblPtr = aStream; return paNoError; error: CloseAudioStream( aStream ); *rwblPtr = NULL; return err; }