Do I need to Lock the UI thread when calling processBlock()?


#1

my audioProcessor want to write some parameters to UI component when call processBlock(),
so I think I need to lock UI thread every time when call processBlock().
But I guess that perhaps juce or the pulgin host has helped me to lock the UI thread when calling processBlock() so
I needn’t to do that? because I did not find any “lock” in the juce audio plugins demo…
thanks~


#2

Yeah, damned right you didn’t!

You should never lock ANYTHING in your process callback, not even a mutex! You’ll find many threads on this forum discussing lock-free fifos and other tricks for communicating back to your UI code from the audio thread.


#3

Yeah, damned right you didn’t!

You should never lock ANYTHING in your process callback, not even a mutex! You’ll find many threads on this forum discussing lock-free fifos and other tricks for communicating back to your UI code from the audio thread.[/quote]

Thank you for your answer, you have pointed out that A LOT OF problems about my coding , so. . Thanks again! :slight_smile:


#4

Note that ::malloc, ::free, ::new, and ::delete implementations all typically lock a global mutex for the duration of the call.


#5

You can have processBlock save some information as a parameter, and set a flag that the gui polls and can notice, then grab the parameter data and reset the flag so that processBlock knows it’s been received - that’s for a simple case, otherwise the fifo as mentioned above might be what you need. The technique mentioned above can also work the other way around, the gui can set a parameter (and a flag if needed) telling process block that it needs to take some special action.


#6

if you are using a thread-queue which is processed in processBlock callback, you need to have a callback mechanism, because if the plugin is inactive, or the might be other situations when the process-block is not called, to have a fall-back mechanism.

Would be great to have reference mechanism directly in the plugin-wrapper. :stuck_out_tongue:

BTW: From a practical view: i’ve created plugins in the past, which holding a mutex for short time (without allocation memory) in the audio-thread, and i had never! any performance problems (like stuttering audio) (even with low sound device latency) with that, BUT this might not be on every platform. So you could never be sure.

Here is a good article about that:
http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing


#7

Well if you are holding a lock for constant time O(1) (on both ends) its no big deal, this is no different than performing a computation. The problem is when the lock is held for O(N).


#8

Hello,

I have been working with a VST audio plugin and have come across the same problem. However, even with trying getCallbackLock (enter & exit) and suspendProcessing functions I couldn’t resolve the issue of interfering the GUI with processBlock. When I modify any variable in processBlock and use it in my GL draw routine (renderOpenGL), it causes gaps and lags between draws. I would appreciate if any of you found a proper solution for this issue or if you could provide any working examples to help me solve the problem. Thank you in advance. :slight_smile:


C++ threads vs JUCE threads - threading tutorials?
#9

Oh my! … seems like I forget to say thanks for all your replys over a year… so…THX…
I found that using a thread-queue is really a great idea .

however, I think the vst sdk 3 has a better solution about send message from UI thread to realtime audio thread
by using " ProcessData.inputParameterChanges" . it provides a Parameter Changes queue inputs correct to “sampling offset” every audio block callback.
So I can make all parameters change happens before start to process the samples. e.g test if no “pitch” changes so I dont need to recalculate the filter coefficients
for resample this block…
So… How do you think about that? masters ? :slight_smile:


#10

@anokta:

Have a look at the AsyncUpdater class, this defers a function call into the UI thread (or any other thread, for that matter).

Also, Vinnie Falco’s VFLib has a solution as in getting a reference for the message thread, and (in)directly deferring an arbitrary function call (or method, for that matter)
into that thread.

http://www.rawmaterialsoftware.com/viewtopic.php?f=2&t=10914 is the topic to look for to see what I mean.

*edit: Added link to multithread topic


#11

@mEnZI1:

The VST3 SDK has a lot of nice things, but none of them are supported by JUCE.
Unfortunately, VST3 is an ugly beast of a lump of code, and support for that is non trivial.
However, nothing is stopping you from trying to bring VST3 support to JUCE.
I’d start with VST3.5 though, since at least that brings VST2 backwards portability and it’s own wrapper with it.

