From bd7eff070558e88195fa1acf4a3212dc6b23129f Mon Sep 17 00:00:00 2001 From: Anthony Nicholls Date: Thu, 13 Feb 2025 09:34:41 +0000 Subject: [PATCH] iOS: Fix an issue in which the reported sample rate may not always be correct --- .../native/juce_Audio_ios.cpp | 96 +++++++++---------- 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/modules/juce_audio_devices/native/juce_Audio_ios.cpp b/modules/juce_audio_devices/native/juce_Audio_ios.cpp index 288ecbec1f..7aad4e342b 100644 --- a/modules/juce_audio_devices/native/juce_Audio_ios.cpp +++ b/modules/juce_audio_devices/native/juce_Audio_ios.cpp @@ -481,66 +481,62 @@ struct iOSAudioIODevice::Pimpl final : public AsyncUpdater { auto session = [AVAudioSession sharedInstance]; - if (exactlyEqual (session.sampleRate, rate)) - return rate; - - const auto startingSampleRate = session.sampleRate; - setAudioSessionActive (false); JUCE_NSERROR_CHECK ([session setPreferredSampleRate: rate error: &error]); setAudioSessionActive (true); - if (! exactlyEqual (startingSampleRate, session.sampleRate)) - return session.sampleRate; - - AudioStreamBasicDescription stream{}; - stream.mFormatID = kAudioFormatLinearPCM; - stream.mSampleRate = rate; - stream.mChannelsPerFrame = 2; - stream.mBitsPerChannel = 32; - stream.mFramesPerPacket = 1; - stream.mBytesPerFrame = stream.mChannelsPerFrame * stream.mBitsPerChannel / 8; - stream.mBytesPerPacket = stream.mBytesPerFrame * stream.mFramesPerPacket; - stream.mFormatFlags = stream.mBitsPerChannel; - stream.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger - | kLinearPCMFormatFlagIsBigEndian - | kLinearPCMFormatFlagIsPacked; - - AudioQueueRef audioQueue; - - auto err = AudioQueueNewOutput (&stream, - [] (auto, auto, auto) {}, - nullptr, - nullptr, - kCFRunLoopCommonModes, - 0, - &audioQueue); - - if (err != noErr || audioQueue == nullptr) + if (@available (ios 18, *)) { + AudioStreamBasicDescription stream{}; + stream.mFormatID = kAudioFormatLinearPCM; + stream.mSampleRate = rate; + stream.mChannelsPerFrame = 2; + stream.mBitsPerChannel = 32; + stream.mFramesPerPacket = 1; + stream.mBytesPerFrame = stream.mChannelsPerFrame * stream.mBitsPerChannel / 8; + stream.mBytesPerPacket = stream.mBytesPerFrame * stream.mFramesPerPacket; + stream.mFormatFlags = stream.mBitsPerChannel; + stream.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger + | kLinearPCMFormatFlagIsBigEndian + | kLinearPCMFormatFlagIsPacked; + + AudioQueueRef audioQueue; + + auto err = AudioQueueNewOutput (&stream, + [] (auto, auto, auto) {}, + nullptr, + nullptr, + kCFRunLoopCommonModes, + 0, + &audioQueue); + + if (err != noErr || audioQueue == nullptr) + { + jassertfalse; + return session.sampleRate; + } + + const ScopeGuard disposeAudioQueueOnReturn { [&] + { + AudioQueueDispose (audioQueue, true); + }}; + + Float64 deviceSampleRate{}; + UInt32 size = sizeof (deviceSampleRate); + + err = AudioQueueGetProperty (audioQueue, + kAudioQueueDeviceProperty_SampleRate, + &deviceSampleRate, + &size); + + if (err == noErr && size == sizeof (deviceSampleRate)) + return deviceSampleRate; + jassertfalse; - return session.sampleRate; } - const ScopeGuard disposeAudioQueueOnReturn { [&] - { - AudioQueueDispose (audioQueue, true); - }}; - - Float64 deviceSampleRate{}; - UInt32 size = sizeof (deviceSampleRate); - - err = AudioQueueGetProperty (audioQueue, - kAudioQueueDeviceProperty_SampleRate, - &deviceSampleRate, - &size); - - if (err == noErr && size == sizeof (deviceSampleRate)) - return deviceSampleRate; - - jassertfalse; return session.sampleRate; }