> On May 14, 2020, at 3:21 PM, Dale Curtis via Coreaudio-api 
> <coreaudio-api@lists.apple.com> wrote:
> 
> Can someone from the CoreAudio team clarify when it's safe to call 
> AudioUnitSetProperty() on kAudioDevicePropertyBufferFrameSize? Specifically 
> we have these questions:
> - Is this just an unexpected bug and this should be safe to call at any time?
> - Should we first call AudioOutputUnitStop() on all units for the target 
> device that have kAudioOutputUnitProperty_IsRunning == true?
> - Should we instead call 
> AudioUnitUninitialize()+AudioComponentInstanceDispose() to destroy the units 
> before changing buffer sizes?

TL;DR;  It is almost never safe to change the IO context properties whenever 
any IO context is running.

Why?

Most software components rely on property listeners to discovery when device 
properties change. They then update their various buffers and what not 
(channels, frame counts, sample rates, etc) for the new values. Unfortunately, 
CoreAudio has never guaranteed any sort of tight coupling between setting a 
value and when it gets updated. This has always been a major pain point, but is 
made much worse when running IO contexts are involved.

Example A: You set a new sample rate on a device, get a successful result, then 
immediately query the device for its current sample rate... and get the 
previous sample rate (sometimes for many dozens of ms). Why? Because setting 
the sample rate is an RPC call that goes straight through to coreaudiod. 
Getting the sample rate returns a cached property in the local process. The 
cached properties don’t get updated until a distributed notification is 
received and CoreAudio in the local process refreshes it’s cache. CoreAudio has 
never provided any sort of synchronization to prevent this from happening.

Ironically, because you can’t trust reading a device property to return the 
correct value, you have to use property listeners to actually trigger updates 
to their values in your app… which means you have to use property listeners and 
treat everything as loosely coupled and asynchronously updated. Very few 
programmers do this, or even understand why it’s necessary, which is why a lot 
of audio using applications frequently have strange and random behaviors.

Example B: You have an active IO context and you change the device’s buffer 
frame size. Almost immediately, some code descending from an IOProc callback 
crashes (ie, per this email). Why? Because CoreAudio only does half the work to 
synchronize changes to an active IO context. Once a change is made, CoreAudio 
will correctly keep the IO context properties unchanged until it has notified 
the client of the change via a property listener. It will also defer calling 
property listeners until after any outstanding IOProc callbacks have returned. 
That’s the first half, and it gets that part right.

Unfortunately, once the property listener has fired (been dispatched?**) 
CoreAudio does not wait for the callout to return before it updates the IO 
context properties and resumes calling IOProc callbacks. Whether or not your 
property listener has actually run before the next IOProc callback is entirely 
dependent on the whims of the scheduler and whatever else is running on your 
machine. The more things running, the worse your chances.

This effectively means that anytime you change a device property with an active 
IO context, you can get an IOProc callback for an IO context with completely 
different properties _before_ you get notified that those properties have 
changed (and/or had a chance to fully deal with the changes). And given Example 
A, you can’t even trust an property poll from the IOProc itself to see if they 
are current.

-Ed

** This might only be a problem with the block/queue based APIs. The older 
function based property notifiers might get it right, I’m not entirely sure as 
I haven’t exhaustively checked… but I’d assume not until proven otherwise.

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list      (Coreaudio-api@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/coreaudio-api/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to