SC vs Modular Synths (Eurorack)

the sophistication of the supercollider pattern library can be leveraged to sequence control voltages pretty neatly:

I think this is an interesting discussion. It is inspiring to think of how much is actually possible to do with SuperCollider.

Like other users have stated, analog modular synthesizers are known for producing a warmer, fuller sound. At the same time, according to experts in the field of physical modelling it is possible to reproduce these sounds within the digital domain.

I think that the software synthesizer Tassman from Applied Acoustics, now sadly deprecated, was an interesting example of this. It is also worth noting, that Tassman bears a lot of resemblance with the synthesizer Modalys, which is featured in the Computer Music Tutorial (under the name MOSAIC) and is developed by IRCAM.

If you follow the link below, you can read a Q&A with one of the creators of that software. I was asking myself the same question as you did, and this interview shed some light on the subject.
Applied Acoustics Tech Talk

Kind regards,
Tim

hi @capogreco ,
what kind of “messages” do you send to the es-8 from supercollider ?

do you have a small example script ?
thanks !

so far I’ve been outputting CV using these synths:

SynthDef (\trigger) {
	arg out = 0;
	var env = Env.step (1.asArray, SampleDur.ir.asArray);
	env = EnvGen.ar (env, doneAction: 2);
	Out.ar (out, env);
}.add;

SynthDef (\static_value) {
	arg out = 0, volts = 0, lag_time = 1, lag_on = 0;
	var sig, lag_sig;
	sig = Lag.kr (volts * 0.097, 0);
	sig = K2A.ar (sig);
	lag_sig = Lag3.ar (sig, lag_time);
	sig = SelectX.ar (lag_on, [ sig, lag_sig ]);
	Out.ar (out, sig);
}.add;

SynthDef (\ramp) {
	arg out = 0, start_value = 0, end_value = 1, time = 1, curve = 0;
	var env = Env.new ([ start_value, end_value ], time, curve);
	env = EnvGen.ar (env, doneAction: 2);
	Out.ar (out, env);
}.add;

the example I posted above used this code for sequencing:

(
var change_func = {
	var new_note_array, new_lag_array;
	new_note_array = (0..11).euclidify (7, 5).postln.euclidify (5, 5.rand).scramble;
	new_note_array = new_note_array + ([ 12 ] ++ (0!4)).scramble;
	new_lag_array = 2 + 10.rand;
	new_lag_array = Array.euclid (new_lag_array, 1 + new_lag_array.rand.half.floor, new_lag_array.rand).postln;
	Pbindef (\p_3,
		\note_array, new_note_array,
		\lag_on_array, new_lag_array,
	);
	Pbindef (\p_5,
		\on_array, Array.euclid (8, 3, 8.rand),
	);
};

Pbindef (\changer,
	\type, \set,
	\delta, 16,
	\change_func, Pfunc { change_func.value },
);

// bld
Pbindef (\bld).clear;
Pbindef (\bld,
	\delta, 1,
	\volts, Pseq ((-4!16) ++ (0!16), inf) / 12,
);

// chan 0
Pdef (\bld_trig) {
	Pbind (
		\instrument, \trigger,
		\out, 0,
	);
};
Pdef (\chan_0) { Pbindef (\bld_trig) <> Pbindef (\bld) };

// chan 1
Pdef (\bld_cv) {
	Pmono (\static_value,
		\out, 1,
	);
};
Pdef (\chan_1) { Pbindef (\bld_cv) <> Pbindef (\bld) };

// chan 2
Pbindef (\p_2).clear;
Pbindef (\p_2,
	\out, 2,
	\instrument, \ramp,
	\delta, 16,
	\curve, 16,
	\time, Pkey (\delta) * Pfunc { TempoClock.beatDur },
	\start_value, 0,
	\end_value, 1,
);
Pdef (\chan_2) { Pbindef (\p_2) };

// chan 3
Pbindef (\p_3).clear;
Pbindef (\p_3,
	\type, \set,
	\delta, 1 / 3,
	\out, 3,
	\note_array, [ 0, 3, 7, 10 ],
	\volts, Pkey (\note_array).composeBinaryOp (\wrapAt, Pseries ()) / 12,
	\lag_time, Pkey (\delta) * Pfunc { TempoClock.beatDur },
	\lag_on_array, [ 1, 0, 0, 0 ],
	\lag_on, Pkey (\lag_on_array).composeBinaryOp (\wrapAt, Pseries ()),
);
Pdef (\chan_3) { Pmono (\static_value) <> Pbindef (\p_3) };

// chan 4
Pbindef (\p_4).clear;
Pbindef (\p_4,
	\out, 4,
	\instrument, \ramp,
	\delta, 1,
	\start_value, Pwhite (-1.0, 1.0),
	\end_value, Pwhite (-1.0, 1.0),
	\time, Pkey (\delta) * Pfunc { TempoClock.beatDur },
);
Pdef (\chan_4) { Pbindef (\p_4) };

// chan 5
Pbindef (\p_5).clear;
Pbindef (\p_5,
	\out, 5,
	\instrument, \ramp,
	\delta, 1,
	\on_array, Array.euclid (8, 3, 0),
	\ramp_on, Pkey (\on_array).composeBinaryOp (\wrapAt, Pseries ()),
	\start_value, 1 * Pkey (\ramp_on),
	\end_value, 1 * Pkey (\ramp_on),
	\time, Pkey (\delta) * Pfunc { TempoClock.beatDur },
);
Pdef (\chan_5) { Pbindef (\p_5) };

TempoClock.tempo_ (107 / 60);
Pdef (\chan_0).play;
Pdef (\chan_1).play;
Pdef (\chan_2).play;
Pdef (\chan_3).play;
Pdef (\chan_4).play;
Pdef (\chan_5).play;
Pbindef (\changer).play;
)