On the mechanism you quote itself, nothing prevents you from using the exact same technique in your code.
All you need is a lock-free FIFO, and once you’ve got that, you can implement the parameter change method
to use that FIFO and do the actual parameter adjustments in processBlock(…).
However, this may put up some strain on your actual processing workload, and it might fire some AudioProcessorListener events,
which will need to be properly taken care of and decoupled from the audio thread as well (again, by using AsyncUpdater or FIFO implementations
and message thread polling).


#12

[quote=“lucem”]@mEnZI1:

On the mechanism you quote itself, nothing prevents you from using the exact same technique in your code.
All you need is a lock-free FIFO, and once you’ve got that, you can implement the parameter change method
to use that FIFO and do the actual parameter adjustments in processBlock(…).
However, this may put up some strain on your actual processing workload, and it might fire some AudioProcessorListener events,
which will need to be properly taken care of and decoupled from the audio thread as well (again, by using AsyncUpdater or FIFO implementations
and message thread polling).[/quote]

Thank you so detailed reply :smiley: .I tried FIFO,but there still one thing make me confusion. :frowning:
I don’t know how to get precisely “sample offset” about a message in processBlock() callback by using FIFO things…
Should I put a High precision timer in UI thread and make it sync to audio thread ?
This problem is just killing me… :x :x :x

I looked at the “vst2warper” in vst sdk 3, looks like the warper will send MIDI messages which have some “special” mark to replace parameter change from UI thread ,so when processEvents() called,
processor can get the “precisely sample offset” because somehow midi message have “sample offset”.
but its seems like juce can’t do the same way…


#13

[quote=“lucem”]@anokta:

Have a look at the AsyncUpdater class, this defers a function call into the UI thread (or any other thread, for that matter).

Also, Vinnie Falco’s VFLib has a solution as in getting a reference for the message thread, and (in)directly deferring an arbitrary function call (or method, for that matter)
into that thread.

http://www.rawmaterialsoftware.com/viewtopic.php?f=2&t=10914 is the topic to look for to see what I mean.

*edit: Added link to multithread topic[/quote]

Thank you for the quick response. I have tried AsyncUpdater by doing my assignments (audio variable to gui variable) in handleAsyncUpdate and calling triggerAsyncUpdate in my update function - to be called from timerCallback function of my editor. It didn’t change a thing though. I have also tried to put triggerAsyncUpdate in my draw routine, but still no luck in reducing that glitchy gui draws. Am I doing something wrong here?

On the other hand, I am now trying to put my variables in a ValueTree and set/get properties accordingly from my audio and draw routines, it seems to reduce the problem a bit. I’ll also check VFLib as well as soon as possible. Thanks again for the feedback.


#14

Well, of course when buffering you will have to calculate the sample offset along and store it in the FIFO
(and it is assumed they are supplied in temporal order).
But you will have to do that for all MIDI messages anyway, so it’s probably better to move that calculation up to the MIDI receiver code and attach the timestamp there.
The AudioPlayHead class can supply you with some of the data you might need in the process :wink:


#15

Now that’s exactly my current problem! I have successfully set up message queues between the UI and the Processor and the other way round, but if Processor::processBlock() is not being called my Processor queue gets filled with no chance to be processed. I tried to flag whether the Processor is running using prepareToPlay() / releaseResources(), but that’s not reliable.

I have in mind to place a “dummy” call to SetParameterNotifyingHost() from the GUI after posting a message to the Processor queue, and process queued messages in MyProcessor::setParameter(), but I think there are better solutions… How are you guys addressing this?


#16

I require that processBlock() is called constantly.


#17

in a plugin you can’t rely on that. The host may not call processBlock, to save CPU when silence in produces silence out. Neither it calls it before prepareToPlay or after releaseResources.


#18

and will processBlockBypassed be called everytime when processBlock is not called ?
or is it possible that none is getting called ?


#19

I am also a bit confused about the juce threads.

Can someone show me the code that allows the UI thread to access a member variable of an internal plugin? I have a timer callback from the UI thread that wants to look at a plugin's variable.

The internal plugin sets its member variable during processBlock.