SuperDirt internal routing / apply effects to MIDI device

I am sorry for the topic title, it is a bit fuzzy.


I have been trying to spawn some VSTi from within SuperCollider using VSTPlugin. I am doing this because I have audio problems if I use external VSTi and route its output back into SuperDirt (cfr this previous topic).

Below is a minimal example of how it works in sclang:

(
SynthDef(\vstTest, {|out|
	var sound = VSTPlugin.ar(nil, ~dirt.numChannels, id: \Arp2600);
	Out.ar(out, sound);
}).add;
)

~synth = Synth(\vstTest);
~instrument = VSTPluginController(~synth, \Arp2600).open("path/to/vst/plugin", editor: true);

To have the synthesiser played using TidalCycles I can use:

~dirt.soundLibrary.addMIDI(\midi, ~instrument.midi);

as this is basically mimicking MIDIOut.

Now the problem: I am not able to apply any effect the same way I would not be able if I don't route the VSTi output back into SuperDirt.
Is there a solution for this?

In the meantime I also think: is there a way to take a SuperDirt orbit output and plug it back, e.g. the VSTi plays in d1 and I am able to have it as input using d2 $ s "in" via some internal routing so I can apply some effect?

1 Like

Hi @mattia.paterna, thanks so much for your code, I struggled making VST Controller work a few days ago so it helps me a lot, and works perfectly.

As per your question, I think the answer is in SuperDirt hacks folder, there is an examples called :

cross-orbit-rounting.scd

I have not been able to make it work properly yet, but I think that is the way to go.

1 Like

Yes, it works with the example I pointed earlier, there is everything in the scd help file to make it work properly

Sorry for the late reply, that is so good to know! you mean inside cross-orbit-rounting.scd?
Can you post a minimum reproducible example of it?

Yes, everything is there already for the minimal example. Just open it in SC.
Once in SC, open the startup folder and go to SuperDirt folder

Sorry, I was a bit in a hurry earlier, here is the full example :

# read input from another orbit


(
var busses = ~dirt.orbits.collect { |x| x.dryBus };

SynthDef(\readorb, { |out, amp = 1, n = 0| // number
	var bus, sound;

	bus = Select.kr(n, busses);
	sound = InFeedback.ar(bus, ~dirt.numChannels);
	//sound = CombL.ar(sound, 0.2, 0.03, 1);

	Out.ar(out,
		sound * (amp * 2.5)
	)
}).add;
);

# in tidal, e.g.:


d1 $ sound "can bd hh*5 bd" # pan "0" # up "{1 2 3 4}/4"

d2 $ sound "readorb:0 blip"
  # pan "1" # orbit "1"
  # delay "1" # delaytime "0.15" # delayfeedback "0.5"
  # bandf "{90 200 1450 9000}/3" # bandq "10"

d1 $ sound "can*2" # pan "0" # up "{1 2 3 4}/4"

on Mac, it is located here : Library⁩ ▸ ⁨Application Support⁩ ▸ ⁨SuperCollider⁩ ▸ ⁨downloaded-quarks⁩ ▸ ⁨SuperDirt⁩ ▸ ⁨hacks⁩

That is so strange, I can't make it work with the VST although it worked with the example.
It seems like there is no audio signal on the orbit.

@julian (apologies for throwing you in the topic): when I send some MIDI instructions from Tidal, what happens in SuperDirt? Is what I think true, i.e. the sound is not physically inside any orbit hence the internal routing does not work?

I think I might have found an answer using a modified version of \in:

(
SynthDef(\vstIn, { |out, pan|
	var sound;
	sound = In.ar([55, 56]);  // my SynthDef routes to buses [55, 56]
	Out.ar(out,
		DirtPan.ar(sound, ~dirt.numChannels, pan)
	)
}).add
);

but I see two problems:

  1. I need define the SynthDef above before defining the other SynthDef that hosts the VSTi (don't know why though)
  2. I need manually define the buses therefore create as many SynthDefs as I need. Is there a way to parametrise the in busses e.g. vstIn # buses [55, 56]?

I also thought of using dirt_from but I didn't understand how.

@mattia.paterna I have updates for you :slight_smile: Step by step I am able to understand the routing process in SuperDirt. An orbit has four different bus types:

  • outBus
  • synthBus
  • globalEffectBus
  • dryBus

When you route your (VST) SynthDef through the dryBus then you are able to apply globalEffects on it:

(
var bus = ~dirt.orbits[0].dryBus;

SynthDef("VST", { |pan = 0, n = 0|
	var sound;

	sound = In.ar(bus, ~dirt.numChannels);

	sound = VSTPlugin.ar(sound, ~dirt.numChannels, id: \vk); // This is a vst instrument
	Out.ar(bus,
		DirtPan.ar(sound, ~dirt.numChannels, pan)
	)
}).add;

)

I know that the orbit here is static. You would still have to extract the orbit from TidalCycles when using the vst_midi event, select the bus from SuperDirt and pass it to the VST synth. But this is more a topic for the VST thread.

This works totally fine when I use it in TidalCycles:

d1 $ n "0 1 2 3" # s "vk" 
   # room 0.5 # sz 0.9
   # leslie 1 # lsize 2.8 # lrate 6.7

Here are some references to global effects:

I hoped when I am using the synthBus that even every non global effect would be applied but it looks like that it does not work this way.

But at least you can basically work with it without constantly using an extra in SynthDef.