How can I insert multiple plugin racks?

I’m trying to add multiple plugin racks to an edit. I’m able to load one plugin rack in the edit, but as soon as I add multiple ones, then the audio goes wrong (there is only an internal sampler placed at the end of the plugin list).

I’m experimenting with a rack containing only the internal midiModifier, I exported it from Waveform.

Here’s the setup function I use to add the rack to a given audio track:

void AudioEngine::appendTransposeRackPlugin(int trackIndex)
{
    auto xmlPreset  = juce::String::createStringFromData(BinaryData::midiTranspose_trkpreset, BinaryData::midiTranspose_trkpresetSize);
    auto vt = juce::ValueTree::fromXml(xmlPreset);
    auto rackVT = vt.getChildWithName(te::IDs::RACK);
    edit.getRackList().addRackTypeFrom(rackVT);
    
    auto rackFx = dynamic_cast<te::RackInstance*> (edit.getPluginCache().createNewPlugin(te::RackInstance::xmlTypeName, {}).get());
    
    if (rackFx)
    {
        auto track = getOrInsertAudioTrackAt (edit, trackIndex);
        auto index = track->pluginList.size();
        track->pluginList.insertPlugin (*rackFx, index, nullptr);   
    }
}

Calling this function once works, but if I place several racks successively in the plugin list, by doing:

  appendTransposeRackPlugin(0);
  appendTransposeRackPlugin(0);

Then the audio output is garbage.
Here is the XML for the exported rack (it purposefully doesn’t do anything except bypass midi events) :

<?xml version="1.0" encoding="UTF-8"?>

<PRESET name="New Rack" tags="Rack">
  <RACK id="1006" name="New Rack">
    <MACROPARAMETERS id="1011"/>
    <WINDOWSTATE windowPos="109 125 600 500" active="1" windowLocked="1"/>
    <OUTPUT name="midi output"/>
    <OUTPUT name="output 1 (left)"/>
    <OUTPUT name="output 2 (right)"/>
    <INPUT name="midi input"/>
    <INPUT name="input 1 (left)"/>
    <INPUT name="input 2 (right)"/>
    <MODIFIERS/>
    <FACEPLATE width="8" height="4" autoSize="1">
      <RESOURCES/>
    </FACEPLATE>
    <PLUGININSTANCE x="0.5409836065573771" y="0.3451327433628318">
      <PLUGIN type="midiModifier" windowLocked="1" id="1033" enabled="1" presetDirty="1"
              semitonesUp="0.0" windowX="189" windowY="205">
        <MACROPARAMETERS id="1036"/>
        <MODIFIERASSIGNMENTS/>
        <FACEPLATE width="8" height="4" autoSize="1">
          <RESOURCES/>
        </FACEPLATE>
      </PLUGIN>
    </PLUGININSTANCE>
    <CONNECTION src="0" dst="1033" srcPin="0" dstPin="0"/>
    <CONNECTION src="1033" dst="0" srcPin="0" dstPin="0"/>
  </RACK>
</PRESET>

I’m probably doing something wrong in the appendTransposeRackPlugin function, but I can’t figure out what…

It’s probably adding the same Rack to the track twice creating a feedback loop.
If you want separate instances, you probably need to assign a new Rack ID to the rackVT before adding it to the RackList.

You can do this using Edit::createNewItemID() and then newID = writeID (rackVT, nullptr).

Hope that helps.

1 Like

Thank you, unfortunately this is not helping, after I tried

auto rackVT = vt.getChildWithName(te::IDs::RACK);
auto newID = edit.createNewItemID();
newID.writeID(rackVT, nullptr);

But the problem also occurs if I try to add two different racks to the track.

Do you think I should try and also replace all the ids in the rackVT ?

Ah yes, probably. We have quite an elaborate way of doing this in Waveform as we have additional data in our presets like Faceplates which we need to cover.

Does calling
EditItemID::remapIDs (rackVT, nullptr, [&edit] { return edit.createNewItemID(); })
give unique IDs to all the plugins for you?

Yes this seems to give new values to all the ids in the rack plugin and fields. However, still no luck with the audio glitches… I made a self-contained super lightweight project that reproduces the problem, if you have the time to check it out, maybe you can spot the problem?
All you have to do to reproduce is uncomment the designated line in initAudio().bs2_testImportingRackFile-master.zip (6.5 KB)

Yeah, it’s similar to what I thought. The Racks are getting the correct unique IDs now but you’re creating an instance of the same Rack as you’re not specifying what Rack to create an instance for. Changing the following fixes the problem:

    auto rackType = edit.getRackList().addRackTypeFrom(rackVT);
    auto rackInstanceCreationInfo = te::RackInstance::create (*rackType);
    auto rackFx = dynamic_cast<te::RackInstance*> (edit.getPluginCache().createNewPlugin (rackInstanceCreationInfo).get());

I would have expected an error to be thrown when doing this edit.getPluginCache().createNewPlugin(te::RackInstance::xmlTypeName, {}) though as there’s no info there about what Rack to create. Maybe the {} is defaulting the the “0” index Rack.
I’ll see if I can add some warnings to this effect.

2 Likes

Thanks a lot for your time Dave!