From 898877e8b3586bae333793114c3f6f008cd71790 Mon Sep 17 00:00:00 2001 From: Sebastian Parborg Date: Fri, 2 May 2025 14:56:16 +0200 Subject: [PATCH] Audaspace: Workaround Core Audio clock quirk --- .../plugins/coreaudio/CoreAudioDevice.cpp | 27 +++++++++++++------ .../plugins/coreaudio/CoreAudioDevice.h | 2 ++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/extern/audaspace/plugins/coreaudio/CoreAudioDevice.cpp b/extern/audaspace/plugins/coreaudio/CoreAudioDevice.cpp index 9a2d04d581d..a03e4a84e77 100644 --- a/extern/audaspace/plugins/coreaudio/CoreAudioDevice.cpp +++ b/extern/audaspace/plugins/coreaudio/CoreAudioDevice.cpp @@ -46,6 +46,22 @@ OSStatus CoreAudioDevice::CoreAudio_mix(void* data, AudioUnitRenderActionFlags* device->notifyMixingThread(); } + if (!device->m_audio_clock_ready) { + // Workaround CoreAudio quirk that corrupts the clock time data when the first mix callback occurs. + // Both the start time and current time will be invalid. We need to reset them. + if(device->isSynchronizerPlaying()) + CAClockStop(device->m_clock_ref); + + CAClockTime clock_time; + clock_time.format = kCAClockTimeFormat_Seconds; + clock_time.time.seconds = device->m_synchronizerStartTime; + CAClockSetCurrentTime(device->m_clock_ref, &clock_time); + + if(device->isSynchronizerPlaying()) + CAClockStart(device->m_clock_ref); + device->m_audio_clock_ready = true; + } + return noErr; } @@ -62,7 +78,7 @@ void CoreAudioDevice::playing(bool playing) m_playback = playing; } -CoreAudioDevice::CoreAudioDevice(DeviceSpecs specs, int buffersize) : m_buffersize(uint32_t(buffersize)), m_playback(false), m_audio_unit(nullptr) +CoreAudioDevice::CoreAudioDevice(DeviceSpecs specs, int buffersize) : m_buffersize(uint32_t(buffersize)), m_playback(false), m_audio_unit(nullptr), m_audio_clock_ready(false) { if(specs.channels == CHANNELS_INVALID) specs.channels = CHANNELS_STEREO; @@ -208,12 +224,6 @@ CoreAudioDevice::CoreAudioDevice(DeviceSpecs specs, int buffersize) : m_buffersi throw; } - /* Workaround CoreAudio quirk that makes the Clock (m_clock_ref) be in an invalid state - * after we try to re-init the device. (It is fine the first time we init the device...) - * We have to do a start/stop toggle to get it into a valid state again. */ - AudioOutputUnitStart(m_audio_unit); - AudioOutputUnitStop(m_audio_unit); - create(); startMixingThread(buffersize * 2 * AUD_DEVICE_SAMPLE_SIZE(specs)); @@ -244,6 +254,7 @@ void CoreAudioDevice::seekSynchronizer(double time) clock_time.format = kCAClockTimeFormat_Seconds; clock_time.time.seconds = time; CAClockSetCurrentTime(m_clock_ref, &clock_time); + m_synchronizerStartTime = time; if(isSynchronizerPlaying()) CAClockStart(m_clock_ref); @@ -257,7 +268,7 @@ double CoreAudioDevice::getSynchronizerPosition() OSStatus status; - if(isSynchronizerPlaying()) + if(isSynchronizerPlaying() && m_audio_clock_ready) status = CAClockGetCurrentTime(m_clock_ref, kCAClockTimeFormat_Seconds, &clock_time); else status = CAClockGetStartTime(m_clock_ref, kCAClockTimeFormat_Seconds, &clock_time); diff --git a/extern/audaspace/plugins/coreaudio/CoreAudioDevice.h b/extern/audaspace/plugins/coreaudio/CoreAudioDevice.h index acdd84d25ee..79b617458dd 100644 --- a/extern/audaspace/plugins/coreaudio/CoreAudioDevice.h +++ b/extern/audaspace/plugins/coreaudio/CoreAudioDevice.h @@ -56,6 +56,8 @@ private: /// The CoreAudio clock referene. CAClockRef m_clock_ref; + bool m_audio_clock_ready; + double m_synchronizerStartTime{0}; /** * Mixes the next bytes into the buffer.