static int TestBadActions( void ) { PortAudioStream *stream = NULL; PaError result; PaQaData myData; /* Setup data for synthesis thread. */ myData.framesLeft = (unsigned long) (SAMPLE_RATE * 100); /* 100 seconds */ myData.numChannels = 1; myData.mode = MODE_OUTPUT; /* Default output. */ EXPECT( "TestBadActions", ((result = Pa_OpenStream( &stream, paNoDevice, 0, paFloat32, NULL, Pa_GetDefaultOutputDeviceID(), 2, paFloat32, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, NUM_BUFFERS, paClipOff, QaCallback, &myData ) ) == 0) ); HOPEFOR( "start", ((result = Pa_StartStream( NULL )) == paBadStreamPtr) ); HOPEFOR( "stop", ((result = Pa_StopStream( NULL )) == paBadStreamPtr) ); HOPEFOR( "active?", ((result = Pa_StreamActive( NULL )) == paBadStreamPtr) ); HOPEFOR( "close", ((result = Pa_CloseStream( NULL )) == paBadStreamPtr) ); HOPEFOR( "time?", ((result = (PaError)Pa_StreamTime( NULL )) != 0) ); HOPEFOR( "CPULoad?", ((result = (PaError)Pa_GetCPULoad( NULL )) != 0) ); error: if( stream != NULL ) Pa_CloseStream( stream ); return result; }
int main(int argc, char* argv[]) { PaStream *stream; PaError err; patest1data data; int i; int inputDevice = Pa_GetDefaultInputDeviceID(); int outputDevice = Pa_GetDefaultOutputDeviceID(); /* initialise sinusoidal wavetable */ for( i=0; i<100; i++ ) data.sine[i] = sin( ((double)i/100.) * M_PI * 2. ); data.phase = 0; data.sampsToGo = 44100 * 4; // 20 seconds /* initialise portaudio subsytem */ Pa_Initialize(); err = Pa_OpenStream( &stream, inputDevice, 2, /* stereo input */ paFloat32, /* 32 bit floating point input */ NULL, outputDevice, 2, /* stereo output */ paFloat32, /* 32 bit floating point output */ NULL, 44100., // 22050, /* half second buffers */ // 4, /* four buffers */ 512, /* half second buffers */ 0, /* four buffers */ paClipOff, /* we won't output out of range samples so don't bother clipping them */ patest1Callback, &data ); if( err == paNoError ) { err = Pa_StartStream( stream ); // printf( "Press any key to end.\n" ); // getc( stdin ); //wait for input before exiting // Pa_AbortStream( stream ); printf( "Waiting for stream to complete...\n" ); while( Pa_StreamActive( stream ) ) Pa_Sleep(1000); /* sleep until playback has finished */ err = Pa_CloseStream( stream ); } else { fprintf( stderr, "An error occured while opening the portaudio stream\n" ); if( err == paHostError ) fprintf( stderr, "Host error number: %d\n", Pa_GetHostError() ); else fprintf( stderr, "Error number: %d\n", err ); } Pa_Terminate(); printf( "bye\n" ); return 0; }
int main(void) { PortAudioStream *stream; PaError err; paTestData data; int totalSamps; printf("PortAudio Test: output " FORMAT_NAME "\n"); data.left_phase = data.right_phase = 0.0; data.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */ err = Pa_Initialize(); if( err != paNoError ) goto error; err = Pa_OpenStream( &stream, paNoDevice,/* default input device */ 0, /* no input */ TEST_FORMAT, NULL, Pa_GetDefaultOutputDeviceID(), /* default output device */ 2, /* stereo output */ TEST_FORMAT, NULL, SAMPLE_RATE, 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; printf("Waiting %d seconds for sound to finish.\n", NUM_SECONDS ); while( Pa_StreamActive( stream ) ) Pa_Sleep(10); err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; Pa_Terminate(); printf("PortAudio Test Finished: " FORMAT_NAME "\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 wave_is_busy(void *theHandler) { (void)theHandler; // unused PaError active = 0; if (pa_stream) { #if USE_PORTAUDIO == 18 active = Pa_StreamActive(pa_stream) && (mInCallbackFinishedState == false); #else active = Pa_IsStreamActive(pa_stream) && (mInCallbackFinishedState == false); #endif } return active == 1; }
int wave_is_busy(void* theHandler) { PaError active=0; SHOW_TIME("wave_is_busy"); if (pa_stream) { #if USE_PORTAUDIO == 18 active = Pa_StreamActive(pa_stream) && (mInCallbackFinishedState == false); #else active = Pa_IsStreamActive(pa_stream) && (mInCallbackFinishedState == false); #endif } SHOW("wave_is_busy: %d\n",active); return (active==1); }
int TestStopMode( paTestData *data ) { PortAudioStream *stream; PaError err; data->done = 0; data->phase = 0.0; data->frameCounter = 0; data->noteCounter = 0; data->repeatCounter = 0; data->phase_increment = data->tune[data->noteCounter]; err = Pa_Initialize(); if( err != paNoError ) goto error; err = Pa_OpenStream( &stream, paNoDevice,/* default input device */ 0, /* no input */ paFloat32, /* 32 bit floating point input */ NULL, OUTPUT_DEVICE, 2, /* stereo output */ 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; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; if( data->stopMode == MODE_FINISH ) { while( Pa_StreamActive( stream ) ) { /*printf("outTime = %g, note# = %d, repeat# = %d\n", data->outTime, data->noteCounter, data->repeatCounter ); fflush(stdout); /**/ Pa_Sleep( SLEEP_DUR ); } } else { while( data->repeatCounter < MAX_REPEATS ) { /*printf("outTime = %g, note# = %d, repeat# = %d\n", data->outTime, data->noteCounter, data->repeatCounter ); fflush(stdout); /**/ Pa_Sleep( SLEEP_DUR ); } } if( data->stopMode == MODE_ABORT ) { printf("Call Pa_AbortStream()\n"); err = Pa_AbortStream( stream ); } else { printf("Call Pa_StopStream()\n"); err = Pa_StopStream( stream ); } if( err != paNoError ) goto error; printf("Call Pa_CloseStream()\n"); fflush(stdout); 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 wave_close(void* theHandler) { SHOW_TIME("wave_close > ENTER"); static int aStopStreamCount = 0; #if (USE_PORTAUDIO == 19) if( pa_stream == NULL ) { SHOW_TIME("wave_close > LEAVE (NULL stream)"); return 0; } if( Pa_IsStreamStopped( pa_stream ) ) { SHOW_TIME("wave_close > LEAVE (stopped)"); return 0; } #else if( pa_stream == NULL ) { SHOW_TIME("wave_close > LEAVE (NULL stream)"); return 0; } if( Pa_StreamActive( pa_stream ) == false && mInCallbackFinishedState == false ) { SHOW_TIME("wave_close > LEAVE (not active)"); return 0; } #endif // Avoid race condition by making sure this function only // gets called once at a time aStopStreamCount++; if (aStopStreamCount != 1) { SHOW_TIME("wave_close > LEAVE (stopStreamCount)"); return 0; } // Comment from Audacity-1.2.4b adapted to the eSpeak context. // // We got here in one of two ways: // // 1. The calling program calls the espeak_Cancel function and we // therefore want to stop as quickly as possible. // So we use AbortStream(). If this is // the case the portaudio stream is still in the Running state // (see PortAudio state machine docs). // // 2. The callback told PortAudio to stop the stream since it had // reached the end of the selection. // The event polling thread discovered this by noticing that // wave_is_busy() returned false. // wave_is_busy() (which calls Pa_GetStreamActive()) will not return // false until all buffers have finished playing, so we can call // AbortStream without losing any samples. If this is the case // we are in the "callback finished state" (see PortAudio state // machine docs). // // The moral of the story: We can call AbortStream safely, without // losing samples. // // DMM: This doesn't seem to be true; it seems to be necessary to // call StopStream if the callback brought us here, and AbortStream // if the user brought us here. // #if (USE_PORTAUDIO == 19) if (pa_stream) { Pa_AbortStream( pa_stream ); SHOW_TIME("wave_close > Pa_AbortStream (end)"); Pa_CloseStream( pa_stream ); SHOW_TIME("wave_close > Pa_CloseStream (end)"); pa_stream = NULL; mInCallbackFinishedState = false; } #else if (pa_stream) { if (mInCallbackFinishedState) { Pa_StopStream( pa_stream ); SHOW_TIME("wave_close > Pa_StopStream (end)"); } else { Pa_AbortStream( pa_stream ); SHOW_TIME("wave_close > Pa_AbortStream (end)"); } Pa_CloseStream( pa_stream ); SHOW_TIME("wave_close > Pa_CloseStream (end)"); pa_stream = NULL; mInCallbackFinishedState = false; } #endif init_buffer(); aStopStreamCount = 0; // last action SHOW_TIME("wave_close > LEAVE"); return 0; }
static int wave_open_sound() { ENTER("wave_open_sound"); PaError err=paNoError; PaError active; #if USE_PORTAUDIO == 18 active = Pa_StreamActive(pa_stream); #else active = Pa_IsStreamActive(pa_stream); #endif if(active == 1) { SHOW_TIME("wave_open_sound > already active"); return(0); } if(active < 0) { out_channels = 1; #if USE_PORTAUDIO == 18 // err = Pa_OpenDefaultStream(&pa_stream,0,1,paInt16,wave_samplerate,FRAMES_PER_BUFFER,N_WAV_BUF,pa_callback,(void *)userdata); PaDeviceID playbackDevice = Pa_GetDefaultOutputDeviceID(); PaError err = Pa_OpenStream( &pa_stream, /* capture parameters */ paNoDevice, 0, paInt16, NULL, /* playback parameters */ playbackDevice, out_channels, paInt16, NULL, /* general parameters */ wave_samplerate, FRAMES_PER_BUFFER, 0, //paClipOff | paDitherOff, paNoFlag, pa_callback, (void *)userdata); SHOW("wave_open_sound > Pa_OpenDefaultStream(1): err=%d (%s)\n",err, Pa_GetErrorText(err)); if(err == paInvalidChannelCount) { SHOW_TIME("wave_open_sound > try stereo"); // failed to open with mono, try stereo out_channels = 2; // myOutputParameters.channelCount = out_channels; PaError err = Pa_OpenStream( &pa_stream, /* capture parameters */ paNoDevice, 0, paInt16, NULL, /* playback parameters */ playbackDevice, out_channels, paInt16, NULL, /* general parameters */ wave_samplerate, FRAMES_PER_BUFFER, 0, //paClipOff | paDitherOff, paNoFlag, pa_callback, (void *)userdata); // err = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16, // wave_samplerate, // FRAMES_PER_BUFFER, // N_WAV_BUF,pa_callback,(void *)userdata); SHOW("wave_open_sound > Pa_OpenDefaultStream(2): err=%d (%s)\n",err, Pa_GetErrorText(err)); err=0; // avoid warning } mInCallbackFinishedState = false; // v18 only #else myOutputParameters.channelCount = out_channels; unsigned long framesPerBuffer = paFramesPerBufferUnspecified; err = Pa_OpenStream( &pa_stream, NULL, /* no input */ &myOutputParameters, wave_samplerate, framesPerBuffer, paNoFlag, // paClipOff | paDitherOff, pa_callback, (void *)userdata); if ((err!=paNoError) && (err!=paInvalidChannelCount)) //err==paUnanticipatedHostError { fprintf(stderr, "wave_open_sound > Pa_OpenStream : err=%d (%s)\n",err,Pa_GetErrorText(err)); framesPerBuffer = FRAMES_PER_BUFFER; err = Pa_OpenStream( &pa_stream, NULL, /* no input */ &myOutputParameters, wave_samplerate, framesPerBuffer, paNoFlag, // paClipOff | paDitherOff, pa_callback, (void *)userdata); } if(err == paInvalidChannelCount) { SHOW_TIME("wave_open_sound > try stereo"); // failed to open with mono, try stereo out_channels = 2; myOutputParameters.channelCount = out_channels; err = Pa_OpenStream( &pa_stream, NULL, /* no input */ &myOutputParameters, wave_samplerate, framesPerBuffer, paNoFlag, // paClipOff | paDitherOff, pa_callback, (void *)userdata); // err = Pa_OpenDefaultStream(&pa_stream,0,2,paInt16,(double)wave_samplerate,FRAMES_PER_BUFFER,pa_callback,(void *)userdata); } mInCallbackFinishedState = false; #endif } SHOW("wave_open_sound > %s\n","LEAVE"); return (err != paNoError); }
int main(void) { PortAudioStream *stream; PaError err; paTestData data; int i; int totalFrames; int numSamples; int numBytes; SAMPLE max, average, val; 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 ); if( data.recordedSamples == NULL ) { printf("Could not allocate record array.\n"); exit(1); } for( i=0; i<numSamples; i++ ) data.recordedSamples[i] = 0; err = Pa_Initialize(); if( err != paNoError ) goto error; /* Record some audio. -------------------------------------------- */ err = Pa_OpenStream( &stream, Pa_GetDefaultInputDeviceID(), NUM_CHANNELS, PA_SAMPLE_TYPE, NULL, paNoDevice, 0, PA_SAMPLE_TYPE, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, /* frames per buffer */ 0, /* number of buffers, if zero then use default minimum */ 0, /* paDitherOff, // flags */ recordCallback, &data ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Now recording!!\n"); fflush(stdout); while( Pa_StreamActive( stream ) ) { Pa_Sleep(1000); printf("index = %d\n", data.frameIndex ); fflush(stdout); } err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; /* Measure maximum peak amplitude. */ max = 0; average = 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 / numSamples; if( PA_SAMPLE_TYPE == paFloat32 ) /* This should be done at compile-time with "#if" ?? */ { /* MIPS-compiler warns at the int-version below. */ printf("sample max amplitude = %f\n", max ); printf("sample average = %f\n", average ); } else { printf("sample max amplitude = %d\n", max ); /* <-- This IS compiled anyhow. */ printf("sample average = %d\n", average ); } /* Write recorded data to a file. */ #if 0 { 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; printf("Begin playback.\n"); fflush(stdout); err = Pa_OpenStream( &stream, paNoDevice, 0, /* NO input */ PA_SAMPLE_TYPE, NULL, Pa_GetDefaultOutputDeviceID(), NUM_CHANNELS, PA_SAMPLE_TYPE, 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 */ playCallback, &data ); if( err != paNoError ) goto error; if( stream ) { err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Waiting for playback to finish.\n"); fflush(stdout); while( Pa_StreamActive( stream ) ) Pa_Sleep(100); err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; printf("Done.\n"); fflush(stdout); } free( data.recordedSamples ); Pa_Terminate(); 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 -1; }
int main(void) { PortAudioStream *stream; PaError err; paTestData DATA; int i; int totalSamps; 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; DATA.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */ err = Pa_Initialize(); if( err != paNoError ) goto error; err = Pa_OpenStream( &stream, paNoDevice,/* default input device */ 0, /* no input */ paFloat32, /* 32 bit floating point input */ NULL, Pa_GetDefaultOutputDeviceID(), /* default output device */ 2, /* stereo output */ 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.outTime = -1.0; // mark time for callback as undefined err = Pa_StartStream( stream ); if( err != paNoError ) goto error; /* Watch until sound is halfway finished. */ printf("Play for %d seconds.\n", NUM_SECONDS/2 ); fflush(stdout); do { ReportStreamTime( stream, &DATA ); Pa_Sleep(100); } while( Pa_StreamTime( stream ) < (totalSamps/2) ); /* Stop sound until ENTER hit. */ err = Pa_StopStream( stream ); if( err != paNoError ) goto error; printf("Pause for 2 seconds.\n"); fflush(stdout); Pa_Sleep( 2000 ); DATA.outTime = -1.0; // mark time for callback as undefined err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Play until sound is finished.\n"); fflush(stdout); do { ReportStreamTime( stream, &DATA ); Pa_Sleep(100); } while( Pa_StreamActive( stream ) ); 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; }
static int output_data(char *buf, int32 nbytes) { unsigned int i; int32 samplesToGo; char *bufepoint; if(pa_active == 0) return -1; while((pa_active==1) && (pa_data.samplesToGo > bytesPerInBuffer)){ Pa_Sleep(1);}; // if(pa_data.samplesToGo > DATA_BLOCK_SIZE){ // Sleep( (pa_data.samplesToGo - DATA_BLOCK_SIZE)/dpm.rate/4 ); // } samplesToGo=pa_data.samplesToGo; bufepoint=pa_data.bufepoint; if (pa_data.buf+bytesPerInBuffer*2 >= bufepoint + nbytes){ memcpy(bufepoint, buf, nbytes); bufepoint += nbytes; //buf += nbytes; }else{ int32 send = pa_data.buf+bytesPerInBuffer*2 - bufepoint; if (send != 0) memcpy(bufepoint, buf, send); buf += send; memcpy(pa_data.buf, buf, nbytes - send); bufepoint = pa_data.buf + nbytes - send; //buf += nbytes-send; } samplesToGo += nbytes; pa_data.samplesToGo=samplesToGo; pa_data.bufepoint=bufepoint; /* if(firsttime==1){ err = Pa_StartStream( stream ); if( err != paNoError ) goto error; firsttime=0; } */ #if PORTAUDIO_V19 if( 0==Pa_IsStreamActive(stream)){ #else if( 0==Pa_StreamActive(stream)){ #endif err = Pa_StartStream( stream ); if( err != paNoError ) goto error; } // if(ctl->id_character != 'r' && ctl->id_character != 'A' && ctl->id_character != 'W' && ctl->id_character != 'P') // while((pa_active==1) && (pa_data.samplesToGo > bytesPerInBuffer)){ Pa_Sleep(1);}; // Pa_Sleep( (pa_data.samplesToGo - bytesPerInBuffer)/dpm.rate * 1000); return 0; error: Pa_Terminate(); pa_active=0; ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "PortAudio error: %s\n", Pa_GetErrorText( err ) ); return -1; } static void close_output(void) { if( pa_active==0) return; #ifdef PORTAUDIO_V19 if(Pa_IsStreamActive(stream)){ #else if(Pa_StreamActive(stream)){ #endif Pa_Sleep( bytesPerInBuffer/dpm.rate*1000 ); } err = Pa_AbortStream( stream ); if( (err!=paStreamIsStopped) && (err!=paNoError) ) goto error; err = Pa_CloseStream( stream ); // if( err != paNoError ) goto error; Pa_Terminate(); pa_active=0; #ifdef AU_PORTAUDIO_DLL #ifndef PORTAUDIO_V19 free_portaudio_dll(); #endif #endif return; error: Pa_Terminate(); pa_active=0; #ifdef AU_PORTAUDIO_DLL #ifndef PORTAUDIO_V19 free_portaudio_dll(); #endif #endif ctl->cmsg( CMSG_ERROR, VERB_NORMAL, "PortAudio error: %s\n", Pa_GetErrorText( err ) ); return; } static int acntl(int request, void *arg) { switch(request) { case PM_REQ_GETQSIZ: *(int *)arg = bytesPerInBuffer*2; return 0; //break; case PM_REQ_GETFILLABLE: *(int *)arg = bytesPerInBuffer*2-pa_data.samplesToGo; return 0; //break; case PM_REQ_GETFILLED: *(int *)arg = pa_data.samplesToGo; return 0; //break; case PM_REQ_DISCARD: case PM_REQ_FLUSH: pa_data.samplesToGo=0; pa_data.bufpoint=pa_data.bufepoint; err = Pa_AbortStream( stream ); if( (err!=paStreamIsStopped) && (err!=paNoError) ) goto error; err = Pa_StartStream( stream ); if(err!=paNoError) goto error; return 0; //break; case PM_REQ_RATE: { int i; double sampleRateBack; i = *(int *)arg; //* sample rate in and out * close_output(); sampleRateBack=dpm.rate; dpm.rate=i; if(0==open_output()){ return 0; }else{ dpm.rate=sampleRateBack; open_output(); return -1; } } //break; // case PM_REQ_RATE: // return -1; case PM_REQ_PLAY_START: //* Called just before playing * case PM_REQ_PLAY_END: //* Called just after playing * return 0; default: return -1; } return -1; error: /* Pa_Terminate(); pa_active=0; #ifdef AU_PORTAUDIO_DLL free_portaudio_dll(); #endif */ ctl->cmsg( CMSG_ERROR, VERB_NORMAL, "PortAudio error in acntl : %s\n", Pa_GetErrorText( err ) ); return -1; } static void print_device_list(void){ PaDeviceIndex maxDeviceIndex, i; PaHostApiIndex HostApiIndex; const PaDeviceInfo* DeviceInfo; #if PORTAUDIO_V19 HostApiIndex=Pa_HostApiTypeIdToHostApiIndex(HostApiTypeId); #endif maxDeviceIndex=Pa_GetDeviceCount(); for( i = 0; i < maxDeviceIndex; i++){ DeviceInfo=Pa_GetDeviceInfo(i); #if PORTAUDIO_V19 if( DeviceInfo->hostApi == HostApiIndex){ #endif if( DeviceInfo->maxOutputChannels > 0){ ctl->cmsg( CMSG_ERROR, VERB_NORMAL, "%2d %s",i,DeviceInfo->name); } #if PORTAUDIO_V19 } #endif } }
static void *output_thread(void *ptr) { int err; int output_buffer_size; #ifndef PORTAUDIO_DEV int num_mixers, nbVolumes, volumeIdx; #endif struct timeval now; struct timespec timeout; slimaudio_t *audio = (slimaudio_t *) ptr; audio->output_STMs = false; audio->output_STMu = false; err = Pa_Initialize(); if (err != paNoError) { printf("PortAudio error4: %s Could not open any audio devices.\n", Pa_GetErrorText(err) ); exit(-1); } if ( audio->renice ) if ( slimproto_renice_thread (-5) ) /* Increase priority */ fprintf(stderr, "output_thread: renice failed. Got Root?\n"); #ifndef PORTAUDIO_DEV DEBUGF("output_thread: output_device_id : %i\n", audio->output_device_id ); DEBUGF("output_thread: pa_framesPerBuffer: %lu\n", pa_framesPerBuffer ); DEBUGF("output_thread: pa_numberOfBuffers: %lu\n", pa_numberOfBuffers ); err = Pa_OpenStream( &audio->pa_stream, /* stream */ paNoDevice, /* input device */ 0, /* input channels */ 0, /* input sample format */ NULL, /* input driver info */ audio->output_device_id,/* output device */ 2, /* output channels */ paInt16, /* output sample format */ NULL, /* output driver info */ 44100.0, /* sample rate */ pa_framesPerBuffer, /* frames per buffer */ pa_numberOfBuffers, /* number of buffers */ paNoFlag, /* stream flags */ pa_callback, /* callback */ audio); /* user data */ #else PaStreamParameters outputParameters; const PaDeviceInfo * paDeviceInfo; float newLatency; #ifdef PADEV_WASAPI PaWasapiStreamInfo streamInfo; const PaHostApiInfo *paHostApiInfo; #endif paDeviceInfo = Pa_GetDeviceInfo(audio->output_device_id); /* Device is not stereo or better, abort */ if (paDeviceInfo->maxOutputChannels < 2) { printf("output_thread: PortAudio device does not support 44.1KHz, 16-bit, stereo audio.\n"); printf("output_thread: Use -L for a list of supported audio devices, then use -o followed\n"); printf("output_thread: by the device number listed before the colon. See -h for details.\n"); exit(-2); } outputParameters.device = audio->output_device_id; #ifdef SLIMPROTO_ZONES outputParameters.channelCount = 2 * audio->output_num_zones; #else outputParameters.channelCount = 2; #endif outputParameters.sampleFormat = paInt16; outputParameters.suggestedLatency = paDeviceInfo->defaultHighOutputLatency; if ( audio->modify_latency ) { newLatency = (float) audio->user_latency / 1000.0; if ( ( newLatency > 1.0 ) || ( newLatency <= paDeviceInfo->defaultLowOutputLatency ) ) { fprintf (stderr, "User defined latency %f out of range %f-1.0, using default.\n", newLatency, paDeviceInfo->defaultLowOutputLatency ); newLatency = paDeviceInfo->defaultHighOutputLatency; } outputParameters.suggestedLatency = newLatency ; } #ifdef PADEV_WASAPI /* Use exclusive mode for WASAPI device, default is shared */ paHostApiInfo = Pa_GetHostApiInfo ( paDeviceInfo->hostApi ); if ( paHostApiInfo != NULL ) { if ( paHostApiInfo->type == paWASAPI ) { /* Use exclusive mode for WasApi device, default is shared */ if (wasapi_exclusive) { streamInfo.size = sizeof(PaWasapiStreamInfo); streamInfo.hostApiType = paWASAPI; streamInfo.version = 1; streamInfo.flags = paWinWasapiExclusive; outputParameters.hostApiSpecificStreamInfo = &streamInfo; DEBUGF("WASAPI: Exclusive\n"); } else { outputParameters.hostApiSpecificStreamInfo = NULL; DEBUGF("WASAPI: Shared\n"); } } } #else outputParameters.hostApiSpecificStreamInfo = NULL; #endif DEBUGF("paDeviceInfo->deviceid %d\n", outputParameters.device); DEBUGF("paDeviceInfo->maxOutputChannels %i\n", paDeviceInfo->maxOutputChannels); DEBUGF("outputParameters.suggestedLatency %f\n", outputParameters.suggestedLatency); DEBUGF("paDeviceInfo->defaultHighOutputLatency %f\n", (float) paDeviceInfo->defaultHighOutputLatency); DEBUGF("paDeviceInfo->defaultLowOutputLatency %f\n", (float) paDeviceInfo->defaultLowOutputLatency); DEBUGF("paDeviceInfo->defaultSampleRate %f\n", paDeviceInfo->defaultSampleRate); err = Pa_OpenStream ( &audio->pa_stream, /* stream */ NULL, /* inputParameters */ &outputParameters, /* outputParameters */ 44100.0, /* sample rate */ paFramesPerBufferUnspecified, /* framesPerBuffer */ paPrimeOutputBuffersUsingStreamCallback, /* streamFlags */ pa_callback, /* streamCallback */ audio); /* userData */ #endif #ifdef BSD_THREAD_LOCKING pthread_mutex_lock(&audio->output_mutex); #endif if (err != paNoError) { printf("output_thread: PortAudio error1: %s\n", Pa_GetErrorText(err) ); exit(-1); } #ifndef PORTAUDIO_DEV num_mixers = Px_GetNumMixers(audio->pa_stream); while (--num_mixers >= 0) { DEBUGF("Mixer: %s\n", Px_GetMixerName(audio->pa_stream, num_mixers)); } if (audio->volume_control == VOLUME_DRIVER) { DEBUGF("Opening mixer.\n" ); audio->px_mixer = Px_OpenMixer(audio->pa_stream, 0); } if (audio->px_mixer != NULL) { DEBUGF("Px_mixer = %p\n", audio->px_mixer); DEBUGF("PCM volume supported: %d.\n", Px_SupportsPCMOutputVolume(audio->px_mixer)); nbVolumes = Px_GetNumOutputVolumes(audio->px_mixer); DEBUGF("Nb volumes supported: %d.\n", nbVolumes); for (volumeIdx=0; volumeIdx<nbVolumes; ++volumeIdx) { DEBUGF("Volume %d: %s\n", volumeIdx, Px_GetOutputVolumeName(audio->px_mixer, volumeIdx)); } } #endif while (audio->output_state != QUIT) { switch (audio->output_state) { case STOPPED: audio->decode_num_tracks_started = 0L; audio->stream_samples = 0UL; audio->pa_streamtime_offset = audio->stream_samples; DEBUGF("output_thread STOPPED: %llu\n",audio->pa_streamtime_offset); slimaudio_buffer_set_readopt(audio->output_buffer, BUFFER_BLOCKING); case PAUSED: /* We report ourselves to the server every few seconds ** as a keep-alive. This is required for Squeezebox Server ** v6.5.x although technically, "stat" is not a valid event ** code for the STAT Client->Server message. This was ** lifted by observing how a Squeezebox3 reports itself to ** the server using Squeezebox Server's d_slimproto and ** d_slimproto_v tracing services. Note that Squeezebox3 ** seems to report every 1 second or so, but the server only ** drops the connection after 15-20 seconds of inactivity. */ DEBUGF("output_thread PAUSED: %llu\n",audio->pa_streamtime_offset); if (audio->keepalive_interval <= 0) { pthread_cond_wait(&audio->output_cond, &audio->output_mutex); } else { gettimeofday(&now, NULL); timeout.tv_sec = now.tv_sec + audio->keepalive_interval; timeout.tv_nsec = now.tv_usec * 1000; err = pthread_cond_timedwait(&audio->output_cond, &audio->output_mutex, &timeout); if (err == ETIMEDOUT) { DEBUGF("Sending keepalive. Interval=%ds.\n", audio->keepalive_interval); output_thread_stat(audio, "stat"); } } break; case PLAY: audio->output_predelay_frames = audio->output_predelay_msec * 44.100; DEBUGF("output_thread PLAY: output_predelay_frames: %i\n", audio->output_predelay_frames); output_buffer_size = slimaudio_buffer_available(audio->output_buffer); DEBUGF("output_thread BUFFERING: output_buffer_size: %i output_threshold: %i", output_buffer_size, audio->output_threshold); DEBUGF(" buffering_timeout: %i\n", audio->buffering_timeout); if ( (output_buffer_size < audio->output_threshold) && (audio->buffering_timeout > 0) ) { pthread_mutex_unlock(&audio->output_mutex); pthread_cond_broadcast(&audio->output_cond); Pa_Sleep(100); pthread_mutex_lock(&audio->output_mutex); audio->buffering_timeout--; } else { DEBUGF("output_thread PLAY: start stream: %llu\n", audio->pa_streamtime_offset); audio->buffering_timeout = BUFFERING_TIMEOUT; err = Pa_StartStream(audio->pa_stream); if (err != paNoError) { printf("output_thread: PortAudio error2: %s\n", Pa_GetErrorText(err)); exit(-1); } audio->output_state = PLAYING; pthread_cond_broadcast(&audio->output_cond); } break; case BUFFERING: DEBUGF("output_thread BUFFERING: %llu\n",audio->pa_streamtime_offset); case PLAYING: gettimeofday(&now, NULL); timeout.tv_sec = now.tv_sec + 1; timeout.tv_nsec = now.tv_usec * 1000; err = pthread_cond_timedwait(&audio->output_cond, &audio->output_mutex, &timeout); if (err == ETIMEDOUT) { DEBUGF("output_thread ETIMEDOUT-PLAYING: %llu\n",audio->pa_streamtime_offset); output_thread_stat(audio, "STMt"); } /* Track started */ if (audio->output_STMs) { audio->output_STMs = false; audio->decode_num_tracks_started++; audio->replay_gain = audio->start_replay_gain; slimaudio_output_vol_adjust(audio); audio->pa_streamtime_offset = audio->stream_samples; DEBUGF("output_thread STMs-PLAYING: %llu\n",audio->pa_streamtime_offset); output_thread_stat(audio, "STMs"); } /* Data underrun ** On buffer underrun causes the server to switch to the next track. */ if (audio->output_STMu) { audio->output_STMu = false; audio->output_state = STOP; DEBUGF("output_thread STMu-PLAYING: %llu\n",audio->pa_streamtime_offset); output_thread_stat(audio, "STMu"); pthread_cond_broadcast(&audio->output_cond); } break; case STOP: #ifndef PORTAUDIO_DEV if ( (err = Pa_StreamActive(audio->pa_stream) ) > 0) { err = Pa_StopStream(audio->pa_stream); if (err != paNoError) { printf("output_thread: PortAudio error3: %s\n", Pa_GetErrorText(err) ); exit(-1); } } else { if ( err != paNoError) { printf("output_thread: PortAudio error9: %s\n", Pa_GetErrorText(err) ); exit(-1); } } #else if ( (err = Pa_IsStreamActive(audio->pa_stream)) > 0) { err = Pa_StopStream(audio->pa_stream); if (err != paNoError) { printf("output_thread[STOP]: PortAudio error3: %s\n", Pa_GetErrorText(err) ); exit(-1); } } else if ( err != paNoError) { printf("output_thread[STOP ISACTIVE]: PortAudio error3: %s\n", Pa_GetErrorText(err) ); exit(-1); } #endif audio->output_state = STOPPED; DEBUGF("output_thread STOP: %llu\n",audio->pa_streamtime_offset); pthread_cond_broadcast(&audio->output_cond); break; case PAUSE: #ifndef PORTAUDIO_DEV if ( (err = Pa_StreamActive(audio->pa_stream) ) > 0) { err = Pa_StopStream(audio->pa_stream); if (err != paNoError) { printf("output_thread: PortAudio error10: %s\n", Pa_GetErrorText(err)); exit(-1); } } else { if ( err != paNoError) { printf("output_thread: PortAudio error11: %s\n", Pa_GetErrorText(err) ); exit(-1); } } #else if ( (err = Pa_IsStreamActive(audio->pa_stream)) > 0) { err = Pa_StopStream(audio->pa_stream); if (err != paNoError) { printf("output_thread[PAUSE]: PortAudio error3: %s\n", Pa_GetErrorText(err) ); exit(-1); } } else if ( err != paNoError) { printf("output_thread[PAUSE ISACTIVE]: PortAudio error3: %s\n", Pa_GetErrorText(err) ); exit(-1); } #endif audio->output_state = PAUSED; DEBUGF("output_thread PAUSE: %llu\n",audio->pa_streamtime_offset); pthread_cond_broadcast(&audio->output_cond); break; case QUIT: DEBUGF("output_thread QUIT: %llu\n",audio->pa_streamtime_offset); break; } } pthread_mutex_unlock(&audio->output_mutex); #ifndef PORTAUDIO_DEV if (audio->px_mixer != NULL) { Px_CloseMixer(audio->px_mixer); audio->px_mixer = NULL; } #endif err = Pa_CloseStream(audio->pa_stream); if (err != paNoError) { printf("output_thread[exit]: PortAudio error3: %s\n", Pa_GetErrorText(err) ); exit(-1); } audio->pa_stream = NULL; Pa_Terminate(); DEBUGF("output_thread: PortAudio terminated\n"); return 0; }
PaError TestRecording( paTestData *dataPtr ) { PortAudioStream *stream; PaError err; int i; /* Record some audio. */ err = Pa_OpenStream( &stream, Pa_GetDefaultInputDeviceID(), dataPtr->samplesPerFrame, /* stereo input */ PA_SAMPLE_TYPE, NULL, paNoDevice, 0, PA_SAMPLE_TYPE, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, /* frames per buffer */ NUM_REC_BUFS, /* number of buffers, if zero then use default minimum */ paClipOff, /* we won't output out of range samples so don't bother clipping them */ recordCallback, dataPtr ); if( err != paNoError ) goto error; err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Now recording!\n"); fflush(stdout); for( i=0; i<(NUM_SECONDS*1000/SLEEP_DUR_MSEC); i++ ) { if( Pa_StreamActive( stream ) <= 0) { printf("Stream inactive!\n"); break; } if( dataPtr->maxFrameIndex <= dataPtr->frameIndex ) { printf("Buffer recording complete.\n"); break; } Pa_Sleep(100); printf("index = %d\n", dataPtr->frameIndex ); fflush(stdout); } printf("Finished loop. Close stream.\n"); fflush(stdout); err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; printf("Done.\n"); fflush(stdout); { SAMPLE max = 0; SAMPLE posVal; int i; for( i=0; i<dataPtr->numSamples; i++ ) { posVal = dataPtr->recordedSamples[i]; if( posVal < 0 ) posVal = -posVal; if( posVal > max ) max = posVal; } printf("Largest recorded sample = %d\n", max ); } /* Write recorded data to a file. */ #if 0 { FILE *fid; fid = fopen("recorded.raw", "wb"); if( fid == NULL ) { printf("Could not open file."); } else { fwrite( dataPtr->recordedSamples, dataPtr->samplesPerFrame * sizeof(SAMPLE), totalFrames, fid ); fclose( fid ); printf("Wrote data to 'recorded.raw'\n"); } } #endif error: return err; }
PaError TestRecording( paTestData *dataPtr ) { PaError err; int i; int lastIndex = 0; /* Open input stream if not already open. */ if( dataPtr->inputStream == NULL ) { /* Record some audio. */ err = Pa_OpenStream( &dataPtr->inputStream, Pa_GetDefaultInputDeviceID(), dataPtr->samplesPerFrame, /* stereo input */ PA_SAMPLE_TYPE, NULL, paNoDevice, 0, PA_SAMPLE_TYPE, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, /* frames per buffer */ NUM_REC_BUFS, /* number of buffers, if zero then use default minimum */ paClipOff, /* we won't output out of range samples so don't bother clipping them */ recordCallback, dataPtr ); if( err != paNoError ) goto error; } dataPtr->frameIndex = 0; err = Pa_StartStream( dataPtr->inputStream ); if( err != paNoError ) goto error; printf("Now recording!\n"); fflush(stdout); for( i=0; i<(NUM_SECONDS*1000/SLEEP_DUR_MSEC); i++ ) { int frameIndex, delta; Pa_Sleep(SLEEP_DUR_MSEC); frameIndex = dataPtr->frameIndex; if( Pa_StreamActive( dataPtr->inputStream ) <= 0) { printf("Stream inactive!\n"); break; } if( dataPtr->maxFrameIndex <= frameIndex ) { printf("Buffer recording complete.\n"); break; } delta = frameIndex - lastIndex; lastIndex = frameIndex; printf("index = %d, delta = %d\n", frameIndex, delta ); fflush(stdout); } err = Pa_StopStream( dataPtr->inputStream ); if( err != paNoError ) goto error; printf("Done.\n"); fflush(stdout); error: return err; }
static int wave_open_sound() { PaError err = paNoError; PaError active; #if USE_PORTAUDIO == 18 active = Pa_StreamActive(pa_stream); #else active = Pa_IsStreamActive(pa_stream); #endif if (active == 1) return 0; if (active < 0) { out_channels = 1; #if USE_PORTAUDIO == 18 err = Pa_OpenStream(&pa_stream, // capture parameters paNoDevice, 0, paInt16, NULL, // playback parameters myOutputDevice, out_channels, paInt16, NULL, // general parameters wave_samplerate, FRAMES_PER_BUFFER, 0, paNoFlag, pa_callback, (void *)userdata); if (err == paInvalidChannelCount) { // failed to open with mono, try stereo out_channels = 2; err = Pa_OpenStream(&pa_stream, // capture parameters paNoDevice, 0, paInt16, NULL, // playback parameters myOutputDevice, out_channels, paInt16, NULL, // general parameters wave_samplerate, FRAMES_PER_BUFFER, 0, paNoFlag, pa_callback, (void *)userdata); } mInCallbackFinishedState = false; // v18 only #else myOutputParameters.channelCount = out_channels; unsigned long framesPerBuffer = paFramesPerBufferUnspecified; err = Pa_OpenStream(&pa_stream, NULL, // no input &myOutputParameters, wave_samplerate, framesPerBuffer, paNoFlag, pa_callback, (void *)userdata); if ((err != paNoError) && (err != paInvalidChannelCount)) { fprintf(stderr, "wave_open_sound > Pa_OpenStream : err=%d (%s)\n", err, Pa_GetErrorText(err)); framesPerBuffer = FRAMES_PER_BUFFER; err = Pa_OpenStream(&pa_stream, NULL, // no input &myOutputParameters, wave_samplerate, framesPerBuffer, paNoFlag, pa_callback, (void *)userdata); } if (err == paInvalidChannelCount) { // failed to open with mono, try stereo out_channels = 2; myOutputParameters.channelCount = out_channels; err = Pa_OpenStream(&pa_stream, NULL, // no input &myOutputParameters, wave_samplerate, framesPerBuffer, paNoFlag, pa_callback, (void *)userdata); } mInCallbackFinishedState = false; #endif } return err != paNoError; }
int main(void) { PortAudioStream *stream; PaError err; paTestData data; int i; int totalSamps; #if TEST_UNSIGNED printf("PortAudio Test: output UNsigned 8 bit sine wave.\n"); #else printf("PortAudio Test: output signed 8 bit sine wave.\n"); #endif /* initialise sinusoidal wavetable */ for( i=0; i<TABLE_SIZE; i++ ) { data.sine[i] = (char) (127.0 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. )); #if TEST_UNSIGNED data.sine[i] += (unsigned char) 0x80; #endif } data.left_phase = data.right_phase = 0; data.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */ err = Pa_Initialize(); if( err != paNoError ) goto error; err = Pa_OpenStream( &stream, paNoDevice,/* default input device */ 0, /* no input */ TEST_FORMAT, NULL, Pa_GetDefaultOutputDeviceID(), /* default output device */ 2, /* stereo output */ TEST_FORMAT, NULL, SAMPLE_RATE, 256, /* 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; /* Watch until sound is halfway finished. */ while( Pa_StreamTime( stream ) < (totalSamps/2) ) Pa_Sleep(10); /* Stop sound until ENTER hit. */ err = Pa_StopStream( stream ); if( err != paNoError ) goto error; printf("Pause for 2 seconds.\n"); Pa_Sleep( 2000 ); err = Pa_StartStream( stream ); if( err != paNoError ) goto error; printf("Waiting for sound to finish.\n"); while( Pa_StreamActive( stream ) ) Pa_Sleep(10); 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; }