9.1.6 Channel layout problematic?

I’ve been trying to debug a plugin in which I use 7.1.4 as well as 9.1.6 channel layouts.

In Nuendo and Resolve (not aware of another software that supports 9.1.6), the 7.1.4 are laid out correctly, but the 9.1.6 behaves strangely (channels aren’t laid out correctly).

Whilst debugging sound with Resolve, sending signal just to channel 0 in a 7.1.4 track I get the following debug:



As you can see, sound does come through channel 0 correctly.

In a 9.1.6 track, however, the result is as follows:

As you can see, channel 0 is being sent to 12?

I contacted Blackmagic to try and sort this out, but they replied this was a JUCE issue, and provided the following information:

[QUOTE from Blackmagic:]

Here’s the internal JUCE code in question [in juce_VST3_Wrapper.cpp]. That bufferMapper appears to be the internal translation of the VST3 format order to the internal JUCE channel order – but, as you can see – that’s clearly messed up for 9.1.6.

    template <typename FloatType>

    void processAudio (Vst::ProcessData& data)


        ClientRemappedBuffer<FloatType> remappedBuffer { bufferMapper, data };

        auto& buffer = remappedBuffer.buffer;


        jassert ((int) buffer.getNumChannels() == jmax (pluginInstance->getTotalNumInputChannels(),


I’ll note also the following comment in the JUCE 9.1.6 format definition:

    /** Creates a set for a 9.1.6 surround setup (left, right, centre, LFE, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, wideLeft, wideRight, topFrontLeft, topFrontRight, topSideLeft, topSideRight, topRearLeft, topRearRight).


        Note that the VST3 layout arranges the front speakers "L Lc C Rc R", but the JUCE layout

        uses the arrangement "wideLeft left centre right wideRight". To maintain the relative

        positions of the speakers, the channels will be remapped accordingly. This means that the

        VST3 host's "L" channel will be received on a JUCE plugin's "wideLeft" channel, the

        "Lc" channel will be received on a JUCE plugin's "left" channel, and so on.


        Is equivalent to: k91_6 (VST3), kAudioChannelLayoutTag_Atmos_9_1_6 (CoreAudio).


    static AudioChannelSet JUCE_CALLTYPE create9point1point6();

So, the remapping that you note where channel 0 appears on channel 12 is actually this remapper within Juce.

Our own channel order is of course the 9.1.6 SMPTE one, which we’re mapping to the VST3 k91_6 format.


To add: Nuendo as well seems to mess the channel (Left) and of course, in consequence, the whole layout.

Needless to say, would love to find a possible suggestion / fix :slight_smile:

Suggestion: Why not, instead of messing the SMPTE order, you just simply remap channels Lc and Rc in the proper SMPTE order (as if they were Lw and rW), and then it’s the developer who decides whether they are wide or centre?

If I understand you correctly you are “sending signal just to channel 0” in Resolve and this appears in the 12th channel of the JUCE AudioBuffer.

That is the expected, and documented, although somewhat surprising behaviour.

The trick in this case is that VST3 uses a speaker layout in 9.1.6 that follows a different logic than other formats, and places its left speakers where other formats place their wide left speakers.

So channel 0 of VST3’s k91_6 speaker arrangement maps to layout.getChannelIndexForType (juce::AudioChannelSet::wideLeft) which is 12.

Using this logic it’s possible to write your plugin once, given that the plugin uses semantic channels in its logic, and not trying to guess channel indices, and it should work correctly in all plugin formats and all hosts.

Since the framework interacts with the DAW through the VST3 API, it is largely irrelevant what the internal channel order of Resolve is, as long as they map that to k91_6 correctly.

Wait - so I wrote the following code to monitor the channel numbers:

        const auto& layout = bus->getCurrentLayout();
        DBG("dbg left " << layout.getChannelIndexForType(juce::AudioChannelSet::left));
        DBG("dbg right " << layout.getChannelIndexForType(juce::AudioChannelSet::right));
        DBG("dbg c " << layout.getChannelIndexForType(juce::AudioChannelSet::centre));
        DBG("dbg lfe " << layout.getChannelIndexForType(juce::AudioChannelSet::LFE));

        DBG("dbg lsurround side " << layout.getChannelIndexForType(juce::AudioChannelSet::leftSurroundSide));
        DBG("dbg rsurround side " << layout.getChannelIndexForType(juce::AudioChannelSet::rightSurroundSide));
        DBG("dbg lsurround " << layout.getChannelIndexForType(juce::AudioChannelSet::leftSurround));
        DBG("dbg rsurround " << layout.getChannelIndexForType(juce::AudioChannelSet::rightSurround));
        DBG("dbg lsurround rear " << layout.getChannelIndexForType(juce::AudioChannelSet::leftSurroundRear));
        DBG("dbg rsurround rear " << layout.getChannelIndexForType(juce::AudioChannelSet::rightSurroundRear));
        DBG("dbg left centre " << layout.getChannelIndexForType(juce::AudioChannelSet::leftCentre));
        DBG("dbg right centre " << layout.getChannelIndexForType(juce::AudioChannelSet::rightCentre));
        DBG("dbg left wide " << layout.getChannelIndexForType(juce::AudioChannelSet::wideLeft));
        DBG("dbg right wide " << layout.getChannelIndexForType(juce::AudioChannelSet::wideRight));
        DBG("dbg ------- ");

In Nuendo:
In a 7.1.2 channel I get the following:

In a 9.1.4 I get the following:

In a 9.1.6 channel, I get the following:

Why are 9.1.6 and 9.1.4 any different in the way LR are treated, when k91_6 and k91_4 seem to have the same description (aside from the extra 2 top channels)? Is this a Steinberg thing?

You’re right, that the channel layouts should be consistent in this case. Thanks for bringing attention to this.

There is a fix for this issue now on develop

1 Like