# Current state of bypass management

**URL:** <https://forum.juce.com/t/current-state-of-bypass-management/54662>\
**Category:** Audio Plugins\
**Created:** [January 24, 2023, 10:44am UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662 "2023-01-24T10:44:59Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![lcapozzi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/lcapozzi/32/10960_2.png) [@lcapozzi](https://forum.juce.com/u/lcapozzi)\
**Post date:** [January 24, 2023, 10:44am UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/1 "2023-01-24T10:44:59Z")

</div>

Hi guys,

I’m trying to deal with the situation where hosts are not calling processBlockBypassed when a plugin gets bypassed via the host bypass buttons. I’ve read several threads, some of them dated almost 10 years ago, and the situation looks basically unsolved.

I know about getBypassParameter method, but I don’t think that’s a reliable solution. Most hosts looks like to just not calling processBlock any longer, when their bypass is on, so there’s no way (afaik) to reliably detect the bypass state and clear buffers (or do anything we need to do when the plugin is bypassed). EDIT: looks like getBypassParameter is not getting called at all. I tried overriding the method and it’s never called.

Right now, I’m trying with a bare boolean to detect if processBlock is working

```auto
isProcessing = true; //first processBlock row
//--- my processing code ---
//isProcessing = false; //last processBlock row

```

Then I can check the state of this bool in getStateInformation, since it’s seems to be called when the bypass button on the host is clicked. That works but it’s obviously useless if you need to do buffer operations, so I’m back to square one.

I also tried to check if the processor gets suspended, but looks like it is not… so, basically, there are hosts (like Live, Reaper, maybe Logic Pro) which are simply not calling processBlock or entirely skipping the plugin in the chain.

Has anyone found a viable workaround to this?

Thanks,  
Luca

---

<div class="post-metadata">

**Author:** ![jcomusic](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jcomusic/32/2014_2.png) [@jcomusic](https://forum.juce.com/u/jcomusic)\
**Post date:** [January 26, 2023, 6:34am UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/2 "2023-01-26T06:34:02Z")

</div>

Hi,

Some hosts allow disabling the plugin entirely in addition to bypassing it. It’s also not uncommon that the plugin is suspended (e.g. no processing is ever called) to save CPU, Logic is very aggressive with that. There is also no rule that forces a host to support the soft bypass of your plugin in addition to its own bypass mechanics.

Long story short: Neither can you rely on processBlockBypassed being used, nor can you reliably detect if the plugin is suspended.  
The best workaround for “plugin is inactive” detection I have found so far is storing a timestamp in my process callback and having the UI test how long ago that was. If it’s more than X (few hundred ms), I use this to fade out some audio engine visual feedback. I’m also making sure that everything works from a usability perspective without any audio processing ever happening. This is important for cases like “offline processing” in Cubase, for example.

I’d also recommend not making any assumptions on when exactly getStateInformation will be called. Host behavior is wildly different when it comes to that. I’ve even seen situations where hosts call setStateInformation during a process callback (which should never ever happen - but it does). Best play it as safe as possible, and assume that hosts will interpret the plugin interfaces creatively to the point of ignoring specifications.

---

<div class="post-metadata">

**Author:** ![lcapozzi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/lcapozzi/32/10960_2.png) [@lcapozzi](https://forum.juce.com/u/lcapozzi)\
**Post date:** [January 26, 2023, 8:06am UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/3 "2023-01-26T08:06:30Z")

</div>

> [@jcomusic](#):
>
> assume that hosts will interpret the plugin interfaces creatively to the point of ignoring specifications

that was my assumption too after struggling with this 😃 Thanks for your feedback, @jcomusic. Your timestamp suggestion could be a fine workaround.

Luca

---

<div class="post-metadata">

**Author:** ![lcapozzi](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/lcapozzi/32/10960_2.png) [@lcapozzi](https://forum.juce.com/u/lcapozzi)\
**Post date:** [January 30, 2023, 3:03pm UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/4 "2023-01-30T15:03:40Z")

</div>

Thanks @jcomusic. I used a similar workaround, but stored in processBlock.

Basically I store, at the end of processBlock, the value of Time::getMillisecondsCounter()  
At the very beginning of processBlock, I get another call to getMillisecondsCounter and compare it with the previously store. If the difference between the two is over a predefined threshold, I call the methods I need to clear my buffers. Works flawlessly.

---

<div class="post-metadata">

**Author:** ![rip-off](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/rip-off/32/2406_2.png) [@rip-off](https://forum.juce.com/u/rip-off)\
**Post date:** [November 30, 2023, 8:42am UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/5 "2023-11-30T08:42:24Z")

</div>

And how does that work in offline rendering then? The timings must be vastly different I assume…

---

<div class="post-metadata">

**Author:** ![jcomusic](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jcomusic/32/2014_2.png) [@jcomusic](https://forum.juce.com/u/jcomusic)\
**Post date:** [December 4, 2023, 9:20pm UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/6 "2023-12-04T21:20:59Z")

</div>

You can (and should) check for offline/non-realtime rendering. I’d only use the timestamp trick for non-critical stuff like disabling visualizers in the UI and the like. I’ve had good experience with thresholds in the range of “no update during the last 250ms”. Offline rendering has a high probability of running faster than realtime, so it could even be a good idea to throttle down things like UI feedback for that case. It depends, it could just as well be blocking for a long time between process calls because some plugin needs to do a blocking load of sample data during offline rendering.

I’d definitely not rely on the timestamp heuristic for anything affecting audio processing. Transitions between offline and non-offline can be detected quite well without it, and they can be used to clear history buffers (reverb or delay tails, filter state, etc). Not all DAWs behave the same way when it comes to reset and prepare calls. But that’s a different rabbit hole.

---

<div class="post-metadata">

**Author:** ![rip-off](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/rip-off/32/2406_2.png) [@rip-off](https://forum.juce.com/u/rip-off)\
**Post date:** [December 11, 2023, 8:52am UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/7 "2023-12-11T08:52:30Z")

</div>

Yep that is what I was thinking. We want to clear buffers / effect tails / meters etc. also when bypassing and then un-bypassing, not just when switching between non realtime and realtime rendering. So we implemented the timer based thing also for audio stuff. Of course that only works in realtime mode but hey - it’s something. For offline rendering we have to rely on processBlockBypassed() or the bypass parameter so there will be a known issue regarding offline rendering in Logic, Reaper and possibly other more exotic DAWs. I’m curious whether that all goes through release qualification… 😅

As part of the implementation I did some research on which DAW does what to implement bypass that I think could be handy for others should they find themselves in the position of having to “fix” the bypass handling of their plugins.

# Cubase 13

## Deactivating by clicking the _Activate_ button

Stops calling processBlock() and does not call processBlockBypassed()

## Activating by clicking the _Activate_ button

Calls perpareToPlay()

## Bypassing by clicking the _Bypass_ button

#### Without getBypassParameter() overridden

Calls processBlockBypassed()

#### With getBypassParameter() overridden

Continues to call processBlock() with bypass parameter set to 1.0

## Un-Bypassing by clicking the _Bypass_ button

#### Without getBypassParameter() overridden

Starts calling processBlock() again

#### With getBypassParameter() overridden

Continues to call processBlock() with bypass parameter set to 0.0

## Differences between VST2 & 3

Could not check as Steinberg is the only DAW manufacturer not supporting VST2 on an M2 Mac

# Pro Tools Ultimate 23.09

## Bypassing by clicking the _Bypass_ button in the plugin window frame

#### Without getBypassParameter() overridden

Calls processBlockBypassed()

#### With getBypassParameter() overridden

Continues to call processBlock() with bypass parameter set to 1.0

## Un-Bypassing by clicking the _Bypass_ button in the plugin window frame

#### Without getBypassParameter() overridden

Starts calling processBlock() again

#### With getBypassParameter() overridden

Continues to call processBlock() with bypass parameter set to 0.0

# Logic Pro X

## Bypassing and unbypassing using the on/off button in the plugin window frame or channel strip

Stops & resumes calling processBlock()

You cannot really get logs very well from Logic now that they’re sandboxing plugins in AUHostingService. So the behaviour is my best guess for the symptoms I saw.

# Studio One 6

## Deactivating by clicking the _Activate_ button

Stops calling processBlock() and does not call processBlockBypassed()

## Activating by clicking the _Activate_ button

Calls perpareToPlay()

## Bypassing by clicking the _Bypass_ button

#### Without getBypassParameter() overridden

Calls processBlockBypassed()

#### With getBypassParameter() overridden

Continues to call processBlock() with bypass parameter set to 1.0

## Un-Bypassing by clicking the _Bypass_ button

#### Without getBypassParameter() overridden

Starts calling processBlock() again

#### With getBypassParameter() overridden

Continues to call processBlock() with bypass parameter set to 0.0

## Differences between VST2, VST3 & AU

None

# Live

## Deactivating by clicking the Device Activator button

Stops calling processBlock()

## VST2: Activating by clicking the Device Activator button

Calls perpareToPlay()

## AU & VST3: Activating by clicking the Device Activator button

Starts calling processBlock() again

# Reaper

## Deactivating the plugin by unchecking the checkbox

Stops calling processBlock() and does not call processBlockBypassed()

## Activating the plugin by unchecking the checkbox

Starts calling processBlock() again

## Differences between VST2, VST3 & AU

None

## Adding a dedicated bypass parameter and returning it to JUCE wrappers by overriding getBypassParameter()

Three of the tested DAWs change their behaviour:

Cubase 13

Pro Tools Ultimate 23.09

Studio One 6

all continue to call processBlock() with the bypass parameter set to 1 instead of 0 when bypassed.

Studio One and Cubase have the additional “Activate” button which behaves the same no matter whether there is a bypass parameter or not.

## Difference between effect and instrument plugins

The difference I found is that Pro Tools and Reaper stop calling the processing callback when there is silence in the channel for longer than approximately 15 seconds or so.

---

<div class="post-metadata">

**Author:** ![HowardAntares](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/howardantares/32/4629_2.png) [@HowardAntares](https://forum.juce.com/u/HowardAntares)\
**Post date:** [December 11, 2023, 2:43pm UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/8 "2023-12-11T14:43:48Z")

</div>

Note that Cubase also has a Preference to stop calling the plugin when there is no audio.

---

<div class="post-metadata">

**Author:** ![jcomusic](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/jcomusic/32/2014_2.png) [@jcomusic](https://forum.juce.com/u/jcomusic)\
**Post date:** [December 11, 2023, 5:54pm UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/9 "2023-12-11T17:54:18Z")

</div>

Hey! Thanks for sharing the info about the behaviour you observed. It might be relevant to also take “reset” calls into consideration that DAWs can use to explicitly notify a plugin that it should probably clear its buffers.  
Reaper also wins the “anything is possible” competition by letting the user configure how and what of the plugin API to call in various combinations.

---

<div class="post-metadata">

**Author:** ![dpsproservices](https://avatars.discourse-cdn.com/v4/letter/d/d26b3c/32.png) [@dpsproservices](https://forum.juce.com/u/dpsproservices)\
**Post date:** [September 10, 2024, 2:07pm UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/10 "2024-09-10T14:07:27Z")

</div>

Thank you so much for providing this info it would have taken days to figure out

---

<div class="post-metadata">

**Author:** ![dpsproservices](https://avatars.discourse-cdn.com/v4/letter/d/d26b3c/32.png) [@dpsproservices](https://forum.juce.com/u/dpsproservices)\
**Post date:** [September 11, 2024, 4:43pm UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/11 "2024-09-11T16:43:24Z")

</div>

> [@jcomusic](#):
>
> . I’ve even seen situations where hosts call setStateInformation during a process callback (which should never ever happen - but it does).

Do you recall which host(s) that occurred ? Also was it only setStateInformation or any other AudioProcessor functions that you have seen called during a processBlock ? I have never seen a pliugin code example which has any code in the PluginProcessor which does additional logic to deal with situation like that. If anyone has please reply here want to look at an exmaple.

---

<div class="post-metadata">

**Author:** ![dpsproservices](https://avatars.discourse-cdn.com/v4/letter/d/d26b3c/32.png) [@dpsproservices](https://forum.juce.com/u/dpsproservices)\
**Post date:** [September 11, 2024, 5:17pm UTC](https://forum.juce.com/t/current-state-of-bypass-management/54662/12 "2024-09-11T17:17:00Z")

</div>

> [@jcomusic](#):
>
> Transitions between offline and non-offline can be detected quite well without it

How do we do detect transition between offline and non-offline processing?
