From ee76af899f7f27f4784d3bbae27f2c63f0f1e6ce Mon Sep 17 00:00:00 2001 From: Gary Scavone Date: Mon, 6 Jan 2014 16:53:30 -0800 Subject: Updates to OS-X sample rate querying, other small changes suggested by Martin Koegler. --- RtAudio.cpp | 54 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'RtAudio.cpp') 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; } -- cgit v1.2.3