I’m facing a dilemma regarding how to share data between UI and Audio threads.
I totally understand that I won’t have the perfect solution and it’s just a matter of choice and trade off.
I read almost all the topics talking about it on the JUCE forum and also the great ADC videos. However I cannot still make a decision and the point of this post is to share ideas about it and maybe it could help someone who is facing the same problem.
I currently written a plugin with multiple effects. I also have a LFO that can modulate these effect.
The parameter UI enables min/max modulation range and need to display them plus the current scaled value computed regarding the lfo value (like Serum with its destination pattern).
I’ve more than 30 UI effect where I should display Min - Max - scaledValue related to the lfo.
I’m facing 2 cases:
Case 1: all computation in AudioThread
The MainThread slider will only sent min max between [0,1] to the AudioThread.
The AudioThread will listen them convert the [0,1] value to the desired effect range (with NormalisableRange), it will also listen to the lfo parameter and will use it to scale the effect value and use it.
The full process will be:
- the UI change the min max value and send it to the AudioThread using ValueTree
- the AudioThread get the normalized min max and store them into the real min max range.
- the AudioThread get the changed lfo value and scale the parameters.
- the MainThread poll the min/max/scaledValue and propagate them into the related UI component to display value on labels.
I will need to send to the MainThread a lot of parameter min/max/scaledValue (around 30 * 3 = 90 atomic values).
I know how to handle it with a map and other pattern but it still a lot of code since I have to pass them into the UI component after taking them into the timberCallback of the editor.
Also having the NormalisableRange inside the Processor seems to be a smell code.
case 2: all computation in MainThread
The MainThread listen to the lfo value change using a timerCallback related to the AudioThread (classic pattern). The value is propagated to the desired UI component, and can compute the scaled value and display it directly but I will use ValueTree to send these data to the AudioThread.
I reduce a lot the code but I’m worried about the effeciency now.
The full process will be:
- lfo value is changed
- the MainThread listen the AudioThread with a callback and get this value
- the value is propagated into the UI desired class
- the UI do the computation to get the scaled value, display the labels and send the scaled value to the AudioThread using a ValueTree
- the AudioThread will read the new value only at the next (or more?) call of processBlock.
I would like to be able to use this case since it reduce the code but I’m worried using this with a lot of parameters.
Also I don’t even know how to compare the speed performance to evaluate these 2 cases.
Somebody could share his thought regarding this problem?
Maybe I’m worried for nothing but I’ve the feeling the case 1 won’t scale very well.