SuperDirt effects on VST plugins in Tidal cycles

Hello,

I’m quite new to Tidal Cycles so please forgive me if I’m describing some technical aspects not 100% correct.

Currently, I’m trying to build an performance instrument for my personal use that includes a 16ch mixer with reverb, delay and hpf/lpf and of cource volume control all implemented in mixbusses which is controlled by Launchcontrol XL.

I use TidalCycles for sequencing samples and alike. The orbits 0 to 15 are routed to mixbusses I defined and represent the 16 mixer channels.

In BootTidal.hs I mapped the d1 - d16 to the corresponding orbits:

“ d1 = p 1 . (|< orbit 0)

d2 = p 2 . (|< orbit 1)

d3 = p 3 . (|< orbit 2)

d4 = p 4 . (|< orbit 3)

d5 = p 5 . (|< orbit 4)

d6 = p 6 . (|< orbit 5)

d7 = p 7 . (|< orbit 6)

d8 = p 8 . (|< orbit 7)

d9 = p 9 . (|< orbit 8)

d10 = p 10 . (|< orbit 9)

d11 = p 11 . (|< orbit 10)

d12 = p 12 . (|< orbit 11)

d13 = p 13 . (|< orbit 12)

d14 = p 14 . (|< orbit 13)   

d15 = p 15 . (|< orbit 14)

d16 = p 16 . (|< orbit 15)”

In startup.scd I’ve initialized the busses and assigned the orbits to the corresponding mixbusses:

