Memory management for real-time audio components

Dear all,


I have a pretty fundamental question about real-time audio, but I cannot find a proper answer. The context is low-level audio programming on mobile platforms, that is the programming my own audio modules with their own C/C++ audio render functions.


Consider the following case:


My audio graph (the API it is implemented in doesn’t matter really) contains several independent modules, whose render functions are called and audio outputs are mixed together at each audio render loop call.


At some point, for some reason (there can be plenty, but let’s say the order comes from outside the audio thread, which is generally the case), I need to free and reallocate the resources of one of the modules (some of these resources are accessed inside the render function), without disturbing the other modules.

  • If the audio render loop is running precisely at the moment I receive the order to reallocate resources, I have to wait for the render function to finish to avoid freeing memory that it currently being read or written.
  • I have to prevent the render function of this particular module, but not those of the other modules, from running while I’m doing memory free/alloc.
  • As it is always the case within the audio thread, I shall not use any lock, or free/alloc inside the audio render function.
  • I cannot stop the audio render loop, because the other modules are potentially running and producing audio output.


My question is then:


How can I SAFELY and PROPERLY free and reallocate some resources used inside the audio thread, without disturbing the audio render loop?



Thank you all for your input 🙂


Tom

Replies

Memory should not be allocated (or set free) inside the audio thread, and the audio thread should not touch these resources while they are being modified in another thread (or by another processor). To do this without blocking seems to require some sort of lock free atomic signal. I think this is possible on ARM processors (which can reorder memory writes) using memory barrier instrinsics or OS calls from a language (ASM or C ?) that does not reorder around said memory barrier(s). Assuming this is correct, the following might work:


Use a flag (an atomic word) to tell the real-time context whether it can use memory resources or not, and execute a memory barrier. If a running audio unit is told not to use memory, it can instead discard any buffer inputs, and output silence (or some other error conceilment data) in place of audio processing. After the memory barrier (and perhaps waiting one or four audio callback intervals), your app can safely allocate, free, modify, etc., any memory completely outside of the audio context. After another memory barrier, you can reset the atomic flag to allow the audio unit to proceed as usual.


I've been using a similar sequence to pass data to/from running audio units using lock-free circular FIFOs. Hopefully, this is correct. If not, Apple should provide some example code.

Hello hotpaw2,


Thank you for your answer.

That was exactly the kind of thing I had in mind.


As I'm working on crossplatform code (iOS/Android essentially) at this level, I think i'll try to do something universal and language-based, maybe with C++ std::atomic. I need to spend some time studying on atomicity and memory barrier at first though... 😉


I'll let you know as soon as I have something that seems interesting.


Also obviously interesting in some feedback from Apple about this tricky question!