From ee76af899f7f27f4784d3bbae27f2c63f0f1e6ce Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Mon, 6 Jan 2014 16:53:30 -0800 Subject: [PATCH] Updates to OS-X sample rate querying, other small changes suggested by Martin Koegler. --- RtAudio.cpp | 54 +++++++++++++++++++++++++++++----------- RtAudio.h | 8 +++--- doc/doxygen/tutorial.txt | 4 +++ 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/RtAudio.cpp b/RtAudio.cpp index f9259df..0a7d9eb 100644 --- a/RtAudio.cpp +++ b/RtAudio.cpp @@ -75,6 +75,11 @@ const unsigned int RtApi::SAMPLE_RATES[] = { // // *************************************************** // +std::string RtAudio :: getVersion( void ) throw() +{ + return std::string( RTAUDIO_VERSION ); +} + void RtAudio :: getCompiledApi( std::vector &apis ) throw() { apis.clear(); @@ -176,7 +181,8 @@ RtAudio :: RtAudio( RtAudio::Api api ) throw() // definition __RTAUDIO_DUMMY__ is automatically defined if no // API-specific definitions are passed to the compiler. But just in // case something weird happens, we'll print out an error message. - std::cerr << "\nRtAudio: no compiled API support found ... critical error!!\n\n"; + std::string errorText = "\nRtAudio: no compiled API support found ... critical error!!\n\n"; + throw( RtAudioError( errorText, RtAudioError::UNSPECIFIED ) ); } RtAudio :: ~RtAudio() throw() @@ -213,7 +219,7 @@ RtApi :: RtApi() stream_.userBuffer[1] = 0; MUTEX_INITIALIZE( &stream_.mutex ); showWarnings_ = true; - firstErrorOccurred = false; + firstErrorOccurred_ = false; } RtApi :: ~RtApi() @@ -718,18 +724,37 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device ) return info; } - Float64 minimumRate = 100000000.0, maximumRate = 0.0; + // The sample rate reporting mechanism is a bit of a mystery. It + // seems that it can either return individual rates or a range of + // rates. I assume that if the min / max range values are the same, + // then that represents a single supported rate and if the min / max + // range values are different, the device supports an arbitrary + // range of values (though there might be multiple ranges, so we'll + // use the most conservative range). + Float64 minimumRate = 1.0, maximumRate = 10000000000.0; + bool haveValueRange = false; + info.sampleRates.clear(); for ( UInt32 i=0; i maximumRate ) maximumRate = rangeList[i].mMaximum; + if ( rangeList[i].mMinimum == rangeList[i].mMaximum ) + info.sampleRates.push_back( (unsigned int) rangeList[i].mMinimum ); + else { + haveValueRange = true; + if ( rangeList[i].mMinimum > minimumRate ) minimumRate = rangeList[i].mMinimum; + if ( rangeList[i].mMaximum < maximumRate ) maximumRate = rangeList[i].mMaximum; + } } - info.sampleRates.clear(); - for ( unsigned int k=0; k= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate ) - info.sampleRates.push_back( SAMPLE_RATES[k] ); + if ( haveValueRange ) { + for ( unsigned int k=0; k= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate ) + info.sampleRates.push_back( SAMPLE_RATES[k] ); + } } + // Sort and remove any redundant values + std::sort( info.sampleRates.begin(), info.sampleRates.end() ); + info.sampleRates.erase( unique( info.sampleRates.begin(), info.sampleRates.end() ), info.sampleRates.end() ); + if ( info.sampleRates.size() == 0 ) { errorStream_ << "RtApiCore::probeDeviceInfo: No supported sample rates found for device (" << device << ")."; errorText_ = errorStream_.str(); @@ -791,7 +816,6 @@ static OSStatus rateListener( AudioObjectID inDevice, const AudioObjectPropertyAddress /*properties*/[], void* ratePointer ) { - Float64 *rate = (Float64 *) ratePointer; UInt32 dataSize = sizeof( Float64 ); AudioObjectPropertyAddress property = { kAudioDevicePropertyNominalSampleRate, @@ -863,6 +887,7 @@ bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList ); if (result != noErr || dataSize == 0) { + free( bufferList ); errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration for device (" << device << ")."; errorText_ = errorStream_.str(); return FAILURE; @@ -1003,7 +1028,6 @@ bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne dataSize = sizeof( Float64 ); property.mSelector = kAudioDevicePropertyNominalSampleRate; result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &nominalRate ); - if ( result != noErr ) { errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting current sample rate."; errorText_ = errorStream_.str(); @@ -1025,8 +1049,8 @@ bool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne nominalRate = (Float64) sampleRate; result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &nominalRate ); - if ( result != noErr ) { + AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate ); errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate for device (" << device << ")."; errorText_ = errorStream_.str(); return FAILURE; @@ -7846,10 +7870,10 @@ void RtApi :: error( RtAudioError::Type type ) if ( errorCallback ) { // abortStream() can generate new error messages. Ignore them. Just keep original one. - if ( firstErrorOccurred ) + if ( firstErrorOccurred_ ) return; - firstErrorOccurred = true; + firstErrorOccurred_ = true; const std::string errorMessage = errorText_; if ( type != RtAudioError::WARNING && stream_.state != STREAM_STOPPED) { @@ -7858,7 +7882,7 @@ void RtApi :: error( RtAudioError::Type type ) } errorCallback( type, errorMessage ); - firstErrorOccurred = false; + firstErrorOccurred_ = false; return; } diff --git a/RtAudio.h b/RtAudio.h index d1fbd65..f8285c0 100644 --- a/RtAudio.h +++ b/RtAudio.h @@ -45,13 +45,13 @@ #ifndef __RTAUDIO_H #define __RTAUDIO_H +#define RTAUDIO_VERSION "4.1.0pre" + #include #include #include #include -// RtAudio version: 4.1.0pre - /*! \typedef typedef unsigned long RtAudioFormat; \brief RtAudio data format type. @@ -373,7 +373,7 @@ class RtAudio }; //! A static function to determine the current RtAudio version. - static std::string getVersion( void ) { return "4.1.0"; } + static std::string getVersion( void ) throw(); //! A static function to determine the available compiled audio APIs. /*! @@ -760,7 +760,7 @@ protected: std::string errorText_; bool showWarnings_; RtApiStream stream_; - bool firstErrorOccurred; + bool firstErrorOccurred_; /*! Protected, api-specific method that attempts to open a device diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index da05da6..41f3bc0 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -17,6 +17,10 @@ RtAudio incorporates the concept of audio streams, which represent audio output \section whatsnew Latest Updates (Version 4.1.0) +A minor API change was made. The RtError class was renamed RtAudioError and embedded directly in RtAudio.h. Thus, all references to RtError should be renamed to RtAudioError and the RtError.h file should be deleted. + +Changes in the previous 4.0.12 release included: + - new functionality to allow error reporting via a client-supplied function (thanks to Pavel Mogilevskiy) - new function to return the version number - updated RtAudio.cpp and ASIO files for UNICODE support (thanks to Renaud Schoonbroodt) -- 2.30.2