int main(void) { PaStreamParameters outputParameters; PaStream *stream; PaError err; TestData data; float writeBuffer[ FRAMES_PER_BUFFER * 2 ]; printf("PortAudio Test: check that stopping stream plays out all queued samples. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER); InitTestSignalGenerator( &data ); err = Pa_Initialize(); if( err != paNoError ) goto error; outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; /* test paComplete ---------------------------------------------------------- */ ResetTestSignalGenerator( &data ); err = Pa_OpenStream( &stream, NULL, /* no input */ &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ TestCallback1, &data ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("\nPlaying 'tone-blip' %d times using callback, stops by returning paComplete from callback.\n", NUM_REPEATS ); printf("If final blip is not intact, callback+paComplete implementation may be faulty.\n\n" ); while( (err = Pa_IsStreamActive( stream )) == 1 ) Pa_Sleep( 5 ); if( err != 0 ) goto error; err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Sleep( 500 ); /* test Pa_StopStream() with callback --------------------------------------- */ ResetTestSignalGenerator( &data ); testCallback2Finished = 0; err = Pa_OpenStream( &stream, NULL, /* no input */ &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ TestCallback2, &data ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("\nPlaying 'tone-blip' %d times using callback, stops by calling Pa_StopStream.\n", NUM_REPEATS ); printf("If final blip is not intact, callback+Pa_StopStream implementation may be faulty.\n\n" ); /* note that polling a volatile flag is not a good way to synchronise with the callback, but it's the best we can do portably. */ while( !testCallback2Finished ) Pa_Sleep( 2 ); err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Sleep( 500 ); /* test Pa_StopStream() with Pa_WriteStream --------------------------------- */ ResetTestSignalGenerator( &data ); err = Pa_OpenStream( &stream, NULL, /* no input */ &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ NULL, /* no callback, use blocking API */ NULL ); /* no callback, so no callback userData */ if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("\nPlaying 'tone-blip' %d times using Pa_WriteStream, stops by calling Pa_StopStream.\n", NUM_REPEATS ); printf("If final blip is not intact, Pa_WriteStream+Pa_StopStream implementation may be faulty.\n\n" ); do{ GenerateTestSignal( &data, writeBuffer, FRAMES_PER_BUFFER ); err = Pa_WriteStream( stream, writeBuffer, FRAMES_PER_BUFFER ); if( err != paNoError ) goto error; }while( !IsTestSignalFinished( &data ) ); err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; /* -------------------------------------------------------------------------- */ Pa_Terminate(); printf("Test finished.\n"); return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
PaStream *pa_dev_open(phastream_t *as, int output, char *name, int rate, int framesize, int latencymsecs) { PaStreamParameters inputParameters, outputParameters; PaStream *stream; PaError err; char *in, *out; static double standardSampleRates[] = { 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */ }; int i; int rateIndex; double drate = (double) rate; DBG_DYNA_AUDIO_DRV("phad_pa - pa_dev_open: asking for (name: \"%s\", rate: %d, framesize: %d)\n", name, rate, framesize); if (!strncasecmp(name, "pa:", 3)) { name += 3; } if ((in = strstr(name,"IN=")) != NULL) { inputParameters.device = atoi(in + 3); } else { inputParameters.device = Pa_GetDefaultInputDevice(); if (inputParameters.device == paNoDevice) { return 0; } } if ((out = strstr(name,"OUT="))) { outputParameters.device = atoi(out + 4); } else { outputParameters.device = Pa_GetDefaultOutputDevice(); if (outputParameters.device == paNoDevice) { return 0; } } DBG_DYNA_AUDIO_DRV("pa_dev_open: PA Input %d, PA Output %d\n", inputParameters.device, outputParameters.device); inputParameters.channelCount = 1; inputParameters.sampleFormat = paInt16; inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency; // latencymsecs / 1000.0; // if (inputParameters.suggestedLatency == 0.0) inputParameters.suggestedLatency = latencymsecs / 1000.0; inputParameters.hostApiSpecificStreamInfo = 0; outputParameters.channelCount = 1; outputParameters.sampleFormat = paInt16; outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; // if (outputParameters.suggestedLatency == 0.0) outputParameters.suggestedLatency = latencymsecs / 1000.0; outputParameters.hostApiSpecificStreamInfo = 0; DBG_DYNA_AUDIO_DRV("pa_dev_open: using latencies in = %d ms, out = %d ms\n", (int) (inputParameters.suggestedLatency * 1000.0), (int) (outputParameters.suggestedLatency * 1000.0)); /* find the nearest matching entry in the table */ rateIndex = -1; for (i = 0; standardSampleRates[i] > 0; i++ ) { if (drate <= standardSampleRates[i]) { rateIndex = i; break; } } if (rateIndex == -1) { return 0; } /* check if the initial match is accepted */ err = Pa_IsFormatSupported( &inputParameters, &outputParameters, standardSampleRates[rateIndex] ); if ( err == paFormatIsSupported ) { as->actual_rate = (int) standardSampleRates[rateIndex]; } else { /* find a sampling rate that IS accepted */ i = rateIndex + 1; rateIndex = -1; for (i = 0; standardSampleRates[i] > 0; i++ ) { err = Pa_IsFormatSupported( &inputParameters, &outputParameters, standardSampleRates[i] ); if ( err == paFormatIsSupported ) { rateIndex = i; break; } } if (rateIndex == -1) { return 0; } } as->actual_rate = (int) standardSampleRates[rateIndex]; /* we need to recalculate the frame size? */ if (rate != as->actual_rate) { int frameDuration = 1000 * (framesize / 2) / rate; framesize = frameDuration * as->actual_rate / 1000 * 2; } DBG_DYNA_AUDIO_DRV("pa_dev_open: chosen rate (freq, framesize)=(%d,%d)\n", as->actual_rate, framesize); if (output) { err = Pa_OpenStream( &stream, (output == PH_PA_INOUT) ? &inputParameters : 0, &outputParameters, standardSampleRates[rateIndex], framesize / 2, 0, /* paClipOff, */ /* we won't output out of range samples so don't bother clipping them */ (output == PH_PA_INOUT) ? ph_pa_callback : ph_pa_ocallback, as ); } else { err = Pa_OpenStream( &stream, &inputParameters, 0, standardSampleRates[rateIndex], framesize / 2, 0, /* paClipOff, */ /* we won't output out of range samples so don't bother clipping them */ ph_pa_icallback, as ); } if( err != paNoError ) { return 0; } return stream; }
int main(void) { char pad[256]; PortAudioStream *stream; PaError err; const PaDeviceInfo *pdi; paTestData data = {0}; printf("PortAudio Test: output sine wave on each channel.\n" ); err = Pa_Initialize(); if( err != paNoError ) goto error; pdi = Pa_GetDeviceInfo( OUTPUT_DEVICE ); data.numChannels = pdi->maxOutputChannels; if( data.numChannels > MAX_CHANNELS ) data.numChannels = MAX_CHANNELS; printf("Number of Channels = %d\n", data.numChannels ); data.amplitude = 1.0; err = Pa_OpenStream( &stream, paNoDevice, /* default input device */ 0, /* no input */ paFloat32, /* 32 bit floating point input */ NULL, OUTPUT_DEVICE, data.numChannels, paFloat32, /* 32 bit floating point output */ NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, /* frames per buffer */ 0, /* number of buffers, if zero then use default minimum */ paClipOff, /* we won't output out of range samples so don't bother clipping them */ patestCallback, &data ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; do { printf("Current amplitude = %f\n", data.amplitude ); printf("Enter new amplitude or 'q' to quit.\n"); fflush(stdout); gets( pad ); if( pad[0] != 'q' ) { // I tried to use atof but it seems to be broken on Mac OS X 10.1 float amp; sscanf( pad, "%f", & ); data.amplitude = amp; } } while( pad[0] != 'q' ); err = Pa_StopStream( stream ); if( err != paNoError ) goto error; Pa_CloseStream( stream ); Pa_Terminate(); printf("Test finished.\n"); return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
bool audio_init(audio_t *a, size_t sample_rate, size_t n_channels, size_t samples_per_chunk) { //***Initialize PA internal data structures****** if(Pa_Initialize() != paNoError) return false; size_t frames_per_buffer = samples_per_chunk / n_channels; //******Initialize input device******* PaStreamParameters inparams; PaDeviceIndex dev; PaTime lat; dev = Pa_GetDefaultInputDevice(); if(dev == paNoDevice) return false; lat = Pa_GetDeviceInfo(dev)->defaultLowInputLatency; inparams = (PaStreamParameters) { .device = dev, .channelCount = n_channels, .sampleFormat = paInt16, .suggestedLatency = lat, .hostApiSpecificStreamInfo = NULL }; //******Initialize output device******* PaStreamParameters outparams; //************** dev = Pa_GetDefaultOutputDevice(); if(dev == paNoDevice) return false; lat = Pa_GetDeviceInfo(dev)->defaultLowInputLatency; outparams = (PaStreamParameters) { .device = dev, .channelCount = n_channels, .sampleFormat = paInt16, .suggestedLatency = lat, .hostApiSpecificStreamInfo = NULL }; //********Open play stream******* PaStream *pstream=NULL; if(Pa_OpenStream( &pstream, NULL, &outparams, sample_rate, frames_per_buffer, paClipOff, playCallback, a) != paNoError) return false; //************** //********Open record and listen stream******* PaStream *rstream=NULL; if(Pa_OpenStream( &rstream, &inparams, NULL, sample_rate, frames_per_buffer, paClipOff, recordCallback, a) != paNoError) return false; //*****Initialize communication ring buffers******************** PaUtilRingBuffer rb; void *rb_data; size_t rb_size; rb_size = 1 << (sizeof(samples_per_chunk) * CHAR_BIT - __builtin_clz(samples_per_chunk * RB_MULTIPLIER)); rb_data = malloc(sizeof(audio_sample_t) * rb_size); PaUtil_InitializeRingBuffer(&rb, sizeof(audio_sample_t), rb_size, rb_data); *a = (audio_t) { .sample_rate = sample_rate, .n_channels = n_channels, .samples_per_chunk = samples_per_chunk, .pstream = pstream, .rstream = rstream, .wakeup = false, .wakeup_sig = PTHREAD_COND_INITIALIZER, .wakeup_mutex = PTHREAD_MUTEX_INITIALIZER, .flags = DEFAULT, .prbuf = NULL, .prbuf_size = 0, .prbuf_offset = 0, .rb = rb, .rb_data = rb_data }; return true; } void audio_destroy(audio_t *a) { Pa_CloseStream(a->pstream); Pa_CloseStream(a->rstream); Pa_Terminate(); pthread_cond_destroy(&a->wakeup_sig); pthread_mutex_destroy(&a->wakeup_mutex); audio_clear(a); free(a->rb_data); }
/* -- main function -- */ int main( int argc, char **argv ) { PaStreamParameters inputParameters; float a[2], b[3], mem1[4], mem2[4]; float data[FFT_SIZE]; float datai[FFT_SIZE]; float window[FFT_SIZE]; float freqTable[FFT_SIZE]; char * noteNameTable[FFT_SIZE]; float notePitchTable[FFT_SIZE]; void * fft = NULL; PaStream *stream = NULL; PaError err = 0; struct sigaction action; // add signal listen so we know when to exit: action.sa_handler = signalHandler; sigemptyset (&action.sa_mask); action.sa_flags = 0; sigaction (SIGINT, &action, NULL); sigaction (SIGHUP, &action, NULL); sigaction (SIGTERM, &action, NULL); // build the window, fft, etc /* buildHanWindow( window, 30 ); for( int i=0; i<30; ++i ) { for( int j=0; j<window[i]*50; ++j ) printf( "*" ); printf("\n"); } exit(0); */ buildHanWindow( window, FFT_SIZE ); fft = initfft( FFT_EXP_SIZE ); computeSecondOrderLowPassParameters( SAMPLE_RATE, 330, a, b ); mem1[0] = 0; mem1[1] = 0; mem1[2] = 0; mem1[3] = 0; mem2[0] = 0; mem2[1] = 0; mem2[2] = 0; mem2[3] = 0; //freq/note tables for( int i=0; i<FFT_SIZE; ++i ) { freqTable[i] = ( SAMPLE_RATE * i ) / (float) ( FFT_SIZE ); } for( int i=0; i<FFT_SIZE; ++i ) { noteNameTable[i] = NULL; notePitchTable[i] = -1; } for( int i=0; i<127; ++i ) { float pitch = ( 440.0 / 32.0 ) * pow( 2, (i-9.0)/12.0 ) ; if( pitch > SAMPLE_RATE / 2.0 ) break; //find the closest frequency using brute force. float min = 1000000000.0; int index = -1; for( int j=0; j<FFT_SIZE; ++j ) { if( fabsf( freqTable[j]-pitch ) < min ) { min = fabsf( freqTable[j]-pitch ); index = j; } } noteNameTable[index] = NOTES[i%12]; notePitchTable[index] = pitch; //printf( "%f %d %s\n", pitch, index, noteNameTable[index] ); } // initialize portaudio err = Pa_Initialize(); if( err != paNoError ) goto error; inputParameters.device = Pa_GetDefaultInputDevice(); inputParameters.channelCount = 1; inputParameters.sampleFormat = paFloat32; inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ; inputParameters.hostApiSpecificStreamInfo = NULL; printf( "Opening %s\n", Pa_GetDeviceInfo( inputParameters.device )->name ); err = Pa_OpenStream( &stream, &inputParameters, NULL, //no output SAMPLE_RATE, FFT_SIZE, paClipOff, NULL, NULL ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; // this is the main loop where we listen to and // process audio. while( running ) { // read some data err = Pa_ReadStream( stream, data, FFT_SIZE ); if( err ) goto error; //FIXME: we don't want to err on xrun // low-pass //for( int i=0; i<FFT_SIZE; ++i ) // printf( "in %f\n", data[i] ); for( int j=0; j<FFT_SIZE; ++j ) { data[j] = processSecondOrderFilter( data[j], mem1, a, b ); data[j] = processSecondOrderFilter( data[j], mem2, a, b ); } // window applyWindow( window, data, FFT_SIZE ); // do the fft for( int j=0; j<FFT_SIZE; ++j ) datai[j] = 0; applyfft( fft, data, datai, false ); //find the peak float maxVal = -1; int maxIndex = -1; for( int j=0; j<FFT_SIZE/2; ++j ) { float v = data[j] * data[j] + datai[j] * datai[j] ; /* printf( "%d: ", j*SAMPLE_RATE/(2*FFT_SIZE) ); for( int i=0; i<sqrt(v)*100000000; ++i ) printf( "*" ); printf( "\n" ); */ if( v > maxVal ) { maxVal = v; maxIndex = j; } } float freq = freqTable[maxIndex]; //find the nearest note: int nearestNoteDelta=0; while( true ) { if( nearestNoteDelta < maxIndex && noteNameTable[maxIndex-nearestNoteDelta] != NULL ) { nearestNoteDelta = -nearestNoteDelta; break; } else if( nearestNoteDelta + maxIndex < FFT_SIZE && noteNameTable[maxIndex+nearestNoteDelta] != NULL ) { break; } ++nearestNoteDelta; } char * nearestNoteName = noteNameTable[maxIndex+nearestNoteDelta]; float nearestNotePitch = notePitchTable[maxIndex+nearestNoteDelta]; float centsSharp = 1200 * log( freq / nearestNotePitch ) / log( 2.0 ); // now output the results: printf("\033[2J\033[1;1H"); //clear screen, go to top left fflush(stdout); printf( "Tuner listening. Control-C to exit.\n" ); printf( "%f Hz, %d : %f\n", freq, maxIndex, maxVal*1000 ); printf( "Nearest Note: %s\n", nearestNoteName ); if( nearestNoteDelta != 0 ) { if( centsSharp > 0 ) printf( "%f cents sharp.\n", centsSharp ); if( centsSharp < 0 ) printf( "%f cents flat.\n", -centsSharp ); } else { printf( "in tune!\n" ); } printf( "\n" ); int chars = 30; if( nearestNoteDelta == 0 || centsSharp >= 0 ) { for( int i=0; i<chars; ++i ) printf( " " ); } else { for( int i=0; i<chars+centsSharp; ++i ) printf( " " ); for( int i=chars+centsSharp<0?0:chars+centsSharp; i<chars; ++i ) printf( "=" ); } printf( " %2s ", nearestNoteName ); if( nearestNoteDelta != 0 ) for( int i=0; i<chars && i<centsSharp; ++i ) printf( "=" ); printf("\n"); } err = Pa_StopStream( stream ); if( err != paNoError ) goto error; // cleanup destroyfft( fft ); Pa_Terminate(); return 0; error: if( stream ) { Pa_AbortStream( stream ); Pa_CloseStream( stream ); } destroyfft( fft ); Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return 1; }
int main(void) { PaStream *stream; PaStreamParameters outputParameters; PaError err; paTestData data; int i; printf("Play different tone sine waves that alternate between left and right channel.\n"); printf("The low tone should be on the left channel.\n"); /* initialise sinusoidal wavetable */ for( i=0; i<TABLE_SIZE; i++ ) { data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ); } data.left_phase = data.right_phase = 0; data.currentBalance = 0.0; data.targetBalance = 0.0; err = Pa_Initialize(); if( err != paNoError ) goto error; outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ if (outputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default output device.\n"); goto error; } outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; err = Pa_OpenStream( &stream, NULL, /* No input. */ &outputParameters, /* As above. */ SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ patestCallback, &data ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Play for several seconds.\n"); for( i=0; i<4; i++ ) { printf("Hear low sound on left side.\n"); data.targetBalance = 0.01; Pa_Sleep( 1000 ); printf("Hear high sound on right side.\n"); data.targetBalance = 0.99; Pa_Sleep( 1000 ); } err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); printf("Test finished.\n"); return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
int main(void) { PaStreamParameters inputParameters, outputParameters; PaStream* stream; PaError err = paNoError; paTestData data; int i; int totalFrames; int numSamples; int numBytes; SAMPLE max, val; double average; printf("patest_record.c\n"); fflush(stdout); data.maxFrameIndex = totalFrames = NUM_SECONDS * SAMPLE_RATE; /* Record for a few seconds. */ data.frameIndex = 0; numSamples = totalFrames * NUM_CHANNELS; numBytes = numSamples * sizeof(SAMPLE); data.recordedSamples = (SAMPLE *) malloc( numBytes ); /* From now on, recordedSamples is initialised. */ if( data.recordedSamples == NULL ) { printf("Could not allocate record array.\n"); goto done; } for( i=0; i<numSamples; i++ ) data.recordedSamples[i] = 0; err = Pa_Initialize(); if( err != paNoError ) goto done; inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */ if (inputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default input device.\n"); goto done; } inputParameters.channelCount = 2; /* stereo input */ inputParameters.sampleFormat = PA_SAMPLE_TYPE; inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; /* Record some audio. -------------------------------------------- */ err = Pa_OpenStream( &stream, &inputParameters, NULL, /* &outputParameters, */ SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ recordCallback, &data ); if( err != paNoError ) goto done; err = Pa_StartStream( stream ); if( err != paNoError ) goto done; printf("\n=== Now recording!! Please speak into the microphone. ===\n"); fflush(stdout); while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) { Pa_Sleep(1000); printf("index = %d\n", data.frameIndex ); fflush(stdout); } if( err < 0 ) goto done; err = Pa_CloseStream( stream ); if( err != paNoError ) goto done; /* Measure maximum peak amplitude. */ max = 0; average = 0.0; for( i=0; i<numSamples; i++ ) { val = data.recordedSamples[i]; if( val < 0 ) val = -val; /* ABS */ if( val > max ) { max = val; } average += val; } average = average / (double)numSamples; printf("sample max amplitude = "PRINTF_S_FORMAT"\n", max ); printf("sample average = %lf\n", average ); /* Write recorded data to a file. */ #if WRITE_TO_FILE { FILE *fid; fid = fopen("recorded.raw", "wb"); if( fid == NULL ) { printf("Could not open file."); } else { fwrite( data.recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid ); fclose( fid ); printf("Wrote data to 'recorded.raw'\n"); } } #endif /* Playback recorded data. -------------------------------------------- */ data.frameIndex = 0; outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ if (outputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default output device.\n"); goto done; } outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = PA_SAMPLE_TYPE; outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; printf("\n=== Now playing back. ===\n"); fflush(stdout); err = Pa_OpenStream( &stream, NULL, /* no input */ &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ playCallback, &data ); if( err != paNoError ) goto done; if( stream ) { err = Pa_StartStream( stream ); if( err != paNoError ) goto done; printf("Waiting for playback to finish.\n"); fflush(stdout); while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100); if( err < 0 ) goto done; err = Pa_CloseStream( stream ); if( err != paNoError ) goto done; printf("Done.\n"); fflush(stdout); } done: Pa_Terminate(); if( data.recordedSamples ) /* Sure it is NULL or valid. */ free( data.recordedSamples ); if( err != paNoError ) { fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); err = 1; /* Always return 0 or 1, but no other return codes. */ } return err; }
// print the audio device to stdout. static void printDeviceInfo( int device ) { const PaDeviceInfo *pdi; bool defaultDisplayed = false; pdi = Pa_GetDeviceInfo( device ); if( pdi != NULL ) { messagePrintf( ( "\n" ) ); if( device == Pa_GetDefaultInputDevice() ) { messagePrintf( ( "[ Default Input" ) ); defaultDisplayed = true; } else if( device == Pa_GetHostApiInfo( pdi->hostApi )->defaultInputDevice ) { const PaHostApiInfo *phai = Pa_GetHostApiInfo( pdi->hostApi ); messagePrintf( ( "[ Default %s Input", phai->name ) ); defaultDisplayed = true; } if( device == Pa_GetDefaultOutputDevice() ) { messagePrintf( ( ( defaultDisplayed ? "," : "[") ) ); messagePrintf( ( " Default Output" ) ); defaultDisplayed = true; } else if( device == Pa_GetHostApiInfo( pdi->hostApi )->defaultOutputDevice ) { const PaHostApiInfo *phai = Pa_GetHostApiInfo( pdi->hostApi ); messagePrintf( ( ( defaultDisplayed ? "," : "[") ) ); messagePrintf( ( " Default %s Output", phai->name ) ); defaultDisplayed = true; } if( defaultDisplayed ) messagePrintf( ( " ]\n" ) ); messagePrintf( ( "" "Device %d name: %s\n" "Host API name: %s\n" "Max input channels: %d, Max output channels: %d\n" "Default input latency: %8.4f(low) - %8.4f(high)\n" "Default output latency: %8.4f(low) - %8.4f(high)\n" "Default sample rate: %8.2f\n", device, pdi->name, Pa_GetHostApiInfo( pdi->hostApi )->name, pdi->maxInputChannels, pdi->maxOutputChannels, pdi->defaultLowInputLatency, pdi->defaultHighInputLatency, pdi->defaultLowOutputLatency, pdi->defaultHighOutputLatency, pdi->defaultSampleRate ) ); if( true ) // Print supported standard sample rates { PaStreamParameters inputParameters, outputParameters; inputParameters.device = device; inputParameters.channelCount = pdi->maxInputChannels; inputParameters.sampleFormat = paInt16; // default only inputParameters.suggestedLatency = 0; inputParameters.hostApiSpecificStreamInfo = NULL; outputParameters.device = device; outputParameters.channelCount = pdi->maxOutputChannels; outputParameters.sampleFormat = paInt16; // default only outputParameters.suggestedLatency = 0; outputParameters.hostApiSpecificStreamInfo = NULL; if( inputParameters.channelCount > 0 ) { messagePrintf( ( "Supported standard sample rates input.\n" ) ); printSupportedStandardSampleRates( &inputParameters, NULL ); } if( outputParameters.channelCount > 0 ) { messagePrintf( ( "Supported standard sample rates output.\n" ) ); printSupportedStandardSampleRates( NULL, &outputParameters ); } if( inputParameters.channelCount > 0 && outputParameters.channelCount > 0 ) { messagePrintf( ( "Supported standard sample rates input/output.\n" ) ); printSupportedStandardSampleRates( &inputParameters, &outputParameters ); } } } }
Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) : _stream(NULL), _ringBuffer(true), _scope(scope), _averagedLatency(0.0), _measuredJitter(0), _jitterBufferSamples(initialJitterBufferSamples), _wasStarved(0), _numStarves(0), _lastInputLoudness(0), _lastVelocity(0), _lastAcceleration(0), _totalPacketsReceived(0), _firstPacketReceivedTime(), _packetsReceivedThisPlayback(0), _echoSamplesLeft(NULL), _isSendingEchoPing(false), _pingAnalysisPending(false), _pingFramesToRecord(0), _samplesLeftForFlange(0), _lastYawMeasuredMaximum(0), _flangeIntensity(0.0f), _flangeRate(0.0f), _flangeWeight(0.0f), _collisionSoundMagnitude(0.0f), _collisionSoundFrequency(0.0f), _collisionSoundNoise(0.0f), _collisionSoundDuration(0.0f), _proceduralEffectSample(0), _heartbeatMagnitude(0.0f), _listenMode(AudioRingBuffer::NORMAL), _listenRadius(0.0f) { outputPortAudioError(Pa_Initialize()); // NOTE: Portaudio documentation is unclear as to whether it is safe to specify the // number of frames per buffer explicitly versus setting this value to zero. // Possible source of latency that we need to investigate further. // unsigned long FRAMES_PER_BUFFER = BUFFER_LENGTH_SAMPLES_PER_CHANNEL; // Manually initialize the portaudio stream to ask for minimum latency PaStreamParameters inputParameters, outputParameters; inputParameters.device = Pa_GetDefaultInputDevice(); outputParameters.device = Pa_GetDefaultOutputDevice(); if (inputParameters.device == -1 || outputParameters.device == -1) { qDebug("Audio: Missing device.\n"); outputPortAudioError(Pa_Terminate()); return; } inputParameters.channelCount = 2; // Stereo input inputParameters.sampleFormat = (paInt16 | paNonInterleaved); inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; outputParameters.channelCount = 2; // Stereo output outputParameters.sampleFormat = (paInt16 | paNonInterleaved); outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; outputPortAudioError(Pa_OpenStream(&_stream, &inputParameters, &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paNoFlag, audioCallback, (void*) this)); if (! _stream) { return; } _echoSamplesLeft = new int16_t[AEC_BUFFERED_SAMPLES + AEC_TMP_BUFFER_SIZE]; memset(_echoSamplesLeft, 0, AEC_BUFFERED_SAMPLES * sizeof(int16_t)); // start the stream now that sources are good to go outputPortAudioError(Pa_StartStream(_stream)); // Uncomment these lines to see the system-reported latency //qDebug("Default low input, output latency (secs): %0.4f, %0.4f\n", // Pa_GetDeviceInfo(Pa_GetDefaultInputDevice())->defaultLowInputLatency, // Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice())->defaultLowOutputLatency); const PaStreamInfo* streamInfo = Pa_GetStreamInfo(_stream); qDebug("Started audio with reported latency msecs In/Out: %.0f, %.0f\n", streamInfo->inputLatency * 1000.f, streamInfo->outputLatency * 1000.f); gettimeofday(&_lastReceiveTime, NULL); }
bool Portaudio::init() { PaError err = Pa_Initialize(); if (err != paNoError) { qDebug("Portaudio initialize failed: %s", Pa_GetErrorText(err)); return false; } initialized = true; if (MScore::debugMode) qDebug("using PortAudio Version: %s", Pa_GetVersionText()); PaDeviceIndex idx = preferences.portaudioDevice; if (idx < 0) idx = Pa_GetDefaultOutputDevice(); const PaDeviceInfo* di = Pa_GetDeviceInfo(idx); if (di == nullptr) di = Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice()); _sampleRate = int(di->defaultSampleRate); /* Open an audio I/O stream. */ struct PaStreamParameters out; memset(&out, 0, sizeof(out)); out.device = idx; out.channelCount = 2; out.sampleFormat = paFloat32; #ifdef Q_OS_MAC out.suggestedLatency = 0.020; #else // on windows, this small latency causes some problem out.suggestedLatency = 0.100; #endif out.hostApiSpecificStreamInfo = 0; err = Pa_OpenStream(&stream, 0, &out, double(_sampleRate), 0, 0, paCallback, (void*)this); if (err != paNoError) { // fall back to default device: out.device = Pa_GetDefaultOutputDevice(); err = Pa_OpenStream(&stream, 0, &out, double(_sampleRate), 0, 0, paCallback, (void*)this); if (err != paNoError) { qDebug("Portaudio open stream %d failed: %s", idx, Pa_GetErrorText(err)); return false; } } const PaStreamInfo* si = Pa_GetStreamInfo(stream); if (si) _sampleRate = int(si->sampleRate); #ifdef USE_ALSA midiDriver = new AlsaMidiDriver(seq); #endif #ifdef USE_PORTMIDI midiDriver = new PortMidiDriver(seq); #endif if (midiDriver && !midiDriver->init()) { qDebug("Init midi driver failed"); delete midiDriver; midiDriver = 0; #ifdef USE_PORTMIDI return true; // return OK for audio driver; midi is only input #else return false; #endif } return true; }
int audioPlayRec( int playdevID, SAMPLE * playbuffer, int playbuflen, int playbuffirstchannel, int playbuflastchannel, int recdevID, SAMPLE * recbuffer, int recbuflen, int recbuffirstchannel, int recbuflastchannel, char * recCallbackName, int samplerate ) { paAudioData audio; mxArray * precRingArray = NULL; audio.recMode = PLAYREC_NONE; audio.playBuffer = NULL; audio.playBufLen = 0; audio.playBufPos = 0; audio.playFirstChannel = 0; audio.playChannels = 0; audio.playDevChannels = 0; audio.recBuffer = NULL; audio.recBufLen = 0; audio.recBufWritePos = 0; audio.recBufReadPos = 0; audio.recFirstChannel = 0; audio.recChannels = 0; audio.recDevChannels = 0; if( playdevID != paNoDevice && playbuffer != NULL && playbuflen > 0 && playbuffirstchannel >= 0 && playbuflastchannel >= playbuffirstchannel ) { int playChannels = playbuflastchannel - playbuffirstchannel + 1; audio.recMode |= PLAYREC_PLAY; audio.playBuffer = playbuffer; audio.playBufLen = playbuflen / playChannels; // just only one channel samples audio.playFirstChannel = playbuffirstchannel; audio.playChannels = playChannels; } if( recdevID != paNoDevice && playbuffirstchannel >= 0 && recbuflastchannel >= recbuffirstchannel ) { int recChannels = recbuflastchannel - recbuffirstchannel + 1; if( recbuffer != NULL && recbuflen > 0 ) { audio.recMode |= PLAYREC_REC; audio.recBuffer = recbuffer; audio.recBufLen = recbuflen / recChannels; // just only one channel samples audio.recFirstChannel = recbuffirstchannel; audio.recChannels = recChannels; } else if( recCallbackName != NULL ) { int recBufferLength = samplerate * 2; // 2 seconds ring buffer precRingArray = mxCreateNumericMatrix( recBufferLength, recChannels, SAMPLE_CLASSID, mxREAL ); SAMPLE * recBuf = (SAMPLE *)mxGetData( precRingArray ); if( recBuf != NULL ) { audio.recMode |= PLAYREC_REC; audio.recBuffer = recBuf; audio.recBufLen = recBufferLength; // just only one channel samples audio.recFirstChannel = recbuffirstchannel; audio.recChannels = recChannels; } } } if( audio.recMode == PLAYREC_NONE ) { errorPrintf( ( "Playback and Recording parameters is wrong!\n" ) ); return paNoError; } PaStreamParameters inputParameters, outputParameters; PaStreamParameters *pinputParameters, *poutputParameters; PaStream *stream; PaError err; err = Pa_Initialize(); if( err != paNoError ) goto error; if( audio.recMode & PLAYREC_PLAY ) { poutputParameters = &outputParameters; outputParameters.device = playdevID; outputParameters.channelCount = Pa_GetDeviceInfo( outputParameters.device )->maxOutputChannels; outputParameters.sampleFormat = SAMPLE_FORMAT; outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; audio.playDevChannels = outputParameters.channelCount; } else poutputParameters = NULL; if( audio.recMode & PLAYREC_REC ) { pinputParameters = &inputParameters; inputParameters.device = recdevID; inputParameters.channelCount = Pa_GetDeviceInfo( inputParameters.device )->maxInputChannels; inputParameters.sampleFormat = SAMPLE_FORMAT; inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; audio.recDevChannels = inputParameters.channelCount; } else pinputParameters = NULL; err = Pa_OpenStream( &stream, pinputParameters, poutputParameters, samplerate, FRAMES_PER_BUFFER, paNoFlag, paCallback, &audio ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) { if( recCallbackName != NULL ) { bool stop = false; while( getRecDataLen( &audio ) >= FRAMES_PER_BUFFER ) // recording data is more than FRAMES_PER_BUFFER { mxArray * pdataArray = mxCreateNumericMatrix( FRAMES_PER_BUFFER, audio.recChannels, SAMPLE_CLASSID, mxREAL ); mxArray * presultArray = NULL; SAMPLE * dataBuf = (SAMPLE *)mxGetData( pdataArray ); if( dataBuf != NULL ) { for( int index = 0; index < FRAMES_PER_BUFFER; index++ ) // frame { for( int channel = 0; channel < audio.recChannels; channel++ ) // channel { *(dataBuf + FRAMES_PER_BUFFER * channel + index) = *(audio.recBuffer + audio.recBufLen * channel + audio.recBufReadPos); } if( nextReadPos( &audio ) == -1 ) break; } mexCallMATLAB( 1, &presultArray, 1, &pdataArray, recCallbackName ); if( !mxIsDouble( presultArray ) || mxGetPr( presultArray ) == NULL || ((int)*mxGetPr( presultArray )) != 0 ) // return 0 should be continue, others should be stop stop = true; } if( presultArray != NULL ) mxDestroyArray( presultArray ); if( pdataArray != NULL ) mxDestroyArray( pdataArray ); if( stop ) break; // recording stop } if( stop ) break; // recording stop Pa_Sleep( (FRAMES_PER_BUFFER * 1000) / samplerate ); } else Pa_Sleep( 50 ); } if( err < 0 ) goto error; err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); if( precRingArray != NULL ) mxDestroyArray( precRingArray ); return err; error: Pa_Terminate(); errorPrintf( ( "Error number: %d\n", err ) ); errorPrintf( ( "Error message: %s\n", Pa_GetErrorText(err) ) ); if( precRingArray != NULL ) mxDestroyArray( precRingArray ); return err; }
int main(void) { PortAudioStream *stream; PaError err; paTestData data; int i; PaDeviceID inputDevice; const PaDeviceInfo *pdi; printf("PortAudio Test: input signal from each channel. %d buffers\n", NUM_BUFFERS ); data.liveChannel = 0; err = Pa_Initialize(); if( err != paNoError ) goto error; #ifdef INPUT_DEVICE_NAME printf("Try to use device: %s\n", INPUT_DEVICE_NAME ); inputDevice = PaFindDeviceByName(INPUT_DEVICE_NAME); if( inputDevice == paNoDevice ) { printf("Could not find %s. Using default instead.\n", INPUT_DEVICE_NAME ); inputDevice = Pa_GetDefaultInputDeviceID(); } #else printf("Using default input device.\n"); inputDevice = Pa_GetDefaultInputDeviceID(); #endif pdi = Pa_GetDeviceInfo( inputDevice ); if( pdi == NULL ) { printf("Could not get device info!\n"); goto error; } data.numChannels = pdi->maxInputChannels; printf("Input Device name is %s\n", pdi->name ); printf("Input Device has %d channels.\n", pdi->maxInputChannels); err = Pa_OpenStream( &stream, inputDevice, pdi->maxInputChannels, paFloat32, /* 32 bit floating point input */ NULL, OUTPUT_DEVICE, 2, paFloat32, /* 32 bit floating point output */ NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, /* frames per buffer */ NUM_BUFFERS, /* number of buffers, if zero then use default minimum */ paClipOff, /* we won't output out of range samples so don't bother clipping them */ patestCallback, &data ); if( err != paNoError ) goto error; data.liveChannel = 0; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; for( i=0; i<data.numChannels; i++ ) { data.liveChannel = i; printf("Channel %d being sent to output. Hit ENTER for next channel.", i ); fflush(stdout); getchar(); } err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); Pa_Terminate(); printf("Test finished.\n"); return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
int openPA(Synth* synth, Vocoder* vc) { printf("PortAudio Test: output sawtooth wave.\n"); fflush(stdout); PaStreamParameters inputParameters, outputParameters; paData* data = (paData*) malloc(sizeof(paData)); data->synth = synth; data->vc = vc; /* Initialize library before making any other calls. */ err = Pa_Initialize(); if( err != paNoError ) goto error; /* Set up input parameters */ inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */ if (inputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default input device.\n"); goto error; } printf( "Input device # %d.\n", inputParameters.device ); printf( "Input LL: %g s\n", Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency ); printf( "Input HL: %g s\n", Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ); inputParameters.channelCount = NUM_CHANNELS; inputParameters.sampleFormat = FORMAT; inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; /* Set up output parameters */ outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ if (outputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default output device.\n"); goto error; } printf( "Output device # %d.\n", outputParameters.device ); printf( "Output LL: %g s\n", Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency ); printf( "Output HL: %g s\n", Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency ); outputParameters.channelCount = NUM_CHANNELS; outputParameters.sampleFormat = FORMAT; outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; /* Open an audio I/O stream. */ err = Pa_OpenStream( &stream, &inputParameters, &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, paCallback, data ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); synth_free(data->synth); vc_free(data->vc); free(data); return err; }
SoundDriver_PortAudio::SoundDriver_PortAudio() { mixing_frequency=1; driver_name="PortAudio v19"; active=false; int devices=Pa_GetDeviceCount(); int current_input=0; int current_output=0; std::vector<String> output_names; std::vector<String> input_names; for (int i=0;i<devices;i++) { const PaDeviceInfo * dinfo=Pa_GetDeviceInfo (i); if (dinfo->maxOutputChannels) { if (i==Pa_GetDefaultOutputDevice()) current_output=output_device_index.size(); output_device_index.push_back(i); output_names.push_back(dinfo->name); } if (dinfo->maxInputChannels) { if (i==Pa_GetDefaultInputDevice()) current_input=input_device_index.size(); input_device_index.push_back(i); input_names.push_back(dinfo->name); } } input_devices.set_all("input_devices","Input Devices",input_names,current_input); output_devices.set_all("output_devices","Output Devices",output_names,current_output); std::vector<String> buffer_sizes_text; for (int i=0;i<MAX_BUFFER_SIZES;i++) { buffer_sizes_text.push_back( String::num(buffer_sizes[i]) ); } buffer_size.set_all("buffer_size","Buffer Size",buffer_sizes_text,6,"frames"); sampling_rate_values.push_back(4000); sampling_rate_values.push_back(5512); sampling_rate_values.push_back(8000); sampling_rate_values.push_back(9600); sampling_rate_values.push_back(11025); sampling_rate_values.push_back(16000); sampling_rate_values.push_back(22050); sampling_rate_values.push_back(22050); sampling_rate_values.push_back(32000); sampling_rate_values.push_back(44100); sampling_rate_values.push_back(48000); sampling_rate_values.push_back(88200); sampling_rate_values.push_back(96000); sampling_rate_values.push_back(192000); std::vector<String> sampling_rates_text; for (int i=0;i<sampling_rate_values.size();i++) { sampling_rates_text.push_back( String::num(sampling_rate_values[i]) ); } int default_sampling_rate=0; for (int i=0;i<sampling_rate_values.size();i++) { default_sampling_rate=i; if (sampling_rate_values[i]>=48000) break; } mix_rate.set_all("sampling_rate","Sampling Rate",sampling_rates_text,default_sampling_rate,"hz"); settings.push_back(&input_devices); settings.push_back(&output_devices); settings.push_back(&buffer_size); settings.push_back(&mix_rate); stream=NULL; }
/* Internal: create playback stream */ static pj_status_t create_play_stream(struct pa_aud_factory *pa, const pjmedia_aud_param *param, pjmedia_aud_play_cb play_cb, void *user_data, pjmedia_aud_stream **p_snd_strm) { pj_pool_t *pool; pjmedia_aud_dev_index play_id; struct pa_aud_stream *stream; PaStreamParameters outputParam; int sampleFormat; const PaDeviceInfo *paDevInfo = NULL; const PaHostApiInfo *paHostApiInfo = NULL; const PaStreamInfo *paSI; unsigned paFrames, paRate, paLatency; PaError err; PJ_ASSERT_RETURN(play_cb && p_snd_strm, PJ_EINVAL); play_id = param->play_id; if (play_id < 0) { play_id = pa_get_default_output_dev(param->channel_count); if (play_id < 0) { /* No such device. */ return PJMEDIA_EAUD_NODEFDEV; } } paDevInfo = Pa_GetDeviceInfo(play_id); if (!paDevInfo) { /* Assumed it is "No such device" error. */ return PJMEDIA_EAUD_INVDEV; } if (param->bits_per_sample == 8) sampleFormat = paUInt8; else if (param->bits_per_sample == 16) sampleFormat = paInt16; else if (param->bits_per_sample == 32) sampleFormat = paInt32; else return PJMEDIA_EAUD_SAMPFORMAT; pool = pj_pool_create(pa->pf, "playstrm", 1024, 1024, NULL); if (!pool) return PJ_ENOMEM; stream = PJ_POOL_ZALLOC_T(pool, struct pa_aud_stream); stream->pool = pool; pj_strdup2_with_null(pool, &stream->name, paDevInfo->name); stream->dir = PJMEDIA_DIR_PLAYBACK; stream->play_id = play_id; stream->rec_id = -1; stream->user_data = user_data; stream->samples_per_sec = param->clock_rate; stream->samples_per_frame = param->samples_per_frame; stream->bytes_per_sample = param->bits_per_sample / 8; stream->channel_count = param->channel_count; stream->play_cb = play_cb; stream->play_buf = (pj_int16_t*)pj_pool_alloc(pool, stream->samples_per_frame * stream->bytes_per_sample); stream->play_buf_count = 0; pj_bzero(&outputParam, sizeof(outputParam)); outputParam.device = play_id; outputParam.channelCount = param->channel_count; outputParam.hostApiSpecificStreamInfo = NULL; outputParam.sampleFormat = sampleFormat; if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY) outputParam.suggestedLatency=param->output_latency_ms / 1000.0; else outputParam.suggestedLatency=PJMEDIA_SND_DEFAULT_PLAY_LATENCY/1000.0; paHostApiInfo = Pa_GetHostApiInfo(paDevInfo->hostApi); /* Frames in PortAudio is number of samples in a single channel */ paFrames = param->samples_per_frame / param->channel_count; err = Pa_OpenStream( &stream->play_strm, NULL, &outputParam, param->clock_rate, paFrames, paClipOff, &PaPlayerCallback, stream ); if (err != paNoError) { pj_pool_release(pool); return PJMEDIA_AUDIODEV_ERRNO_FROM_PORTAUDIO(err); } paSI = Pa_GetStreamInfo(stream->play_strm); paRate = (unsigned)(paSI->sampleRate); paLatency = (unsigned)(paSI->outputLatency * 1000); PJ_LOG(5,(THIS_FILE, "Opened device %d: %s(%s) for playing, sample rate=%d" ", ch=%d, " "bits=%d, %d samples per frame, latency=%d ms", play_id, paDevInfo->name, paHostApiInfo->name, paRate, param->channel_count, param->bits_per_sample, param->samples_per_frame, paLatency)); *p_snd_strm = &stream->base; return PJ_SUCCESS; }
int softrock_open(void) { #ifdef DIRECTAUDIO int arg; int status; #endif #ifdef PORTAUDIO int rc; int status; #endif #ifdef PULSEAUDIO int error; pa_sample_spec params; pa_buffer_attr attrs; #endif #ifdef PORTAUDIO PaStreamParameters inputParameters; PaStreamParameters outputParameters; PaStreamInfo *info; int devices; int i; PaDeviceInfo* deviceInfo; if (softrock_get_verbose()) fprintf(stderr,"softrock_open: portaudio\n"); #endif #ifdef DIRECTAUDIO if (softrock_get_verbose()) fprintf(stderr,"softrock_open: %s\n",softrock_get_device()); #endif if(softrock_get_playback()) { return 0; } #ifdef PULSEAUDIO if (softrock_get_verbose()) fprintf(stderr,"Using PulseAudio\n"); params.format=PA_SAMPLE_FLOAT32LE; params.rate=softrock_get_sample_rate(); params.channels=2; attrs.maxlength=attrs.minreq=attrs.prebuf=attrs.tlength=(uint32_t)-1; attrs.fragsize=attrs.maxlength=attrs.minreq=attrs.prebuf=(uint32_t)-1; attrs.fragsize=SAMPLES_PER_BUFFER*2 * sizeof(float); attrs.tlength=SAMPLES_PER_BUFFER*2 * sizeof(float); if (softrock_get_verbose()) fprintf(stderr,"params.rate=%d\n",params.rate); stream=pa_simple_new("localhost","Softrock", PA_STREAM_RECORD, NULL, "IQ", ¶ms, NULL, &attrs, &error); if(stream==NULL) { if (softrock_get_verbose()) fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); exit(0); } playback_stream=pa_simple_new("localhost","Softrock", PA_STREAM_PLAYBACK, NULL, "IQ", ¶ms, NULL, &attrs, &error); if(playback_stream==NULL) { if (softrock_get_verbose()) fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); exit(0); } ftime(&start_time); #endif #ifdef PORTAUDIO if (softrock_get_verbose()) fprintf(stderr,"Using PortAudio\n"); rc=Pa_Initialize(); if(rc!=paNoError) { if (softrock_get_verbose()) fprintf(stderr,"Pa_Initialize failed: %s\n",Pa_GetErrorText(rc)); exit(1); } devices=Pa_GetDeviceCount(); if(devices<0) { if (softrock_get_verbose()) fprintf(stderr,"Px_GetDeviceCount failed: %s\n",Pa_GetErrorText(devices)); } else { if (softrock_get_verbose()) fprintf(stderr,"default input=%d output=%d devices=%d\n",Pa_GetDefaultInputDevice(),Pa_GetDefaultOutputDevice(),devices); for(i=0;i<devices;i++) { deviceInfo=Pa_GetDeviceInfo(i); if (softrock_get_verbose()) fprintf(stderr,"%d - %s\n",i,deviceInfo->name); if (softrock_get_verbose()) fprintf(stderr,"maxInputChannels: %d\n",deviceInfo->maxInputChannels); if (softrock_get_verbose()) fprintf(stderr,"maxOututChannels: %d\n",deviceInfo->maxOutputChannels); //if (softrock_get_verbose()) fprintf(stderr,"defaultLowInputLatency: %f\n",deviceInfo->defaultLowInputLatency); //if (softrock_get_verbose()) fprintf(stderr,"defaultLowOutputLatency: %f\n",deviceInfo->defaultLowOutputLatency); //if (softrock_get_verbose()) fprintf(stderr,"defaultHighInputLatency: %f\n",deviceInfo->defaultHighInputLatency); //if (softrock_get_verbose()) fprintf(stderr,"defaultHighOutputLatency: %f\n",deviceInfo->defaultHighOutputLatency); //if (softrock_get_verbose()) fprintf(stderr,"defaultSampleRate: %f\n",deviceInfo->defaultSampleRate); } } inputParameters.device=atoi(softrock_get_input()); inputParameters.channelCount=2; inputParameters.sampleFormat=paFloat32; inputParameters.suggestedLatency=Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo=NULL; outputParameters.device=atoi(softrock_get_output()); outputParameters.channelCount=2; outputParameters.sampleFormat=paFloat32; outputParameters.suggestedLatency=Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo=NULL; if (softrock_get_verbose()) fprintf(stderr,"input device=%d output device=%d\n",inputParameters.device,outputParameters.device); rc=Pa_OpenStream(&stream,&inputParameters,&outputParameters,(double)softrock_get_sample_rate(),(unsigned long)SAMPLES_PER_BUFFER,paNoFlag,NULL,NULL); if(rc!=paNoError) { if (softrock_get_verbose()) fprintf(stderr,"Pa_OpenStream failed: %s\n",Pa_GetErrorText(rc)); exit(1); } rc=Pa_StartStream(stream); if(rc!=paNoError) { if (softrock_get_verbose()) fprintf(stderr,"Pa_StartStream failed: %s\n",Pa_GetErrorText(rc)); exit(1); } info=Pa_GetStreamInfo(stream); if(info!=NULL) { if (softrock_get_verbose()) fprintf(stderr,"stream.sampleRate=%f\n",info->sampleRate); if (softrock_get_verbose()) fprintf(stderr,"stream.inputLatency=%f\n",info->inputLatency); if (softrock_get_verbose()) fprintf(stderr,"stream.outputLatency=%f\n",info->outputLatency); } else { if (softrock_get_verbose()) fprintf(stderr,"Pa_GetStreamInfo returned NULL\n"); } #endif #ifdef DIRECTAUDIO if (softrock_get_verbose()) fprintf(stderr,"Using direct audio\n"); /* open sound device */ fd = open(softrock_get_device(), O_RDWR); if (fd < 0) { perror("open of audio device failed"); exit(1); } /* set sampling parameters */ arg = SAMPLE_SIZE; /* sample size */ status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg); if (status == -1) perror("SOUND_PCM_WRITE_BITS ioctl failed"); if (arg != SAMPLE_SIZE) perror("unable to set write sample size"); status = ioctl(fd, SOUND_PCM_READ_BITS, &arg); if (status == -1) perror("SOUND_PCM_READ_BITS ioctl failed"); if (arg != SAMPLE_SIZE) perror("unable to set read sample size"); arg = CHANNELS; /* mono or stereo */ status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg); if (status == -1) perror("SOUND_PCM_WRITE_CHANNELS ioctl failed"); if (arg != CHANNELS) perror("unable to set number of channels"); arg = softrock_get_sample_rate(); /* sampling rate */ if (softrock_get_verbose()) fprintf(stderr,"sample_rate: %d\n",arg); status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg); if (status == -1) perror("SOUND_PCM_WRITE_WRITE ioctl failed"); arg = AFMT_S16_LE; /* signed little endian */ status = ioctl(fd, SOUND_PCM_SETFMT, &arg); if (status == -1) perror("SOUND_PCM_SETFMTS ioctl failed"); #endif InitBuf(&rx_r, "RX_R"); InitBuf(&rx_l, "RX_R"); printf("my ring buffers are set\n"); return 0; }
/* Internal: Create both player and recorder stream */ static pj_status_t create_bidir_stream(struct pa_aud_factory *pa, const pjmedia_aud_param *param, pjmedia_aud_rec_cb rec_cb, pjmedia_aud_play_cb play_cb, void *user_data, pjmedia_aud_stream **p_snd_strm) { pj_pool_t *pool; pjmedia_aud_dev_index rec_id, play_id; struct pa_aud_stream *stream; PaStream *paStream = NULL; PaStreamParameters inputParam; PaStreamParameters outputParam; int sampleFormat; const PaDeviceInfo *paRecDevInfo = NULL; const PaDeviceInfo *paPlayDevInfo = NULL; const PaHostApiInfo *paRecHostApiInfo = NULL; const PaHostApiInfo *paPlayHostApiInfo = NULL; const PaStreamInfo *paSI; unsigned paFrames, paRate, paInputLatency, paOutputLatency; PaError err; PJ_ASSERT_RETURN(play_cb && rec_cb && p_snd_strm, PJ_EINVAL); rec_id = param->rec_id; if (rec_id < 0) { rec_id = pa_get_default_input_dev(param->channel_count); if (rec_id < 0) { /* No such device. */ return PJMEDIA_EAUD_NODEFDEV; } } paRecDevInfo = Pa_GetDeviceInfo(rec_id); if (!paRecDevInfo) { /* Assumed it is "No such device" error. */ return PJMEDIA_EAUD_INVDEV; } play_id = param->play_id; if (play_id < 0) { play_id = pa_get_default_output_dev(param->channel_count); if (play_id < 0) { /* No such device. */ return PJMEDIA_EAUD_NODEFDEV; } } paPlayDevInfo = Pa_GetDeviceInfo(play_id); if (!paPlayDevInfo) { /* Assumed it is "No such device" error. */ return PJMEDIA_EAUD_INVDEV; } if (param->bits_per_sample == 8) sampleFormat = paUInt8; else if (param->bits_per_sample == 16) sampleFormat = paInt16; else if (param->bits_per_sample == 32) sampleFormat = paInt32; else return PJMEDIA_EAUD_SAMPFORMAT; pool = pj_pool_create(pa->pf, "sndstream", 1024, 1024, NULL); if (!pool) return PJ_ENOMEM; stream = PJ_POOL_ZALLOC_T(pool, struct pa_aud_stream); stream->pool = pool; pj_strdup2_with_null(pool, &stream->name, paRecDevInfo->name); stream->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK; stream->play_id = play_id; stream->rec_id = rec_id; stream->user_data = user_data; stream->samples_per_sec = param->clock_rate; stream->samples_per_frame = param->samples_per_frame; stream->bytes_per_sample = param->bits_per_sample / 8; stream->channel_count = param->channel_count; stream->rec_cb = rec_cb; stream->play_cb = play_cb; stream->rec_buf = (pj_int16_t*)pj_pool_alloc(pool, stream->samples_per_frame * stream->bytes_per_sample); stream->rec_buf_count = 0; stream->play_buf = (pj_int16_t*)pj_pool_alloc(pool, stream->samples_per_frame * stream->bytes_per_sample); stream->play_buf_count = 0; pj_bzero(&inputParam, sizeof(inputParam)); inputParam.device = rec_id; inputParam.channelCount = param->channel_count; inputParam.hostApiSpecificStreamInfo = NULL; inputParam.sampleFormat = sampleFormat; if (param->flags & PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) inputParam.suggestedLatency = param->input_latency_ms / 1000.0; else inputParam.suggestedLatency = PJMEDIA_SND_DEFAULT_REC_LATENCY / 1000.0; paRecHostApiInfo = Pa_GetHostApiInfo(paRecDevInfo->hostApi); pj_bzero(&outputParam, sizeof(outputParam)); outputParam.device = play_id; outputParam.channelCount = param->channel_count; outputParam.hostApiSpecificStreamInfo = NULL; outputParam.sampleFormat = sampleFormat; if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY) outputParam.suggestedLatency=param->output_latency_ms / 1000.0; else outputParam.suggestedLatency=PJMEDIA_SND_DEFAULT_PLAY_LATENCY/1000.0; paPlayHostApiInfo = Pa_GetHostApiInfo(paPlayDevInfo->hostApi); /* Frames in PortAudio is number of samples in a single channel */ paFrames = param->samples_per_frame / param->channel_count; /* If both input and output are on the same device, open a single stream * for both input and output. */ if (rec_id == play_id) { err = Pa_OpenStream( &paStream, &inputParam, &outputParam, param->clock_rate, paFrames, paClipOff, &PaRecorderPlayerCallback, stream ); if (err == paNoError) { /* Set play stream and record stream to the same stream */ stream->play_strm = stream->rec_strm = paStream; } } else { err = -1; } /* .. otherwise if input and output are on the same device, OR if we're * unable to open a bidirectional stream, then open two separate * input and output stream. */ if (paStream == NULL) { /* Open input stream */ err = Pa_OpenStream( &stream->rec_strm, &inputParam, NULL, param->clock_rate, paFrames, paClipOff, &PaRecorderCallback, stream ); if (err == paNoError) { /* Open output stream */ err = Pa_OpenStream( &stream->play_strm, NULL, &outputParam, param->clock_rate, paFrames, paClipOff, &PaPlayerCallback, stream ); if (err != paNoError) Pa_CloseStream(stream->rec_strm); } } if (err != paNoError) { pj_pool_release(pool); return PJMEDIA_AUDIODEV_ERRNO_FROM_PORTAUDIO(err); } paSI = Pa_GetStreamInfo(stream->rec_strm); paRate = (unsigned)(paSI->sampleRate); paInputLatency = (unsigned)(paSI->inputLatency * 1000); paSI = Pa_GetStreamInfo(stream->play_strm); paOutputLatency = (unsigned)(paSI->outputLatency * 1000); PJ_LOG(5,(THIS_FILE, "Opened device %s(%s)/%s(%s) for recording and " "playback, sample rate=%d, ch=%d, " "bits=%d, %d samples per frame, input latency=%d ms, " "output latency=%d ms", paRecDevInfo->name, paRecHostApiInfo->name, paPlayDevInfo->name, paPlayHostApiInfo->name, paRate, param->channel_count, param->bits_per_sample, param->samples_per_frame, paInputLatency, paOutputLatency)); *p_snd_strm = &stream->base; return PJ_SUCCESS; }
_JATTA_EXPORT Jatta::PortAudio::Device Jatta::PortAudio::HostApi::GetDefaultOutputDevice() { return Device(host->defaultOutputDevice, Pa_GetDeviceInfo(host->defaultOutputDevice)); }
int main(void) { PaStreamParameters outputParameters; PaStream *stream; PaError err; paTestData data; #ifdef __APPLE__ PaMacCoreStreamInfo macInfo; const SInt32 channelMap[4] = { -1, -1, 0, 1 }; #endif int i; printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER); printf("Output will be mapped to channels 2 and 3 instead of 0 and 1.\n"); /* initialise sinusoidal wavetable */ for( i=0; i<TABLE_SIZE; i++ ) { data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ); } data.left_phase = data.right_phase = 0; err = Pa_Initialize(); if( err != paNoError ) goto error; /** setup host specific info */ #ifdef __APPLE__ PaMacCore_SetupStreamInfo( &macInfo, paMacCorePlayNice ); PaMacCore_SetupChannelMap( &macInfo, channelMap, 4 ); for( i=0; i<4; ++i ) printf( "channel %d name: %s\n", i, PaMacCore_GetChannelName( Pa_GetDefaultOutputDevice(), i, false ) ); #else printf( "Channel mapping not supported on this platform. Reverting to normal sine test.\n" ); #endif outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ if (outputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default output device.\n"); goto error; } outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; #ifdef __APPLE__ outputParameters.hostApiSpecificStreamInfo = &macInfo; #else outputParameters.hostApiSpecificStreamInfo = NULL; #endif err = Pa_OpenStream( &stream, NULL, /* no input */ &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ patestCallback, &data ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Play for %d seconds.\n", NUM_SECONDS ); Pa_Sleep( NUM_SECONDS * 1000 ); err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); printf("Test finished.\n"); return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
int main(void) { PaStreamParameters outputParameters; PaStream *stream; PaError err; int safeSineCount, stressedSineCount; int safeUnderflowCount, stressedUnderflowCount; paTestData data = {0}; double load; printf("PortAudio Test: output sine waves, count underflows. SR = %d, BufSize = %d. MAX_LOAD = %f\n", SAMPLE_RATE, FRAMES_PER_BUFFER, (float)MAX_LOAD ); err = Pa_Initialize(); if( err != paNoError ) goto error; outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ outputParameters.channelCount = 1; /* mono output */ outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; err = Pa_OpenStream( &stream, NULL, /* no input */ &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ patestCallback, &data ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Establishing load conditions...\n" ); /* Determine number of sines required to get to 50% */ do { data.sineCount++; Pa_Sleep( 100 ); load = Pa_GetStreamCpuLoad( stream ); printf("sineCount = %d, CPU load = %f\n", data.sineCount, load ); } while( load < 0.5 && data.sineCount < (MAX_SINES-1)); safeSineCount = data.sineCount; /* Calculate target stress value then ramp up to that level*/ stressedSineCount = (int) (2.0 * data.sineCount * MAX_LOAD ); if( stressedSineCount > MAX_SINES ) stressedSineCount = MAX_SINES; for( ; data.sineCount < stressedSineCount; data.sineCount++ ) { Pa_Sleep( 100 ); load = Pa_GetStreamCpuLoad( stream ); printf("STRESSING: sineCount = %d, CPU load = %f\n", data.sineCount, load ); } printf("Counting underflows for 5 seconds.\n"); data.countUnderflows = 1; Pa_Sleep( 5000 ); stressedUnderflowCount = data.outputUnderflowCount; data.countUnderflows = 0; data.sineCount = safeSineCount; printf("Resuming safe load...\n"); Pa_Sleep( 1500 ); data.outputUnderflowCount = 0; Pa_Sleep( 1500 ); load = Pa_GetStreamCpuLoad( stream ); printf("sineCount = %d, CPU load = %f\n", data.sineCount, load ); printf("Counting underflows for 5 seconds.\n"); data.countUnderflows = 1; Pa_Sleep( 5000 ); safeUnderflowCount = data.outputUnderflowCount; printf("Stop stream.\n"); err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); if( stressedUnderflowCount == 0 ) printf("Test failed, no output underflows detected under stress.\n"); else if( safeUnderflowCount != 0 ) printf("Test failed, %d unexpected underflows detected under safe load.\n", safeUnderflowCount); else printf("Test passed, %d expected output underflows detected under stress, 0 unexpected underflows detected under safe load.\n", stressedUnderflowCount ); return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
int main(void) { PaStreamParameters outputParameters; PaStream *stream; PaError err; float buffer[FRAMES_PER_BUFFER][2]; /* stereo output buffer */ float sine[TABLE_SIZE]; /* sine wavetable */ int left_phase = 0; int right_phase = 0; int left_inc = 1; int right_inc = 3; /* higher pitch so we can distinguish left and right. */ int i, j, k; int bufferCount; printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER); /* initialise sinusoidal wavetable */ for( i=0; i<TABLE_SIZE; i++ ) { sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ); } err = Pa_Initialize(); if( err != paNoError ) goto error; outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; err = Pa_OpenStream( &stream, NULL, /* no input */ &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ NULL, /* no callback, use blocking API */ NULL ); /* no callback, so no callback userData */ if( err != paNoError ) goto error; printf( "Play 3 times, higher each time.\n" ); for( k=0; k < 3; ++k ) { err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Play for %d seconds.\n", NUM_SECONDS ); bufferCount = ((NUM_SECONDS * SAMPLE_RATE) / FRAMES_PER_BUFFER); for( i=0; i < bufferCount; i++ ) { for( j=0; j < FRAMES_PER_BUFFER; j++ ) { buffer[j][0] = sine[left_phase]; /* left */ buffer[j][1] = sine[right_phase]; /* right */ left_phase += left_inc; if( left_phase >= TABLE_SIZE ) left_phase -= TABLE_SIZE; right_phase += right_inc; if( right_phase >= TABLE_SIZE ) right_phase -= TABLE_SIZE; } err = Pa_WriteStream( stream, buffer, FRAMES_PER_BUFFER ); if( err != paNoError ) goto error; } err = Pa_StopStream( stream ); if( err != paNoError ) goto error; ++left_inc; ++right_inc; Pa_Sleep( 1000 ); } err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); printf("Test finished.\n"); return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
int main(void) { PaStreamParameters outputParameters; PaStream *stream; PaError err; paTestData data; int i; printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER); /* initialise sinusoidal wavetable */ for( i=0; i<TABLE_SIZE; i++ ) { data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ); } data.left_phase = data.right_phase = 0; err = Pa_Initialize(); if( err != paNoError ) goto error; outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; err = Pa_OpenStream( &stream, NULL, /* no input */ &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* we won't output out of range samples so don't bother clipping them */ patestCallback, &data ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Play for %d seconds.\n", NUM_SECONDS ); Pa_Sleep( NUM_SECONDS * 1000 ); err = Pa_StopStream( stream ); if( err != paNoError ) goto error; err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); printf("Test finished.\n"); return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
int sdr1000_open(void) { int arg; int status; int rc; #ifdef PORTAUDIO PaStreamParameters inputParameters; PaStreamParameters outputParameters; const PaStreamInfo *info; int devices; int i; const PaDeviceInfo* deviceInfo; fprintf(stderr,"sdr1000_open: portaudio\n"); #else fprintf(stderr,"sdr1000_open: %s\n",sdr1000_get_device()); #endif #ifdef PORTAUDIO rc=Pa_Initialize(); if(rc!=paNoError) { fprintf(stderr,"Pa_Initialize failed: %s\n",Pa_GetErrorText(rc)); exit(1); } devices=Pa_GetDeviceCount(); if(devices<0) { fprintf(stderr,"Px_GetDeviceCount failed: %s\n",Pa_GetErrorText(devices)); } else { fprintf(stderr,"default input=%d output=%d devices=%d\n",Pa_GetDefaultInputDevice(),Pa_GetDefaultOutputDevice(),devices); for(i=0;i<devices;i++) { deviceInfo=Pa_GetDeviceInfo(i); fprintf(stderr,"%d - %s\n",i,deviceInfo->name); fprintf(stderr,"maxInputChannels: %d\n",deviceInfo->maxInputChannels); fprintf(stderr,"maxOututChannels: %d\n",deviceInfo->maxOutputChannels); //fprintf(stderr,"defaultLowInputLatency: %f\n",deviceInfo->defaultLowInputLatency); //fprintf(stderr,"defaultLowOutputLatency: %f\n",deviceInfo->defaultLowOutputLatency); //fprintf(stderr,"defaultHighInputLatency: %f\n",deviceInfo->defaultHighInputLatency); //fprintf(stderr,"defaultHighOutputLatency: %f\n",deviceInfo->defaultHighOutputLatency); //fprintf(stderr,"defaultSampleRate: %f\n",deviceInfo->defaultSampleRate); } } inputParameters.device=atoi(sdr1000_get_input()); inputParameters.channelCount=2; inputParameters.sampleFormat=paFloat32; inputParameters.suggestedLatency=Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo=NULL; outputParameters.device=atoi(sdr1000_get_output()); outputParameters.channelCount=2; outputParameters.sampleFormat=paFloat32; outputParameters.suggestedLatency=Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo=NULL; fprintf(stderr,"input device=%d output device=%d\n",inputParameters.device,outputParameters.device); rc=Pa_OpenStream(&stream,&inputParameters,&outputParameters,(double)sdr1000_get_sample_rate(),(unsigned long)SAMPLES_PER_BUFFER,paNoFlag,NULL,NULL); if(rc!=paNoError) { fprintf(stderr,"Pa_OpenStream failed: %s\n",Pa_GetErrorText(rc)); exit(1); } rc=Pa_StartStream(stream); if(rc!=paNoError) { fprintf(stderr,"Pa_StartStream failed: %s\n",Pa_GetErrorText(rc)); exit(1); } info=Pa_GetStreamInfo(stream); if(info!=NULL) { fprintf(stderr,"stream.sampleRate=%f\n",info->sampleRate); fprintf(stderr,"stream.inputLatency=%f\n",info->inputLatency); fprintf(stderr,"stream.outputLatency=%f\n",info->outputLatency); } else { fprintf(stderr,"Pa_GetStreamInfo returned NULL\n"); } #else /* open sound device */ fd = open(sdr1000_get_device(), O_RDWR); if (fd < 0) { perror("open of audio device failed"); exit(1); } /* set sampling parameters */ arg = SAMPLE_SIZE; /* sample size */ status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg); if (status == -1) perror("SOUND_PCM_WRITE_BITS ioctl failed"); if (arg != SAMPLE_SIZE) perror("unable to set write sample size"); status = ioctl(fd, SOUND_PCM_READ_BITS, &arg); if (status == -1) perror("SOUND_PCM_READ_BITS ioctl failed"); if (arg != SAMPLE_SIZE) perror("unable to set read sample size"); arg = CHANNELS; /* mono or stereo */ status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg); if (status == -1) perror("SOUND_PCM_WRITE_CHANNELS ioctl failed"); if (arg != CHANNELS) perror("unable to set number of channels"); arg = sdr1000_get_sample_rate(); /* sampling rate */ fprintf(stderr,"sample_rate: %d\n",arg); status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg); if (status == -1) perror("SOUND_PCM_WRITE_WRITE ioctl failed"); arg = AFMT_S16_LE; /* signed little endian */ status = ioctl(fd, SOUND_PCM_SETFMT, &arg); if (status == -1) perror("SOUND_PCM_SETFMTS ioctl failed"); #endif return 0; }
static int PAOpenDevice( aout_instance_t *p_aout ) { aout_sys_t *p_sys = p_aout->output.p_sys; const PaDeviceInfo *p_pdi; PaError i_err; vlc_value_t val, text; int i; /* Initialize portaudio */ i_err = Pa_Initialize(); if( i_err != paNoError ) { msg_Err( p_aout, "Pa_Initialize returned %d : %s", i_err, Pa_GetErrorText( i_err ) ); return VLC_EGENERIC; } p_sys->i_devices = Pa_GetDeviceCount(); if( p_sys->i_devices < 0 ) { i_err = p_sys->i_devices; msg_Err( p_aout, "Pa_GetDeviceCount returned %d : %s", i_err, Pa_GetErrorText( i_err ) ); goto error; } /* Display all devices info */ msg_Dbg( p_aout, "number of devices = %d", p_sys->i_devices ); for( i = 0; i < p_sys->i_devices; i++ ) { p_pdi = Pa_GetDeviceInfo( i ); msg_Dbg( p_aout, "------------------------------------- #%d", i ); msg_Dbg( p_aout, "Name = %s", p_pdi->name ); msg_Dbg( p_aout, "Max Inputs = %d, Max Outputs = %d", p_pdi->maxInputChannels, p_pdi->maxOutputChannels ); } msg_Dbg( p_aout, "-------------------------------------" ); msg_Dbg( p_aout, "requested device is #%d", p_sys->i_device_id ); if( p_sys->i_device_id >= p_sys->i_devices ) { msg_Err( p_aout, "device %d does not exist", p_sys->i_device_id ); goto error; } p_sys->deviceInfo = Pa_GetDeviceInfo( p_sys->i_device_id ); if( p_sys->deviceInfo->maxOutputChannels < 1 ) { msg_Err( p_aout, "no channel available" ); goto error; } if( var_Type( p_aout, "audio-device" ) == 0 ) { var_Create( p_aout, "audio-device", VLC_VAR_INTEGER|VLC_VAR_HASCHOICE); text.psz_string = _("Audio Device"); var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL ); if( p_sys->deviceInfo->maxOutputChannels >= 1 ) { val.i_int = AOUT_VAR_MONO; text.psz_string = _("Mono"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 1 channel" ); } if( p_sys->deviceInfo->maxOutputChannels >= 2 ) { val.i_int = AOUT_VAR_STEREO; text.psz_string = _("Stereo"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL ); var_Set( p_aout, "audio-device", val ); msg_Dbg( p_aout, "device supports 2 channels" ); } if( p_sys->deviceInfo->maxOutputChannels >= 4 ) { val.i_int = AOUT_VAR_2F2R; text.psz_string = _("2 Front 2 Rear"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 4 channels" ); } if( p_sys->deviceInfo->maxOutputChannels >= 5 ) { val.i_int = AOUT_VAR_3F2R; text.psz_string = _("3 Front 2 Rear"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 5 channels" ); } if( p_sys->deviceInfo->maxOutputChannels >= 6 ) { val.i_int = AOUT_VAR_5_1; text.psz_string = "5.1"; var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 5.1 channels" ); } var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL ); var_SetBool( p_aout, "intf-change", true ); } /* Audio format is paFloat32 (always supported by portaudio v19) */ p_aout->output.output.i_format = VLC_CODEC_FL32; return VLC_SUCCESS; error: if( ( i_err = Pa_Terminate() ) != paNoError ) { msg_Err( p_aout, "Pa_Terminate returned %d", i_err ); } return VLC_EGENERIC; }
int main(void) { PaStreamParameters outputParameters; PaStream *stream; PaError err; TestData data; int i, j; printf( "PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER ); /* initialise sinusoidal wavetable */ for( i=0; i<TABLE_SIZE; i++ ) { data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ); } err = Pa_Initialize(); if( err != paNoError ) goto error; outputParameters.device = Pa_GetDefaultOutputDevice(); outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; err = Pa_OpenStream( &stream, NULL, /* no input */ &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, /* output will be in-range, so no need to clip */ TestCallback, &data ); if( err != paNoError ) goto error; printf("Repeating test %d times.\n", NUM_LOOPS ); for( i=0; i < NUM_LOOPS; ++i ) { data.phase = 0; data.generatedFramesCount = 0; data.callbackReturnedPaComplete = 0; data.callbackInvokedAfterReturningPaComplete = 0; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Play for %d seconds.\n", NUM_SECONDS ); /* wait for the callback to complete generating NUM_SECONDS of tone */ do { Pa_Sleep( 500 ); } while( !data.callbackReturnedPaComplete ); printf( "Callback returned paComplete.\n" ); printf( "Waiting for buffers to finish playing...\n" ); /* wait for stream to become inactive, or for a timeout of approximately NUM_SECONDS */ j = 0; while( (err = Pa_IsStreamActive( stream )) == 1 && j < NUM_SECONDS * 2 ) { printf(".\n" ); Pa_Sleep( 500 ); ++j; } if( err < 0 ) { goto error; } else if( err == 1 ) { printf( "TEST FAILED: Timed out waiting for buffers to finish playing.\n" ); } else { printf("Buffers finished.\n" ); } if( data.callbackInvokedAfterReturningPaComplete ) { printf( "TEST FAILED: Callback was invoked after returning paComplete.\n" ); } err = Pa_StopStream( stream ); if( err != paNoError ) goto error; } err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); printf("Test finished.\n"); return err; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
JNIEXPORT jobject JNICALL Java_com_github_rjeschke_jpa_JPA_getDeviceInfo(JNIEnv *env, jclass clazz, jint index) { const PaDeviceInfo *inf = Pa_GetDeviceInfo((PaDeviceIndex)index); return inf ? toPaDeviceInfo(env, inf) : 0; }
int main(void) { int i, numDevices, defaultDisplayed; const PaDeviceInfo *deviceInfo; PaStreamParameters inputParameters, outputParameters; PaError err; Pa_Initialize(); printf( "PortAudio version number = %d\nPortAudio version text = '%s'\n", Pa_GetVersion(), Pa_GetVersionText() ); numDevices = Pa_GetDeviceCount(); if( numDevices < 0 ) { printf( "ERROR: Pa_CountDevices returned 0x%x\n", numDevices ); err = numDevices; goto error; } printf( "Number of devices = %d\n", numDevices ); for( i=0; i<numDevices; i++ ) { deviceInfo = Pa_GetDeviceInfo( i ); printf( "--------------------------------------- device #%d\n", i ); /* Mark global and API specific default devices */ defaultDisplayed = 0; if( i == Pa_GetDefaultInputDevice() ) { printf( "[ Default Input" ); defaultDisplayed = 1; } else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultInputDevice ) { const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); printf( "[ Default %s Input", hostInfo->name ); defaultDisplayed = 1; } if( i == Pa_GetDefaultOutputDevice() ) { printf( (defaultDisplayed ? "," : "[") ); printf( " Default Output" ); defaultDisplayed = 1; } else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultOutputDevice ) { const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); printf( (defaultDisplayed ? "," : "[") ); printf( " Default %s Output", hostInfo->name ); defaultDisplayed = 1; } if( defaultDisplayed ) printf( " ]\n" ); /* print device info fields */ printf( "Name = %s\n", deviceInfo->name ); printf( "Host API = %s\n", Pa_GetHostApiInfo( deviceInfo->hostApi )->name ); printf( "Max inputs = %d", deviceInfo->maxInputChannels ); printf( ", Max outputs = %d\n", deviceInfo->maxOutputChannels ); printf( "Default low input latency = %8.3f\n", deviceInfo->defaultLowInputLatency ); printf( "Default low output latency = %8.3f\n", deviceInfo->defaultLowOutputLatency ); printf( "Default high input latency = %8.3f\n", deviceInfo->defaultHighInputLatency ); printf( "Default high output latency = %8.3f\n", deviceInfo->defaultHighOutputLatency ); #ifdef WIN32 #ifndef PA_NO_ASIO /* ASIO specific latency information */ if( Pa_GetHostApiInfo( deviceInfo->hostApi )->type == paASIO ){ long minLatency, maxLatency, preferredLatency, granularity; err = PaAsio_GetAvailableLatencyValues( i, &minLatency, &maxLatency, &preferredLatency, &granularity ); printf( "ASIO minimum buffer size = %ld\n", minLatency ); printf( "ASIO maximum buffer size = %ld\n", maxLatency ); printf( "ASIO preferred buffer size = %ld\n", preferredLatency ); if( granularity == -1 ) printf( "ASIO buffer granularity = power of 2\n" ); else printf( "ASIO buffer granularity = %ld\n", granularity ); } #endif /* !PA_NO_ASIO */ #endif /* WIN32 */ printf( "Default sample rate = %8.2f\n", deviceInfo->defaultSampleRate ); /* poll for standard sample rates */ inputParameters.device = i; inputParameters.channelCount = deviceInfo->maxInputChannels; inputParameters.sampleFormat = paInt16; inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */ inputParameters.hostApiSpecificStreamInfo = NULL; outputParameters.device = i; outputParameters.channelCount = deviceInfo->maxOutputChannels; outputParameters.sampleFormat = paInt16; outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */ outputParameters.hostApiSpecificStreamInfo = NULL; if( inputParameters.channelCount > 0 ) { printf("Supported standard sample rates\n for half-duplex 16 bit %d channel input = \n", inputParameters.channelCount ); PrintSupportedStandardSampleRates( &inputParameters, NULL ); } if( outputParameters.channelCount > 0 ) { printf("Supported standard sample rates\n for half-duplex 16 bit %d channel output = \n", outputParameters.channelCount ); PrintSupportedStandardSampleRates( NULL, &outputParameters ); } if( inputParameters.channelCount > 0 && outputParameters.channelCount > 0 ) { printf("Supported standard sample rates\n for full-duplex 16 bit %d channel input, %d channel output = \n", inputParameters.channelCount, outputParameters.channelCount ); PrintSupportedStandardSampleRates( &inputParameters, &outputParameters ); } } Pa_Terminate(); printf("----------------------------------------------\n"); return 0; error: Pa_Terminate(); fprintf( stderr, "An error occured while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; }
/*-------------------------------------------------------------------------------------------------*/ static int TestBadOpens( void ) { PaStream* stream = NULL; PaError result; PaQaData myData; PaStreamParameters ipp, opp; /* Setup data for synthesis thread. */ myData.framesLeft = (unsigned long) (SAMPLE_RATE * 100); /* 100 seconds */ myData.numChannels = 1; myData.mode = MODE_OUTPUT; /*----------------------------- No devices specified: */ ipp.device = opp.device = paNoDevice; ipp.channelCount = opp.channelCount = 0; /* Also no channels. */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; /* Take the low latency of the default device for all subsequent tests. */ ipp.suggestedLatency = Pa_GetDeviceInfo(Pa_GetDefaultInputDevice())->defaultLowInputLatency; opp.suggestedLatency = Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice())->defaultLowOutputLatency; HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, &opp, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidDevice)); /*----------------------------- No devices specified #2: */ HOPEFOR(((result = Pa_OpenStream(&stream, NULL, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidDevice)); /*----------------------------- Out of range input device specified: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = Pa_GetDeviceCount(); /* And no output device, and no channels. */ opp.channelCount = 0; opp.device = paNoDevice; HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidDevice)); /*----------------------------- Out of range output device specified: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = paNoDevice; /* And no input device, and no channels. */ opp.channelCount = 0; opp.device = Pa_GetDeviceCount(); HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidDevice)); /*----------------------------- Zero input channels: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = Pa_GetDefaultInputDevice(); opp.channelCount = 0; opp.device = paNoDevice; /* And no output device, and no output channels. */ HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidChannelCount)); /*----------------------------- Zero output channels: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = paNoDevice; /* And no input device, and no input channels. */ opp.channelCount = 0; opp.device = Pa_GetDefaultOutputDevice(); HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidChannelCount)); /*----------------------------- Nonzero input and output channels but no output device: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 2; ipp.device = Pa_GetDefaultInputDevice(); /* Both stereo. */ opp.channelCount = 2; opp.device = paNoDevice; HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, &opp, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidDevice)); /*----------------------------- Nonzero input and output channels but no input device: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 2; ipp.device = paNoDevice; opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice(); HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, &opp, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidDevice)); /*----------------------------- NULL stream pointer: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = paNoDevice; /* Output is more likely than input. */ opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice(); /* Only 2 output channels. */ HOPEFOR(((result = Pa_OpenStream(NULL, &ipp, &opp, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paBadStreamPtr)); /*----------------------------- Low sample rate: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = paNoDevice; opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice(); HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp, 1.0, FRAMES_PER_BUFFER, /* 1 cycle per second (1 Hz) is too low. */ paClipOff, QaCallback, &myData )) == paInvalidSampleRate)); /*----------------------------- High sample rate: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = paNoDevice; opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice(); HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp, 10000000.0, FRAMES_PER_BUFFER, /* 10^6 cycles per second (10 MHz) is too high. */ paClipOff, QaCallback, &myData )) == paInvalidSampleRate)); /*----------------------------- NULL callback: */ /* NULL callback is valid in V19 -- it means use blocking read/write stream ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = paNoDevice; opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice(); HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, NULL, &myData )) == paNullCallback)); */ /*----------------------------- Bad flag: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = paNoDevice; opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice(); HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp, SAMPLE_RATE, FRAMES_PER_BUFFER, 255, /* Is 8 maybe legal V19 API? */ QaCallback, &myData )) == paInvalidFlag)); /*----------------------------- using input device as output device: */ if( FindInputOnlyDevice() != paNoDevice ) { ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = paNoDevice; /* And no input device, and no channels. */ opp.channelCount = 2; opp.device = FindInputOnlyDevice(); HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidChannelCount)); } /*----------------------------- using output device as input device: */ if( FindOutputOnlyDevice() != paNoDevice ) { ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 2; ipp.device = FindOutputOnlyDevice(); opp.channelCount = 0; opp.device = paNoDevice; /* And no output device, and no channels. */ HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidChannelCount)); } if( stream != NULL ) Pa_CloseStream( stream ); return result; }
s32 Init() { started=false; stream=NULL; ReadSettings(); PaError err = Pa_Initialize(); if( err != paNoError ) { fprintf(stderr,"* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText( err ) ); return -1; } started=true; int deviceIndex = -1; fprintf(stderr,"* SPU2-X: Enumerating PortAudio devices:"); for(int i=0;i<Pa_GetDeviceCount();i++) { const PaDeviceInfo * info = Pa_GetDeviceInfo(i); const PaHostApiInfo * apiinfo = Pa_GetHostApiInfo(info->hostApi); fprintf(stderr," *** Device %d: '%s' (%s)", i, info->name, apiinfo->name); if(apiinfo->type == m_ApiId) { static wchar_t buffer [1000]; mbstowcs(buffer,info->name,1000); buffer[999]=0; if(m_Device == buffer) { deviceIndex = i; fprintf(stderr," (selected)"); } } fprintf(stderr,"\n"); } if(deviceIndex<0 && m_ApiId>=0) { for(int i=0;i<Pa_GetHostApiCount();i++) { const PaHostApiInfo * apiinfo = Pa_GetHostApiInfo(i); if(apiinfo->type == m_ApiId) { deviceIndex = apiinfo->defaultOutputDevice; } } } if(deviceIndex>=0) { void* infoPtr = NULL; #ifdef __WIN32__ PaWasapiStreamInfo info = { sizeof(PaWasapiStreamInfo), paWASAPI, 1, paWinWasapiExclusive }; if((m_ApiId == paWASAPI) && m_WasapiExclusiveMode) { // Pass it the Exclusive mode enable flag infoPtr = &info; } #endif PaStreamParameters outParams = { // PaDeviceIndex device; // int channelCount; // PaSampleFormat sampleFormat; // PaTime suggestedLatency; // void *hostApiSpecificStreamInfo; deviceIndex, 2, paInt32, 0.2f, infoPtr }; err = Pa_OpenStream(&stream, NULL, &outParams, SampleRate, SndOutPacketSize, paNoFlag, #ifndef __LINUX__ PaCallback, #else PaLinuxCallback, #endif NULL); } else { err = Pa_OpenDefaultStream( &stream, 0, 2, paInt32, 48000, SndOutPacketSize, #ifndef __LINUX__ PaCallback, #else PaLinuxCallback, #endif NULL ); } if( err != paNoError ) { fprintf(stderr,"* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText( err ) ); Pa_Terminate(); return -1; } err = Pa_StartStream( stream ); if( err != paNoError ) { fprintf(stderr,"* SPU2-X: PortAudio error: %s\n", Pa_GetErrorText( err ) ); Pa_CloseStream(stream); stream=NULL; Pa_Terminate(); return -1; } return 0; }
void* RecieveClientThread(void* data) // recieve udp packets containing message/voice to the other client { struct thread* new_data = data; printf("you are recieving from %s IP address\n", new_data->IPaddr); PaStreamParameters outputParam; PaStream *stream = NULL; char *sampleBlock; int i, sockfd, numBytes; PaError error; struct sockaddr_in servaddr, cliaddr; sockfd = socket(AF_INET, SOCK_DGRAM, 0); // make udp socket bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(new_data->IPaddr); servaddr.sin_port = htons(new_data->Port); bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); fflush(stdout); numBytes = FRAMES_BUFFER * SAMPLE_SIZE * 2; sampleBlock = (char *) malloc(numBytes); if(sampleBlock == NULL){ printf("Could not allocate record array.\n"); exit(1); } CLEAR(sampleBlock); printf("Initializing the devices...\n"); error = Pa_Initialize(); if(error != paNoError) goto errorState; outputParam.device = Pa_GetDefaultOutputDevice(); printf( "Output device # %d.\n", outputParam.device ); outputParam.channelCount = 2; outputParam.sampleFormat = paFloat32; outputParam.suggestedLatency = Pa_GetDeviceInfo( outputParam.device )->defaultHighOutputLatency; outputParam.hostApiSpecificStreamInfo = NULL; error = Pa_OpenStream(&stream, NULL, &outputParam, SAMPLE_RATE, FRAMES_BUFFER, paClipOff, NULL, NULL ); if( error != paNoError ) goto errorState; error = Pa_StartStream( stream ); if( error != paNoError ) goto errorState; printf("The client is talking to you\n"); fflush(stdout); while(1){ recvfrom(sockfd, sampleBlock, 4096, 0, NULL, NULL); // recieve packet containing voice data from the other client error = Pa_WriteStream(stream, sampleBlock, FRAMES_BUFFER); if(error && UNDERFLOW) goto exitState; } error = Pa_StopStream(stream); if(error != paNoError) goto errorState; CLEAR(sampleBlock); free(sampleBlock); Pa_Terminate(); return 0; exitState: if(stream){ Pa_AbortStream(stream); Pa_CloseStream(stream); } free(sampleBlock); Pa_Terminate(); if(error & paOutputUnderflow) fprintf(stderr, "Output Underflow.\n"); return (void*)-2; errorState: if(stream) { Pa_AbortStream(stream); Pa_CloseStream(stream); } free(sampleBlock); Pa_Terminate(); fprintf(stderr, "An error occured while using the portaudio stream\n"); fprintf(stderr, "Error number: %d\n", error); fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(error)); return (void*)-1; }