diff --git a/src/hostapi/coreaudio/pa_mac_core.c b/src/hostapi/coreaudio/pa_mac_core.c index b182dac..55ce9f0 100644 --- a/src/hostapi/coreaudio/pa_mac_core.c +++ b/src/hostapi/coreaudio/pa_mac_core.c @@ -990,18 +990,19 @@ static void UpdateTimeStampOffsets( PaMacCoreStream *stream ) } /* ================================================================================= */ -/* Query sample rate property. */ -static OSStatus UpdateSampleRateFromDeviceProperty( PaMacCoreStream *stream, AudioDeviceID deviceID, Boolean isInput ) + +/* can be used to update from nominal or actual sample rate */ +static OSStatus UpdateSampleRateFromDeviceProperty( PaMacCoreStream *stream, AudioDeviceID deviceID, Boolean isInput, AudioDevicePropertyID sampleRatePropertyID ) { PaMacCoreDeviceProperties * deviceProperties = isInput ? &stream->inputProperties : &stream->outputProperties; - /* FIXME: not sure if this should be the sample rate of the output device or the output unit */ - Float64 actualSampleRate = deviceProperties->sampleRate; + + Float64 sampleRate = 0.0; UInt32 propSize = sizeof(Float64); - OSStatus osErr = AudioDeviceGetProperty( deviceID, 0, isInput, kAudioDevicePropertyActualSampleRate, &propSize, &actualSampleRate); - if( (osErr == noErr) && (actualSampleRate > 1000.0) ) // avoid divide by zero if there's an error + OSStatus osErr = AudioDeviceGetProperty( deviceID, 0, isInput, sampleRatePropertyID, &propSize, &sampleRate); + if( (osErr == noErr) && (sampleRate > 1000.0) ) /* avoid divide by zero if there's an error */ { - deviceProperties->sampleRate = actualSampleRate; - deviceProperties->samplePeriod = 1.0 / actualSampleRate; + deviceProperties->sampleRate = sampleRate; + deviceProperties->samplePeriod = 1.0 / sampleRate; } return osErr; } @@ -1013,7 +1014,7 @@ static OSStatus AudioDevicePropertyActualSampleRateListenerProc( AudioDeviceID i // Make sure the callback is operating on a stream that is still valid! assert( stream->streamRepresentation.magic == PA_STREAM_MAGIC ); - OSStatus osErr = UpdateSampleRateFromDeviceProperty( stream, inDevice, isInput ); + OSStatus osErr = UpdateSampleRateFromDeviceProperty( stream, inDevice, isInput, kAudioDevicePropertyActualSampleRate ); if( osErr == noErr ) { UpdateTimeStampOffsets( stream ); @@ -1077,9 +1078,6 @@ static OSStatus SetupDevicePropertyListeners( PaMacCoreStream *stream, AudioDevi OSStatus osErr = noErr; PaMacCoreDeviceProperties *deviceProperties = isInput ? &stream->inputProperties : &stream->outputProperties; - // Start with the current values for the device properties. - UpdateSampleRateFromDeviceProperty( stream, deviceID, isInput ); - if( (osErr = QueryUInt32DeviceProperty( deviceID, isInput, kAudioDevicePropertyLatency, &deviceProperties->deviceLatency )) != noErr ) return osErr; if( (osErr = QueryUInt32DeviceProperty( deviceID, isInput, @@ -1993,53 +1991,48 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, stream->streamRepresentation.streamInfo.sampleRate = sampleRate; - stream->sampleRate = sampleRate; - stream->outDeviceSampleRate = 0; - if( stream->outputUnit ) { - Float64 rate; - UInt32 size = sizeof( rate ); - result = ERR( AudioDeviceGetProperty( stream->outputDevice, - 0, - FALSE, - kAudioDevicePropertyNominalSampleRate, - &size, &rate ) ); - if( result ) - goto error; - stream->outDeviceSampleRate = rate; - } - stream->inDeviceSampleRate = 0; - if( stream->inputUnit ) { - Float64 rate; - UInt32 size = sizeof( rate ); - result = ERR( AudioDeviceGetProperty( stream->inputDevice, - 0, - TRUE, - kAudioDevicePropertyNominalSampleRate, - &size, &rate ) ); - if( result ) - goto error; - stream->inDeviceSampleRate = rate; - } + stream->sampleRate = sampleRate; + stream->userInChan = inputChannelCount; stream->userOutChan = outputChannelCount; // Setup property listeners for timestamp and latency calculations. pthread_mutex_init( &stream->timingInformationMutex, NULL ); stream->timingInformationMutexIsInitialized = 1; - InitializeDeviceProperties( &stream->inputProperties ); - InitializeDeviceProperties( &stream->outputProperties ); + InitializeDeviceProperties( &stream->inputProperties ); // zeros the struct. doesn't actually init it to useful values + InitializeDeviceProperties( &stream->outputProperties ); // zeros the struct. doesn't actually init it to useful values if( stream->outputUnit ) { Boolean isInput = FALSE; + + // Start with the current values for the device properties. + // Init with nominal sample rate. Use actual sample rate where available + + result = ERR( UpdateSampleRateFromDeviceProperty( + stream, stream->outputDevice, isInput, kAudioDevicePropertyNominalSampleRate ) ); + if( result ) + goto error; /* fail if we can't even get a nominal device sample rate */ + + UpdateSampleRateFromDeviceProperty( stream, stream->outputDevice, isInput, kAudioDevicePropertyActualSampleRate ); + SetupDevicePropertyListeners( stream, stream->outputDevice, isInput ); } if( stream->inputUnit ) { Boolean isInput = TRUE; + + // as above + result = ERR( UpdateSampleRateFromDeviceProperty( + stream, stream->inputDevice, isInput, kAudioDevicePropertyNominalSampleRate ) ); + if( result ) + goto error; + + UpdateSampleRateFromDeviceProperty( stream, stream->inputDevice, isInput, kAudioDevicePropertyActualSampleRate ); + SetupDevicePropertyListeners( stream, stream->inputDevice, isInput ); } UpdateTimeStampOffsets( stream ); - // Setup copies to be used by audio callback. + // Setup timestamp copies to be used by audio callback. stream->timestampOffsetCombined_ioProcCopy = stream->timestampOffsetCombined; stream->timestampOffsetInputDevice_ioProcCopy = stream->timestampOffsetInputDevice; stream->timestampOffsetOutputDevice_ioProcCopy = stream->timestampOffsetOutputDevice; diff --git a/src/hostapi/coreaudio/pa_mac_core_internal.h b/src/hostapi/coreaudio/pa_mac_core_internal.h index 462240b..14e3d07 100644 --- a/src/hostapi/coreaudio/pa_mac_core_internal.h +++ b/src/hostapi/coreaudio/pa_mac_core_internal.h @@ -120,7 +120,11 @@ typedef struct PaMacCoreDeviceProperties UInt32 bufferFrameSize; // UInt32 streamLatency; // Seems to be the same as deviceLatency!? UInt32 deviceLatency; - /* Current device sample rate. May change! */ + /* Current device sample rate. May change! + These are initialized to the nominal device sample rate, + and updated with the actual sample rate, when/where available. + Note that these are the *device* sample rates, prior to any required + SR conversion. */ Float64 sampleRate; Float64 samplePeriod; // reciprocal } @@ -166,10 +170,6 @@ typedef struct PaMacCoreStream ACTIVE = 3 /* The stream is active and running. */ } state; double sampleRate; - //these may be different from the stream sample rate due to SR conversion: - double outDeviceSampleRate; - double inDeviceSampleRate; - PaMacCoreDeviceProperties inputProperties; PaMacCoreDeviceProperties outputProperties;