Side discussion about multi-bus setup and setPreferredBusArrangement()

If I understood it correctly, at the moment setting up a multi-bus plug-in involves two steps:

  1. In the constructor for our plug-in class derived from AudioProcessor, set up the correct number of busses in the busArrangement member of the AudioProcessor instance, also giving each bus its preferred set of channels (mono, stereo, etc.)

  2. By mean of setPreferredBusArrangement(), “negotiate” with the wrapper which other set of channels are valid for the busses in busArrangement
    (while, of course, the number of input and output busses must not change)

While this is a perfectly valid way for the wrapper to “probe” and get to know which channel configurations are valid, the discussion in the main multi-bus thread has made it quite clear that this, especially step #2 above, is rather convoluted and hard to get right at first attempt.

The reason is that it forces us developer to translate an explicit requirement (for example: my plug-in should deal with mono->mono, mono->stereo, stereo->stereo main bus, and should have a mono sidechain input) into a set of rules to be put inside setPreferredBusArrangement() so that the same requirement results implicitly from them.

Now I wonder: can this be improved further, allowing us to expose/declare/register in the constructor of our AudioProcessor all the valid bus arrangements (complete with the channel configuration for each bus) for the plug-in?

Speaking in code, I imagined something like this (to express the same valid configs I mentioned before):

// Allow mono -> mono
{
    AudioBusArrangement a;
    a.inputBuses.add  (AudioProcessorBus ("Main In",  AudioChannelSet::mono()));
    a.inputBuses.add  (AudioProcessorBus ("Sidechain In", AudioChannelSet::mono()));
    a.outputBuses.add (AudioProcessorBus ("Main Out", AudioChannelSet::mono()));
    registerValidBusArrangement (a);
}

// Allow mono -> stereo
{
    AudioBusArrangement a;
    a.inputBuses.add  (AudioProcessorBus ("Main In",  AudioChannelSet::mono()));
    a.inputBuses.add  (AudioProcessorBus ("Sidechain In", AudioChannelSet::mono()));
    a.outputBuses.add (AudioProcessorBus ("Main Out", AudioChannelSet::stereo()));
    registerValidBusArrangement (a);
}

// Allow stereo -> stereo
{
    AudioBusArrangement a;
    a.inputBuses.add  (AudioProcessorBus ("Main In",  AudioChannelSet::stereo ()));
    a.inputBuses.add  (AudioProcessorBus ("Sidechain In", AudioChannelSet::mono()));
    a.outputBuses.add (AudioProcessorBus ("Main Out", AudioChannelSet::stereo ()));
    registerValidBusArrangement (a);
}

Considerations:

  • This can be added to the current scheme rather than replace it. Simply, the current implementation of setPreferredBusArrangement() could check if the list/array populated by registerValidBusArrangement() is not empty and, in that case, use that list to determine if the proposed arrangement is acceptable or not.

  • To enforce the requirement that the number of busses must stay the same, registerValidBusArrangement() could check and reject them with a jassert if inconsistent with the first one provided.

  • It may look too verbose, but one will have the option to make it more concise by mean of for loops (I know this will resemble the whole setPreferredBusArrangement() mechanism, but as I said in this case this is an option, not mandatory)

  • It provides a more straightforward conversion from the old JucePlugin_PreferredChannelConfigurations macro.
    In particular, this will make it is possible to move out of the current setPreferredBusArrangement() the code to deal with that macro, which will solve the problem described here: Subprocessor bus arragements.
    The conversion can then be performed by the wrapper: if it sees the macro to be defined, it will register the appropriate bus arrangements for the AudioProcessor right after it has been obtained by createPluginFilter()

Does this make sense or am I missing something obvious?

1 Like

it seems a good idea actually, it will simplify a lot both the wrapper code for supporting busses and plugins implementation.

the only drawback is that you couldn’t achieve Dynamic Speaker Arrangements (aka changing number of channels in the busses dynamically) which should be definately possible with vst3 (and probably au3).

Why not?

For example, considering my example above, if the plug-in starts as mono->mono and it is then asked to switch to the output bus to stereo, that combination will also be allowed because the corresponding AudioBusArrangement will be found to be the second entry in the “internal list” of permitted AudioBusArrangements declared in the constructor (mono->stereo).

This looks great and we have been discussing similar solutions. I think registering bus arrangements is a really good solution and a great way to transition from the old system. Some developers will need even more flexibility and can still use the setPreferredBusArrangement. I’ll keep this in mind.