Sending continuous CV and Gate signals to a modular synth

This week I fought an epic battle that boiled down to not understanding the difference between Symbols and strings. Main take-away is that if you define an Ndef with a string for a name, you'll never be able to access it again, since each string has a unique address.

In the end though I was able to export a bunch of CV and gate synths to tidal. Here's the code I added to startup.scd:

(
	~dirt.orbits.do({ | orbit, i |
		var chans, cvtag, gatetag;
		chans = ~dirt.numChannels;

		// CV synths

		cvtag=('cv_np'++i).asSymbol;

		Ndef(cvtag, { DC.ar }); // force the NP to audio rate
		Ndef(cvtag, { | freq = 440, lag=0.01 |
			var lagFreq = Lag.kr(freq, lagTime: lag);
			LinLin.ar( log2(lagFreq/440), -1, 9, 0, 1);
		});

		~dirt.soundLibrary.addSynth(('cv'++i).asSymbol, (play: {
			Ndef(cvtag).wakeUp; // make sure the Ndef runs
			Ndef(cvtag).set(\freq, ~freq);
		}));

		~dirt.soundLibrary.addSynth(('cv'++i++'_lag').asSymbol, (play: {
			Ndef(cvtag).wakeUp; // make sure the Ndef runs
			Ndef(cvtag).set(\lag, ~n);
		}));

		~dirt.soundLibrary.addSynth(('cv'++i++'_on').asSymbol, (play: {
			Ndef(cvtag).play(i*chans);
		}));

		~dirt.soundLibrary.addSynth(('cv'++i++'_off').asSymbol, (play: {
			Ndef(cvtag).stop;
		}));

		// gate synths

		gatetag = ('gate_np' ++ i).asSymbol;

		Ndef(gatetag, { DC.ar }); // force the NP to audio rate
		Ndef(gatetag, { | level = 0, lag=0.01 |
			var lagLevel = Lag.kr(level, lagTime: lag);
			LinLin.ar( lagLevel, 0, 1, 0, 0.5);
		});

		~dirt.soundLibrary.addSynth(('gate'++i).asSymbol, (play: {
			Ndef(gatetag).wakeUp; // make sure the Ndef runs
			Ndef(gatetag).set(\level, ~n);
		}));

		~dirt.soundLibrary.addSynth(('gate'++i++'_lag').asSymbol, (play: {
			Ndef(gatetag).wakeUp; // make sure the Ndef runs
			Ndef(gatetag).set(\lag, ~n);
		}));

		~dirt.soundLibrary.addSynth(('gate'++i++'_on').asSymbol, (play: {
			Ndef(gatetag).play(i*chans+1);
		}));

		~dirt.soundLibrary.addSynth(('gate' ++i++'_off').asSymbol, (play: {
			Ndef(gatetag).stop;
		}));

	});
)

This can be controlled in Tidal like so:

-- turn on cv0, this starts a continuous DC output on channel 0
once $ s "cv0_on"

-- turn on gate0
once $ s "gate0_on"

-- simple cv pattern
d1 $ n "a6 a5 a6 a5" # s "cv0" 

-- separate gate pattern   
d2 $ n "[1 0]*4" # s "gate0"

-- you can also pattern portamento
d3 $ n "0.01 0.5" # s "cv0_lag"

Here's the result. The red line is cv0 and the green is gate0:

Screen Shot 2023-01-24 at 3.37.48 PM

There is a pretty big problem, however. There's some jitter in the start times of each note. You can see it more clearly when you overlay a simple beat pattern from tidal on top of the CV signal.

d4 $ "bd bd" # channel 2

result with cv0 in blue (no lag) and the bass drum pattern in green:

Screen Shot 2023-01-24 at 3.43.25 PM

I think this may have something to do with sample offsets in tidal / superdirt. I haven't started investigating it yet, but for now, these CV synths aren't usable.

5 Likes