From ad768de27c78093a6000a4f00d1baeca8ca5ce37 Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Thu, 29 Jan 2009 19:00:08 +0000 Subject: [PATCH] Various updates and fixes before 4.0.5 release (GS). --- RtAudio.cpp | 62 ++++++++++++++++++++++++++++++++++----- doc/doxygen/compiling.txt | 2 +- doc/doxygen/duplex.txt | 2 ++ doc/doxygen/playback.txt | 1 + doc/doxygen/recording.txt | 2 ++ doc/doxygen/tutorial.txt | 2 +- doc/release.txt | 3 +- tests/duplex.cpp | 2 ++ tests/playraw.cpp | 2 ++ tests/playsaw.cpp | 1 + tests/record.cpp | 2 ++ tests/testall.cpp | 2 ++ 12 files changed, 72 insertions(+), 11 deletions(-) diff --git a/RtAudio.cpp b/RtAudio.cpp index f86ea12..b66734e 100644 --- a/RtAudio.cpp +++ b/RtAudio.cpp @@ -42,6 +42,9 @@ #include "RtAudio.h" #include +#include +#include +#include // Static variable definitions. const unsigned int RtApi::MAX_SAMPLE_RATES = 14; @@ -1731,9 +1734,15 @@ struct JackHandle { :client(0), drainCounter(0), internalDrain(false) { ports[0] = 0; ports[1] = 0; xrun[0] = false; xrun[1] = false; } }; +void jackSilentError( const char * ) {}; + RtApiJack :: RtApiJack() { // Nothing to do here. +#if !defined(__RTAUDIO_DEBUG__) + // Turn off Jack's internal error reporting. + jack_set_error_function( &jackSilentError ); +#endif } RtApiJack :: ~RtApiJack() @@ -2306,6 +2315,21 @@ void RtApiJack :: abortStream( void ) stopStream(); } +// This function will be called by a spawned thread when the user +// callback function signals that the stream should be stopped or +// aborted. It is necessary to handle it this way because the +// callbackEvent() function must return before the jack_deactivate() +// function will return. +extern "C" void *jackStopStream( void *ptr ) +{ + CallbackInfo *info = (CallbackInfo *) ptr; + RtApiJack *object = (RtApiJack *) info->object; + + object->stopStream(); + + pthread_exit( NULL ); +} + bool RtApiJack :: callbackEvent( unsigned long nframes ) { if ( stream_.state == STREAM_STOPPED ) return SUCCESS; @@ -2325,10 +2349,12 @@ bool RtApiJack :: callbackEvent( unsigned long nframes ) // Check if we were draining the stream and signal is finished. if ( handle->drainCounter > 3 ) { - if ( handle->internalDrain == false ) - pthread_cond_signal( &handle->condition ); + if ( handle->internalDrain == true ) { + ThreadHandle id; + pthread_create( &id, NULL, jackStopStream, info ); + } else - stopStream(); + pthread_cond_signal( &handle->condition ); return SUCCESS; } @@ -2357,7 +2383,8 @@ bool RtApiJack :: callbackEvent( unsigned long nframes ) stream_.bufferSize, streamTime, status, info->userData ); if ( handle->drainCounter == 2 ) { MUTEX_UNLOCK( &stream_.mutex ); - abortStream(); + ThreadHandle id; + pthread_create( &id, NULL, jackStopStream, info ); return SUCCESS; } else if ( handle->drainCounter == 1 ) @@ -3857,7 +3884,7 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned bufferBytes *= 2; // Set cooperative level to DSSCL_EXCLUSIVE ... sound stops when window focus changes. - //result = output->SetCooperativeLevel( hWnd, DSSCL_EXCLUSIVE ); + // result = output->SetCooperativeLevel( hWnd, DSSCL_EXCLUSIVE ); // Set cooperative level to DSSCL_PRIORITY ... sound remains when window focus changes. result = output->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ); if ( FAILED( result ) ) { @@ -4023,6 +4050,11 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned // Update wave format structure and buffer information. waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; + dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels; + + // If the user wants an even bigger buffer, increase the device buffer size accordingly. + while ( dsPointerLeadTime * 2U > (DWORD) bufferBytes ) + bufferBytes *= 2; // Setup the secondary DS buffer description. dsBufferSize = bufferBytes; @@ -4044,6 +4076,20 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned return FAILURE; } + // Get the buffer size ... might be different from what we specified. + DSCBCAPS dscbcaps; + dscbcaps.dwSize = sizeof( DSCBCAPS ); + result = buffer->GetCaps( &dscbcaps ); + if ( FAILED( result ) ) { + input->Release(); + buffer->Release(); + errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") getting buffer settings (" << dsinfo.name << ")!"; + errorText_ = errorStream_.str(); + return FAILURE; + } + + bufferBytes = dscbcaps.dwBufferBytes; + // Lock the capture buffer LPVOID audioPtr; DWORD dataLen; @@ -4483,7 +4529,7 @@ void RtApiDs :: callbackEvent() // The state might change while waiting on a mutex. if ( stream_.state == STREAM_STOPPED ) { MUTEX_UNLOCK( &stream_.mutex ); - return SUCCESS; + return; } // Invoke user callback to get fresh output data UNLESS we are @@ -4530,7 +4576,7 @@ void RtApiDs :: callbackEvent() long bufferBytes; if ( stream_.mode == DUPLEX && !buffersRolling ) { - assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] ); + //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] ); // It takes a while for the devices to get rolling. As a result, // there's no guarantee that the capture and write device pointers @@ -4581,7 +4627,7 @@ void RtApiDs :: callbackEvent() Sleep( 1 ); } - assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] ); + //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] ); buffersRolling = true; handle->bufferPointer[0] = ( safeWritePos + handle->dsPointerLeadTime[0] ); diff --git a/doc/doxygen/compiling.txt b/doc/doxygen/compiling.txt index d7b9a29..79cb314 100644 --- a/doc/doxygen/compiling.txt +++ b/doc/doxygen/compiling.txt @@ -2,7 +2,7 @@ \section debug Debugging -If you are having problems getting RtAudio to run on your system, make sure to pass a value of \e true to the RtAudio::showWarnings() function (this is the default setting). A variety of warning messages will be displayed which may help in determining the problem. Also, try using the programs included in the tests directory. The program audioprobe displays the queried capabilities of all hardware devices found for all APIs compiled. When using the ALSA API, further information can be displayed by defining the preprocessor definition __RTAUDIO_DEBUG__. +If you are having problems getting RtAudio to run on your system, make sure to pass a value of \e true to the RtAudio::showWarnings() function (this is the default setting). A variety of warning messages will be displayed which may help in determining the problem. Also, try using the programs included in the tests directory. The program audioprobe displays the queried capabilities of all hardware devices found for all APIs compiled. When using the ALSA and JACK APIs, further information can be displayed by defining the preprocessor definition __RTAUDIO_DEBUG__. \section compile Compiling diff --git a/doc/doxygen/duplex.txt b/doc/doxygen/duplex.txt index f060602..c76ae73 100644 --- a/doc/doxygen/duplex.txt +++ b/doc/doxygen/duplex.txt @@ -5,6 +5,8 @@ Finally, it is easy to use RtAudio for simultaneous audio input/output, or duple \code #include "RtAudio.h" #include +#include +#include // Pass-through function. int inout( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, diff --git a/doc/doxygen/playback.txt b/doc/doxygen/playback.txt index 4d5a793..c291f5a 100644 --- a/doc/doxygen/playback.txt +++ b/doc/doxygen/playback.txt @@ -5,6 +5,7 @@ In this example, we provide a complete program that demonstrates the use of RtAu \code #include "RtAudio.h" #include +#include // Two-channel sawtooth wave generator. int saw( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, diff --git a/doc/doxygen/recording.txt b/doc/doxygen/recording.txt index 6316a5c..9b62438 100644 --- a/doc/doxygen/recording.txt +++ b/doc/doxygen/recording.txt @@ -6,6 +6,8 @@ Using RtAudio for audio input is almost identical to the way it is used for play \code #include "RtAudio.h" #include +#include +#include int record( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void *userData ) diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index b42a945..02e3bcb 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -32,7 +32,7 @@ Devices are now re-enumerated every time the RtAudio::getDeviceCount(), RtAudio: \section download Download -Latest Release (?? January 2009): Version 4.0.5 +Latest Release (29 January 2009): Version 4.0.5 \section documentation Documentation Links diff --git a/doc/release.txt b/doc/release.txt index 70f82c7..42a3fa9 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -2,11 +2,12 @@ RtAudio - a set of C++ classes that provide a common API for realtime audio inpu By Gary P. Scavone, 2001-2009. -v4.0.5: (?? January 2009) +v4.0.5: (29 January 2009) - added support in CoreAudio for arbitrary stream channel configurations - added getStreamSampleRate() function because the actual sample rate can sometimes vary slightly from the specified one (thanks to Theo Veenker) - added new StreamOptions flag "RTAUDIO_SCHEDULE_REALTIME" and attribute "priority" to StreamOptions (thanks to Theo Veenker) - replaced usleep(50000) in callbackEvent() by a wait on condition variable which gets signaled in startStream() (thanks to Theo Veenker) +- fix for Jack API when user callback function signals stop or abort calls - fix to way stream state is changed to avoid infinite loop problem - fix to int<->float conversion in convertBuffer() (thanks to Theo Veenker) - bug fix in byteSwapBuffer() (thanks to Stefan Muller Arisona and Theo Veenker) diff --git a/tests/duplex.cpp b/tests/duplex.cpp index f416bad..125b56e 100644 --- a/tests/duplex.cpp +++ b/tests/duplex.cpp @@ -10,6 +10,8 @@ #include "RtAudio.h" #include +#include +#include /* typedef signed long MY_TYPE; diff --git a/tests/playraw.cpp b/tests/playraw.cpp index 13e8b49..1ab1600 100644 --- a/tests/playraw.cpp +++ b/tests/playraw.cpp @@ -11,6 +11,8 @@ #include "RtAudio.h" #include +#include +#include /* typedef char MY_TYPE; diff --git a/tests/playsaw.cpp b/tests/playsaw.cpp index d477297..019963b 100644 --- a/tests/playsaw.cpp +++ b/tests/playsaw.cpp @@ -10,6 +10,7 @@ #include "RtAudio.h" #include +#include /* typedef signed long MY_TYPE; diff --git a/tests/record.cpp b/tests/record.cpp index 22bcaac..a56f351 100644 --- a/tests/record.cpp +++ b/tests/record.cpp @@ -11,6 +11,8 @@ #include "RtAudio.h" #include +#include +#include /* typedef char MY_TYPE; diff --git a/tests/testall.cpp b/tests/testall.cpp index 1f3ea26..bd9ca74 100644 --- a/tests/testall.cpp +++ b/tests/testall.cpp @@ -10,6 +10,8 @@ #include "RtAudio.h" #include +#include +#include #define BASE_RATE 0.005 #define TIME 1.0 -- 2.30.2