问题
I am building an audio app based on the AudioUnit callback facility and a graph of audio processing nodes. I know that the callback is executed in a separate (high priority?) thread and therefore all interaction with my processing nodes, such as e.g. changing EQ parameters while playing, should be done in a thread safe manner. In other words, the nodes should be protected from modification while the audio callback chain is being executed.
The way I understand it in terms of more low-level multithreading is that, I need a lock either in each node or a single one for the entire graph, that prevents writes while audio buffers are being processed.
However, I would like the implementation to be more "Swifty" and use DispatchQueue
/DispatchGroup
which should provide the said functionality. I just can't quite understand how to do it in the most efficient manner.
So let's say all audio parameter modifications are done on a queue, like so:
audioQueue.async {
eqNode.setEqParameters(...)
}
How do I ensure this block is not executed until the AudioUnit callback completes? Using audioQueue.sync
is not an option because it means the system audio thread will depend on my audioQueue
, this is not great.
If I were to use DispatchGroup
what would be the best way to implement the said flow?
回答1:
A real-time Audio Unit callback should never lock, wait on locks, or manage memory (Swift or Objective C objects or methods).
I would double buffer the set of audio parameters (or more, e.g. a ring buffer of parameter sets). Have the writer lock the set that is being changed, unlock when done, and never switch sets at or faster than the known audio callback rate (2X+ slower would be safe). Have the periodic reader (Audio Unit real-time callback) check the locks and not use the set of parameters that is locked.
In order to not use locks on inter-thread ring buffers, you might want to use OS atomic memory barriers on the pointer, index, or status load/stores: load_acquire, store_release, etc., to prevent ARM processor write buffer reordering, or Swift optimizer instruction reordering, from corrupting your data.
来源:https://stackoverflow.com/questions/58512485/audiounit-callback-and-synchronization-how-to-ensure-thread-safety-with-gcd