AudioPluginInstance doesn't react to changing bus counts

I’m writing software which loads and uses AU/VST3 plugins and I have some confusion regarding AudioPluginInstance channel and and bus counts and how they can be changed.

If the plugin instance says that it allows adding more audio busses to it, how should it be done in practise? Below is my test code which gave me really weird results: (see code comments for what the return values are)

juce::AudioPluginInstance* p_plugin = ....;     // Native Instruments Battery AU plugin is loaded here

const bool can_add_bus = p_plugin->canAddBus(false);        // Returns TRUE

const int bus_count_1 = p_plugin->getBusCount(false);       // Returns 1
const int temp1a = p_plugin->getTotalNumOutputChannels();   // Returns 2
const int temp1b = p_plugin->getMainBusNumOutputChannels(); // Returns 2


p_plugin->addBus(false);
p_plugin->addBus(false);
p_plugin->enableAllBuses();


const int bus_count_2 = p_plugin->getBusCount(false);       // Returns 1 !!!!!!!!
const int temp2a = p_plugin->getTotalNumOutputChannels();   // Returns 2 !!!!!!!!
const int temp2b = p_plugin->getMainBusNumOutputChannels(); // Returns 2

As you can see, the bus/channel count didn’t change even when I tried adding two more output busses to the plugin. What am I doing wrong here?

To make matters weirder, This plugin seems to always already have 4 busses inside its own menu, regardless of how many busses I may add to it in my code:

On top of that, the plugin has some extra “Direct Outs”. A lot of them. How do I access those through my code? I’m confused what to think of this.

Any points to make this situation less confusing is appreciated.

I think I’d expect that to work.

Could you try loading the same plugin in the AudioPluginHost, then right-click on the plugin node and configure its I/O. You should then see a window where you can add and remove buses. Does the plugin behave as expected when you update the buses in this way? If so, perhaps you could check for differences between your code and the AudioPluginHost.

Are you making sure that the plugin is not processing (i.e. prepareToPlay() and releaseResources() have been called the same number of times) at the point where you reconfigure the buses?

1 Like

Part of the problem seems to be that I indeed had called prepareToPlay() before I tried adjusting the bus amounts. After fixing that I can now change the bus amounts.

However, Battery still shows the exact same bus and output names in its own menus as seen in the pictures I posted. This behavior seems to happen the exact same way also in AudioPluginHost.

To be clear, in AudioPluginHost (and now also in my own software) Battery starts with 2 audio outputs. The output amount reacts correctly as expected when their number is changed by the user. But at all times Batterys own internal menu shows those exact same 4 bus and 16/32 output names, without any changes to them at all.

What really puzzles me is that how, and from where exactly, does Ableton Live find that long list of audio outputs, which are also shown in Batterys internal output list from the start. Here’s a picture from Ableton Live what it lists as Battery’s audio channels which can be used to receive audio into to the Lives own mixer channels:

That’s basically the same list from Batterys Output→Direct Out menu.

Does JUCE give access to this same data or has it been omitted somehow by the JUCE API? Is the way to implement this type of “find maximum amount of output channels” by calling AudioProcessor::canAddBus() in a loop as long as it returns TRUE?

I tried testing Battery 4 in auval, here’s the relevant bit of output:

Reported Channel Capabilities (explicit):
      [0, -32]  

No Input, Output Chans:
0-1   0-2   0-4   0-5   0-6   0-7   0-8
X     X     X     X     X     X     X     

# # AudioChannelLayouts (8), Output Scope:
ChannelLayout is Writable: T
The Unit publishes the following Channel Layouts:
  0x640001, 0x650002, 0x710003, 0x6C0004, 0x750005, 0x790006, 0x7D0007, 0x7E0008, 

Is Audio Channel Layout Available:
Mono    Stereo  Binau.  AU_4    Ambi.   AU_5    AU_5_0  AU_6    AU_6_0  AU_7_0  AU_7_0F AU_8    AU_5_1  AU_6_1  AU_7_1  AU_7_1F 
X       X               X                                                                       X       X               X       

The first couple of lines ([0, -32]) indicate that the plugin supports 0 input channels, and up to 32 output channels across all buses.

The following lines indicate that the plugin supports explicit channel layouts (i.e. channels with placement/content semantics like left, right, LFE). These explicitly-declared layouts are what we surface in the AudioPluginHost.

It looks like Live and REAPER might just be using a single output bus but asking for the maximum number of channels on that bus, and then in Live’s case, arbitrarily dividing that into stereo pairs. At least in REAPER, the output/routing menu inside Battery doesn’t seem to change based on the number of channels on the DAW track, so maybe it’s hard-coded to always display all 32 channels, even when some of those aren’t available in the DAW.

I’m not sure if there’s a way to replicate this behaviour through JUCE, since we always try to respect the explicit channel layouts if they’re available. So, querying the max channels allowed on bus 0 will return 8 in JUCE (the width of a 7.1 layout, which is the largest explicit layout) instead of 32 (the total number of channels allowed across all output buses).

I don’t think we’ll be able to make any changes in this area in the near future, but I’m working on some larger updates to the AudioProcessor machinery at the moment, and I’ll try to consider this use-case as part of that work.

1 Like