s.waitForBoot {
	//Define Busses
	s.newBusAllocators; // Reset Bus counters
	~mixBusCh1 = Bus.audio(s,2);
	~mixBusCh2 = Bus.audio(s,2);
	~mixBusCh3 = Bus.audio(s,2);
	~mixBusCh4 = Bus.audio(s,2);
	~mixBusCh5 = Bus.audio(s,2);
	~mixBusCh6 = Bus.audio(s,2);
	~mixBusCh7 = Bus.audio(s,2);
	~mixBusCh8 = Bus.audio(s,2);
	~mixBusCh9 = Bus.audio(s,2);
	~mixBusCh10 = Bus.audio(s,2);
	~mixBusCh11 = Bus.audio(s,2);
	~mixBusCh12 = Bus.audio(s,2);
	~mixBusCh13 = Bus.audio(s,2);
	~mixBusCh14 = Bus.audio(s,2);
	~mixBusCh15 = Bus.audio(s,2);
	~mixBusCh16 = Bus.audio(s,2);

	~dirt.stop; // stop any old ones, avoid duplicate dirt (if it is nil, this won't do anything)
	~dirt = SuperDirt(2, s); // two output channels, increase if you want to pan across more channels
	~dirt.loadSoundFiles;   // load samples (path containing a wildcard can be passed in)
	~dirt.loadSoundFiles("/Users/msautark/Documents/Projects/TidalCycle_Compositions/audio/*"); // load central user samples

	s.sync; 
	// start listening on port 57120, create two busses each sending audio to channel 0
	~dirt.start(
		57120,
		outBusses: [
			~mixBusCh1, ~mixBusCh2, ~mixBusCh3, ~mixBusCh4,
			~mixBusCh5, ~mixBusCh6, ~mixBusCh7, ~mixBusCh8,
			~mixBusCh9, ~mixBusCh10, ~mixBusCh11, ~mixBusCh12,
			~mixBusCh13, ~mixBusCh14, ~mixBusCh15, ~mixBusCh16
		]
	);
	SuperDirt.default = ~dirt; 

	(
		~d1 = ~dirt.orbits[0]; ~d2 = ~dirt.orbits[1]; ~d3 = ~dirt.orbits[2];
		~d4 = ~dirt.orbits[3]; ~d5 = ~dirt.orbits[4]; ~d6 = ~dirt.orbits[5];
		~d7 = ~dirt.orbits[6]; ~d8 = ~dirt.orbits[7]; ~d9 = ~dirt.orbits[8];
		~d10 = ~dirt.orbits[9]; ~d11 = ~dirt.orbits[10]; ~d12 = ~dirt.orbits[11];
		~d13 = ~dirt.orbits[12]; ~d14 = ~dirt.orbits[13]; ~d15 = ~dirt.orbits[14];
		~d16 = ~dirt.orbits[15];
	);

Now, I’ve created some VSTPluginController that can be triggered from TidalCycles.

e.g.

SynthDef(\noisemaker, { | out, pan=0, n=0 |
var sound;
var env = EnvGen.kr(Env.asr(0.1, 1, 0.1), gate: 1, doneAction:2);
//sound = In.ar(out, ~dirt.numChannels);
sound = VSTPlugin.ar(sound, ~dirt.numChannels, pan, id: \noisemaker_vst) * env;
Out.ar(~mixBusCh8, DirtPan.ar(sound, ~dirt.numChannels, pan));
}).add;

~nmSynth = Synth(\noisemaker, target: ~genGrp);
~noisemaker_vst = VSTPluginController(~nmSynth, id: \noisemaker_vst);
~noisemaker_vst.open("/Library/Audio/Plug-Ins/VST3/TAL-NoiseMaker.vst3", editor: true, action: {
var controller = ~noisemaker_vst;
"TAL-NoiseMaker loaded successfully!".postln;
~dirt.soundLibrary.addSynth(\noisemaker,
(play: {
var midiChan = (~midichan ? 0).value;
var midiNote = (~midinote ? 60).value;
var velocity = ((~amp ? 0.8) * 127).value;

        if(controller.notNil) {
	       // NoiseMaker-specific parameters
            if(~noisemakercutoff.notNil) { controller.set("Filter Cutoff", ~noisemakercutoff) };
            if(~noisemakerresonance.notNil) { controller.set("Filter Resonance", ~noisemakerresonance) };
            if(~noisemakerattack.notNil) { controller.set("Amp Attack", ~noisemakerattack) };
            if(~noisemakerdecay.notNil) { controller.set("Amp Decay", ~noisemakerdecay) };
            if(~noisemakersustain.notNil) { controller.set("Amp Sustain", ~noisemakersustain) };
            if(~noisemakerrelease.notNil) { controller.set("Amp Release", ~noisemakerrelease) };
            if(~noisemakerfilterattack.notNil) { controller.set("Filter Attack", ~noisemakerfilterattack) };
            if(~noisemakerfilterdecay.notNil) { controller.set("Filter Decay", ~noisemakerfilterdecay) };
            if(~noisemakerfiltersustain.notNil) { controller.set("Filter Sustain", ~noisemakerfiltersustain) };
            if(~noisemakerfilterrelease.notNil) { controller.set("Filter Release", ~noisemakerfilterrelease) };
            if(~noisemakerfiltercontour.notNil) { controller.set("Filter Contour", ~noisemakerfiltercontour) };
            if(~noisemakerosc1vol.notNil) { controller.set("Osc 1 Volume", ~noisemakerosc1vol) };
            if(~noisemakerosc2vol.notNil) { controller.set("Osc 2 Volume", ~noisemakerosc2vol) };
            if(~noisemakerosc3vol.notNil) { controller.set("Osc 3 Volume", ~noisemakerosc3vol) };
            if(~noisemakerlfo1rate.notNil) { controller.set("Lfo 1 Rate", ~noisemakerlfo1rate) };
            if(~noisemakerlfo2rate.notNil) { controller.set("Lfo 2 Rate", ~noisemakerlfo2rate) };
            if(~noisemakerdetune.notNil) { controller.set("Master Detune", ~noisemakerdetune) };

            // Generic fallbacks
            if(~cutoff.notNil) { controller.set("Filter Cutoff", ~cutoff) };
            if(~resonance.notNil) { controller.set("Filter Resonance", ~resonance) };
            if(~attack.notNil) { controller.set("Amp Attack", ~attack) };
            if(~decay.notNil) { controller.set("Amp Decay", ~decay) };
            if(~sustain.notNil) { controller.set("Amp Sustain", ~sustain) };
            if(~release.notNil) { controller.set("Amp Release", ~release) };
            if(~filterattack.notNil) { controller.set("Filter Attack", ~filterattack) };

			[midiChan, midiNote, velocity].postln;  // Debug: see what values we're sending
			controller.midi.noteOn(midiChan, midiNote, velocity);

        }{
				 ">>> VST IS NIL! <<<".postln;
			};
    })
);

});

It is possible to controll the parameter of VST Synth, but I cannot apply SuperDirt effects on it.

If i uncomment this line:

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

I don’t hear anything anymore.

Now I’m puzzled how to route VST audio properly to be able to apply SuperDirt effects on VST Plugin audio and route the result through my mixbus to manipulate audio further.

Can someone help me to solve my issue?

Thanks.

Tagging @julian in case he has some advice on this

1 Like

i will go two steps back and implement the Basic Tidal-VST example before starting to integrate it in my existing setup. Maybe i‘ll find a Solution with this approach.

1 Like

I got sorted it out. I started with the implementation provided in TidalVST/TidalVST.scd at main · thgrund/TidalVST · GitHub and then integrated in my existing implementation. The issue I had seemed to be related how I created the synth. I was not using the control busses. Now, it works like a charm.