AUv3 AudioUnit Extension - how to pass data back from render loop to UI?

I'm working on an AUv3 AudioUnit effect extension and I understand the idea invoking a parametertree and observers to pass processing parameters to the render block. This is all working fine but now I'm facing the following problem: How to return processing data from the internalRenderLoop back to the ViewController?


For example think about the gain reduction data that is easy to calculate in the render loop and that should be passed to the ViewController to be visualised for the user?


So far I've tried three ways without success:


1) Using the parameter tree - the parameter tree seams to be a one-way communication as I couldn't find a way to write to the parametertree from the render loop. The observers also seems to produce much overhead when the data is changing fast!?


2) Polling the data from the viewController - I could not get a NSTimer to fire in the extensions ViewController? Used a scheduledTimer with GCD main queue but not get the timer to fire?


3) Adding a write back to the render cycle - could not write back data to ViewController without capturing self.


So I'm pretty much stuck and could find any sample code or forum discussion that would give me a hint. Therefore I would be glad if some one could point me to a direction how to pass data from the render loop to the viewController!


THANKS!

Replies

I'm also experimenting with this at the moment.


I have a GCD dispatch queue and timer running in the audio unit (not the view controller) to poll the data generated by the render loop: this works OK. The problems come in getting the view controller to update: if I post a notification on the main queue via dispatch_async then it works, but if I have multiple instances of the AU running (on iOS) they all pick up the notification.

Dear Alan,


Thanks for your reply - it's good to know that I'm not the only one who is having this issue! So you choosed the "polling approach" - too bad that this have side effects on multiple instances!


Yesterday I've sacrificed one of my valuable free TSI tickets to get an official answer from Apple on how to implement such functionality. I will keep you updated once I have a feedback.


Best regards,

Thank you, I'd be most interested to hear what the recommended way to deal with this issue is.

Dear Alan,


I received feedback from Apple code support (see below) - actually this is what I did before. I could manage to get the timer to fire in UIViewcontroller now - my fault - but it is still not working correct. I only get one update right after start, then nothing!



The best answer I have so far is that there’s no really direct way to do this as some kind of observation, but it can be done via polling. The steps would be:


— Create a new parameter in your parameter tree to hold the value you want to return from rendering.


— Use the “kAudioUnitParameterFlag_MeterReadOnly” flag on this parameter to make it read-only from the view controller’s point of view.


— In the kernel's render function, store your computed value in local storage of the audio unit.


— Implement the “implementorValueProvider” method (https://developer.apple.com/documentation/audiotoolbox/auparameternode/1439942-implementorvalueprovider) in your audio unit. That method would simply return the current stored value (assuming that’s what you want).


— Create a Timer object in your view controller, set to repeat (say) 20 times a second or less. When the timer fires, query the value of the parameter you added to the parameter tree, using the usual “AUParameter.value” property.


— Update the UI with this value, if it has changed.


The timer fire rate is low enough that it won’t add significant overhead, yet it should be responsive enough to produce smooth changes in your UI.

Thank you for posting Apple's response.


This actually raises another question: I need to pass back an array of data, and using multiple parameters would be very cumbersome. At the moment I keep a reference to the audio unit after creating it in createAudioUnitWithComponentDescription so I can call a method on it to retrieve the data; I wonder whether doing this is problematic in some way?

Dear Alan,


The Apple code support confirmed that my code is correct and this is a bug. He asked me to file a bug report - what I did right now. I assume this will take some time this is sorted out.


About your solution: When creating a weak self this should be fine ... I have done something similar in a past project and it worked!


I also found this forum discussion that could be of interest for you: https://forums.developer.apple.com/thread/39193


Take care!

@Hecot, I was trying to use kAudioUnitParameterFlag_MeterReadOnly earlier the same way you described above and it wasn't working. Calling AUParameter.value wasn't triggering implementorValueProvide. So, after googling I came across this post. I guess it's clearly a bug. Kind of crazy that this wasn't found after 5 major releases of iOS. I guess no one reported the issue to Apple up until you did.

Update: what I said above was tests on iOS 13.6 on my iPad Pro. Later on, I tested it on the iPadOS 14 (beta 2) simulator and I can confirm it works as expected. Would be good to get a confirmation from someone who is running the iOS 14 beta on their devices.