It was the same version which is the latest Ableton 10. It also happens with Reaper 6 on Windows. If this never worked @dave96, how do you get rid of the click when bypassing? The problem is that the host just doesn’t call processBlock anymore when bypass is active, so there is no way to implement some kind of crossfading…
I didn’t get rid of it. I just gave up trying in the end and moved on to something else as it seemed like a host bug.
I guess what would be interesting would be to try it on some non-JUCE based plugins and see if they suffer from the same problem?
I see!
So… Is there any solution to this from the JUCE team? All I want is a click-free bypass, it kind of weirds me out that this is so difficult to achieve @jules
Hi, did you solve this problem? I met the same problem.
nope
This seems to be a really old thread but let me add my 2 pennies.
IIRC If you’ve declared a bypass parameter in JUCE via getBypassParameter
, then I don’t believe processBlockBypassed
will ever be called (although that probably wasn’t implemented when Dave first wrote this post). If you haven’t then yes I’ve certainly seen DAW’s call this in the past.
However, Logic never will call this method as its bypass is not actually a bypass it just stops processing altogether. Reaper should have two different bypass mechanisms, one will stop processing altogether (like Logic) the other should indeed notify your bypass parameter or call processBlockBypassed
, but it’s been years since I tested that. I’m less sure about BitWig, but that actually sounds quite smart as it means you get constant processing performance which can reduce glitches due to sudden changes in processing.
See my comment here for more information
Interesting, I can report that for Reaper and Ableton 10 it will call processBlockBypassed if you implemented the bypassParameter. However in both cases the parameter is not linked and if you bypass in the DAW neither processBlock nor processBlockBypassed are called.
Are you testing VST2 by any chance? linking can’t be done with VST2 (at least not in both directions). Which just adds another layer of complexity to the bypass shenanigans.
Nope, VST2 is dead (finally)
I might be getting some things confused with the JUCE host implementation then. I would dig around in juce_VST3_Wrapper.cpp
it should set the Vst::ParameterInfo::kIsBypass
flag on the parameter. I’m surprised though because the only time it calls processBlockBypassed
is when the bypass parameter reports that it’s bypassed and if all is correct then that bypass parameter should be the one returned by getBypassParameter
. I think you also have to make sure that the bypass parameter is in your normal list of reported parameters too, although if it’s not linking with your bypass parameter JUCE must be adding one so you should see it as an additional bypass parameter. I guess if you were returning a parameter in getBypassParameter
but it wasn’t included in the normal list of parameters too then there would only be one bypass parameter reported to the host (the one created by JUCE) so you would end up with processBlockBypassed
working but it wouldn’t sync with your bypass parameter.
I’ve added the bypass parameter to my “normal” parameters and I’m returning it in getBypassParameter()
. Both Reaper and Ableton call processBlock
and processBlockBypassed
then. If I bypass in the DAW neither processBlock
nor processBlockBypassed
are called, so I can’t do anything here…
I’ve just been looking at Reaper and indeed it doesn’t really have what I like to call a bypass (I thought it did I must have been wrong), the documentation says (emphasis mine)…
…This will toggle the bypass of the selected fx. You will no longer hear the effect(s) and they will no longer use CPU resources.
However, if I load one of the stock Apple AU plugins I can see in auval that they don’t have a bypass parameter, but in Reaper it shows a bypass parameter and a wet parameter too. These are host parameters. Unfortunately, the “bypass” parameter is as described above. I suspect Reaper are using the “wet” parameter as a way to allow users to “bypass” the plugin in a glitch-free way, but I also expect that isn’t linked to the bypass parameter in the plugin?
For VST3 I assume if you return a bypass parameter you’ll see two parameters in the list? one being the enable/disable offered by the host and the other being your bypass parameter.
One host that I remember definitely having the linking ability in the past was Cubase. AAX also makes you say which parameter is the bypass parameter so I think ProTools will link the host bypass and plugin bypass.
TBH you’re at the mercy of the host and there’s not much you can do about it . I’m also not sure you should do anything about it as you would be changing the behaviour of the host just for your plugin. If you just want to show that the plugin is bypassed in the GUI you could maybe see if
releaseResources
has been called, or if that’s not consistent, add a mechanism to detect that processBlock
hasn’t been called (you’ll know the maximum block size and samplerate so you’ll have some rough idea of when to expect the next processBlock
).
Yes, it’s not linked.
Exactly
Indeed! Actually it’s not that much of a problem that the bypass parameter is not linked. The way it behaves now is as good as it gets: If the host supports it, the bypass parameter is linked. If it doesn’t you can use my own bypass parameter for glitch-free latency compensated bypassing. If it’s not linked and you use the host’s bypass and you experience a glitch I can’t do anything about it.
so, to summarize: adding a bypass parameter won’t always work with all hosts, but it also won’t break anything in hosts that don’t support it, so you might as well…?
Is this correct?
Just to make clear as this topic is confusing enough:
The LINKING won’t always work. Controlling your bypass parameter from your editor always works. So yes, it’s still a good idea if you don’t want to rely on the host’s bypass implementation.
OK, I’m confused: in looking through the JUCE docs for AudioProcessor::getBypassParameter(), it says that the host should never call processBlockBypassed if this parameter is implemented, instead using the parameter to control the bypass state.
SO… if a host does support bypass parameters and is following the Jules Rules, then it will always call processBlock() and never processBlockBypassed(), right?
And if a host does not support bypass parameters, then it will… always call processBlock() and never processBlockBypassed(), right? the only difference being that it won’t update the state of that parameter to control the bypass…?
so when exactly does processBlockBypassed get called? Ever?
Well, the host doesn’t follow those rules, both Ableton and Reaper call processBlockBypassed if the bypass parameter is implemented.
In order to be save I check the bypass parameter in the processBlock too.
So far no problem, except that the linking doesn’t work and if I use the host’s internal bypass switch neither processBlock nor processBlockBypassed get called - nothing to do here…
gotcha. well, I guess that’s the best we can do for now!
I think the confusion from the docs might be when you use JUCE to host a plugin or any AudioProcessor, rather than when you implement a plugin. Maybe the docs should be updated to reflect that.
Just checked this, for VST3 in Cubase and Live. The distinction Anthony mentions is relevant to VST3 -that’s how it works in Cubase.
Bypass controls the bypass parameter. When it’s on, the wrapper calls processBlockBypassed. Deactivate disables the processing callback, both of them. There’s always a bypass parameter. If you don’t provide one, the wrapper creates it. If you provide one but it’s not in your list of parameters, the wrapper adds it. VST3 doesn’t require a bypass parameter, but it defines a flag (kIsBypass) for it, and says: “special bypass parameter (only one allowed): Plug-in can handle bypass (highly recommended to export a bypass parameter for effect Plug-in)”. What the plugin does with it is not Steinberg’s business -what the Juce wrapper does is calling processBlockBypassed.
The thing is that many (most?) hosts don’t have a bypass button like the Cubase one, so the only way to use the bypass parameter as defined by VST3 is through the plugin’s own interface. That’s what happens in Live. Live’s “device activator” is like Cubase’s “activate effect”. There’s no bypass in the DAW’s interface (no button linked to the bypass parameter as defined by VST3), but the parameter is still there, because the wrapper always provides it, and if you set it, the wrapper calls processBlockBypassed. So…
If this method returns a nullptr then you can still control the bypass by calling processBlockBypassed instead of processBlock. On the other hand, if this method returns a non-null value, you should never call processBlockBypassed but use the returned parameter to control the bypass state instead.
This is the confusing part. I don’t know how Juce hosting works, but this is certainly not what the VST3 wrapper does. The wrapper checks the parameter and chooses the callback accordingly. This suggests a different scheme -to make the plugin itself check its own bypass state.
(edit) Just to clarify, I ask about this because it doesn’t match what the plugin wrappers do -they call processBlockBypassed, not processBlock, when the bypass parameter is on. Many people seem to be checking the bypass parameter in processBlock based on this indication, and I’m not sure if that’s really needed. I guessed Anthony might remember how this came up from the thread where Fabian solved the current implementation.