but if you wanted to run it, you’d also need a few externals:

// http://cgm.cs.mcgill.ca/~godfried/publications/banff.pdf

+ SequenceableCollection {
	*euclid {
		arg length = 12, fill = 7, rotation = 0;
		var obj, euclid_func;
		euclid_func = {
			arg array_1, array_2;
			if (array_1.size > array_2.size) {
				array_2.do { |element, i|
					array_2[i] = array_1.pop ++ element;
				};
			} {
				array_1.do { |element, i|
					array_1[i] = element ++ array_2.pop;
				};
			};
			if (array_1.size > 0) {
				euclid_func.value (array_2, array_1);
			} { array_2.flatten };
		};
		obj = euclid_func.value ([ 1 ]!fill, [ 0 ]!(length - fill)).rotate (rotation);
		^obj
	}

	euclidify { | fill, rotation |
		var euc_array, new_array;
		new_array = [];
		euc_array = Array.euclid (this.size, fill, rotation);
		euc_array.do { | item, i |
			if (item.asBoolean) {
				new_array = new_array.add (this[i]);
			};
		};
		^new_array;
	}
}

Thank you @capogreco,
I will have a deeper look into your code later.

Just one more quick practical question,
how do you make the connection from your laptop to the es-8,
is there an external soundcard in between or is that direct lineout from laptop?
( Sorry, it wasn’t immediately clear in the video )

from the expert sleepers website:

The ES-8 is a USB 2.0 class-compliant audio interface in a Eurorack module, with DC-coupled inputs and outputs that can be used for both CVs and audio.

the module connects via USB-B:

1 Like

You can also connect it via adat to your audio interface. Works great.

Sam

The key advantage of digital over analog is scalability. When you can make a virtual sounding object and then say “give me choir of them”, there is hardly anything that can beat it for composer. So if you approach music theoretically, you will go SC, PD, Csound, etc. But if you want a “toy” to play with, then analog instruments are very good, and especially those with mechanical control. Good music can be made both ways. But if for digital to gain analog coolness is a matter of cpu power and algorithm availability, for analog - scalability is very limited.

1 Like

The ability to immediately change the system in physically infeasible ways is pretty huge too. Variables and functions > patch cables, multiples, utility modules, etc.

Stravinsky: The artist is truly free when under constraints. (Or something like that.)

Analog synthesis is about (ab)using limited resources extremely, extremely cleverly.

I’m not good at it :laughing:

hjh

1 Like

Well, he used orchestra and Dyagylev’s resources. That’s an early version of SCying :stuck_out_tongue_winking_eye:

:wink:

What I’m getting at is, there’s a kind of casual assumption that more is better. But I find just as often, when I can create 20-30 instruments and players, the texture can easily become overloaded and unfocused. There’s a kind of discipline that comes from controlling the number of distinct elements. Analog modular uses money as the constraint (it’s not “how many oscillators do you want?” but rather “how many can you afford?”).

I still like SC better, but I don’t think it’s right to say that analog is a toy because the components are physically limited. It’s rather a matter of different technology and different ways of thinking.

hjh

1 Like

PS Ask Andrew Huang how many he can afford :astonished:

hjh

1 Like

Absolutely, it’s a common mind trap in aesthetical regard which often goes along with new vs. old options. Orchestra is not “better” than string quartet, 36 speakers are not “better” than 4, digital is not “better” than analog, electroacoustic is not “better” than instrumental-acoustic. It’s always just more and/or other possibilities, there might be good reasons to decide for the more/other/new possibilties if you think that there are higher chances that something new and interesting can be achieved (the crucial and unseizable point) but there might be good reasons to stay with (some) constraints too. Saying this as someone who slowly switched from the instrumental to the digital domain.

The “toy” assumption comes from how people usually use analog modular systems these days. I think this actually is key factor in their popularization today. It’s kind of fetish, and I feel it, I’m a violinist after all, I like nice sounding toys. And Andrew looks just like the guy who plays with nice sounding toys. It’s all good. But if you want the freedom of defining your own constraints - digital is the way to go.

I can see your point – but, if analog is to be judged by “how people usually use it,” then digital audio programming environments should likewise be judged by their typical usage. For that, – be honest – by the numbers, Max and Pd are far more typical than SC.

One of the use cases mentioned here for digital audio is the use of iteration to simplify additive synth structures, e.g. Array.fill(100, { ... oscillator variant... }).sum. Dataflows are famously bad at this – e.g. [1] tells you how to detune oscillators in Max by literally creating three oscillators by hand, and amplitude scaling and mixing them by hand. So if you look at typical digital audio programming, you might conclude that it also has a scalability problem, in terms of mouse clicks instead of money (which is improved in specialized, but much less popular tools – just as analog possibilities are greatly expanded by specialized modules).

One point in common between analog and digital is the astonishment of creating something that “should” be impossible, given the equipment. Like, I know someone here in GZ who plays ambient music on his modular rig, about as big as a couple of shoe boxes. Kinda blows my mind what he’s able to get out of a setup that is really not that large. It also startles people when I get music out of an off-the-shelf laptop, a Nanokontrol and a moderate amount of typing. I see it as different sides of the same coin.

hjh

[1] https://music.arts.uci.edu/dobrian/maxcookbook/detuning-oscillators-max

Max 8 introduced MC to simplify this. I had fun building a mediocre reverb in it. That said, I still prefer using SC code for this type of thing.

This idea is almost exactly what got me into SC :slight_smile:

I think its important that the digital space includes a lot of free tools made by many hands. Literature has always been an ‘empire of letters’ which can contain and reply to each other - in the digital age music and video gained a similar discursive character and that’s cool and democratic. I think folks should step back from cultural forms that have a super high cost of admission, whether that means fancy schools or fancy gear…

Interesting discussion, thanks everybody!

I think it’s important to separate my mental biases from any value judgments about different ways of working. I like SC’s way of doing things, and I don’t like Max/Pd’s way of doing things. But, I’ve seen students express some interest in SC and then get overwhelmed by the code – and I’ve also seen students, quite unexpectedly, play with Pd a little, and then take the ball and run with it further than I would have guessed. So it doesn’t matter what I like or don’t like – it’s what works for the person. I find it really perplexing how modular gear handles logic through CVs, triggers and gates – but my lack of understanding doesn’t mean that analog is “less powerful” or such… just different, and those differences will appeal to some people who might look at SC and think it’s completely bonkers. They’re all toys.

The arguments get into trouble when they start saying that one or the other is better. E.g., a “super high cost of admission” – all of us depend on spare time, which is a/ becoming more expensive in general and b/ much less available to segments of society that are traditionally disadvantaged (or discriminated against) economically. If you choose to spend the money you have buying modules or you choose to spend the free time you have coding modules – to me, it’s 6 vs the half dozen, because none of that matters if you’re working 3 part-time jobs to support kids. (Even so, economics are one of the reasons why I’m committed to digital audio programming.)

@license thanks for the link on Max 8. About time somebody did something about that.

hjh

Reviving this thread to ask a related question.

I’m trying to use supercollider as a MIDI to CV coverter. This is the code I’m using:

MIDIdef.noteOn(\midi,
	{
		|vel,nn|
		var offset=60, note_per_oct=12, max_voltage=4.75;
		var volt = nn - offset / note_per_oct / max_voltage;
		Ndef(\cv,{ var cv = DC.ar(volt); Out.ar(0,cv)});
	}

);

This works great with correct tuning and everything. But there’s a very large latency, I estimate around 100-200 ms. I have tried changing the blockSize, but that didn’t help.

Is there an inherent latency to using Ndef? I tried using a SynthDef instead, but for whatever reason it refused to work.

There’s no latency when I use BitWig’s MIDI to CV device. So I know either SC or my code is causing the latency.

Any ideas what could be causing this?