Little (an 80s glitchy thing with jazz chords)

I’m gearing up to do a big project soon; so, this is a “little” etude—if you will—in preparation. I’ve been studying Eli Fieldsteel’s tutorials for years, and have been studying Nathan Ho’s code recently. So shoutout to those guys for making Supercollider accessible to an amateur like me.

and here’s the code:

s.boot;

(
s.newBusAllocators;
~vbus = Bus.audio(s, 2);
s.freeAll;
)
(

SynthDef(\reverb, {
	var sig, in;
	in = \in.ar(0);
	sig = In.ar(in, 2);
	sig = Delay2.ar(sig);
	sig = FreeVerb.ar(sig, 0.75, 0.7, 0.3);
	sig = LPF.ar(sig, \cut.ar(2000));
	sig = LeakDC.ar(sig!2);
	Out.ar(0, sig);
}).add;

SynthDef(\bass, {
	var sig, freq, duration, cutoff, fxSend;
	fxSend = \fxSend.ar(0);
	duration = \duration.kr(1);
	cutoff = SinOsc.ar(XLine.ar(duration/2, duration*3, duration)).range(\lcut.ar(100), \hcut.ar(2000));
	freq = \freq.ar(440);
	sig = Saw.ar(freq * [-0.1, 0, 0.1].midiratio);
	sig = sig.sum * -7.dbamp;
	sig = MoogFF.ar(sig, cutoff);
	sig = sig * Env.perc(\atk.kr(0.01), duration, curve: -4).ar(Done.freeSelf);
	Out.ar(\out.ar(0), sig!2 * \amp.ar(1));
	Out.ar(\fx.ar(0), sig!2 * fxSend.dbamp);
}).add;

SynthDef(\kick, {
	var sig, freq;
	freq = \freq.ar(55);
	sig = SinOsc.ar(freq * [1, 2.1, 3.2, 4.5], Rand(0, 1), [1, 0.3, 0.2, 0.1]) * (1 + (3 * Env.perc(0, 1, curve: -8).ar));
	sig = sig * Env.perc(0.001, [0.51, 0.3, 0.2, 0.1], curve: 4).ar;
	sig = sig.sum;
	sig = sig * -10.dbamp;
	sig = sig + BPF.ar(Hasher.ar(Sweep.ar), 1250, 0.3, 0.3);
	sig = sig * Env.perc(0.001, 0.3, curve: -8).ar(Done.freeSelf);
	sig = Pan2.ar(sig, \pan.ar(0));
	Out.ar(\out.ar(0), sig * \amp.ar(0.5));
}).add;

SynthDef(\snare, {
	var sig, freq;
	freq = \freq.ar(255);
	sig = SinOsc.ar(freq * [1, 2.1, 3.2, 4.5], Rand(0, 1), [0.51, 0.3, 0.2, 0.1]) * (1 + (2 * Env.perc(0, 1, curve: -8).ar));
	sig = sig * Env.perc(0, [0.51, 0.3, 0.2, 0.1], curve: 4).ar;
	sig = sig.sum;
	sig = sig * -15.dbamp;
	sig = sig + BPF.ar(Hasher.ar(Sweep.ar), 2550, 0.7);
	sig = sig + BPF.ar(Hasher.ar(Sweep.ar), 5500, 0.7);
	sig = sig * Env.perc(0.001, 0.3, curve: -8).ar(Done.freeSelf);
	sig = Pan2.ar(sig, \pan.ar(-0.4));
	Out.ar(\out.ar(0), sig * \amp.ar(0.25));
}).add;

SynthDef(\hat, {
	var sig;
	sig = WhiteNoise.ar * (1 + (2 * Env.perc(0, 0.3, curve: -10).ar));
	sig = BPF.ar(sig, 8500, 0.5);
	sig = sig + BPF.ar(sig, 8500, 0.7);
	sig = sig * -10.dbamp;
	sig = sig * Env.perc(0.001, 0.3, curve: -8).ar(Done.freeSelf);
	sig = Pan2.ar(sig, {Rand(-0.5, 0.5)});
	Out.ar(\out.ar(0), sig * \amp.ar(0.45));
}).add;
)
/* TEST CODE
Synth(\kick);
Synth(\snare);
Synth(\hat);
Synth(\bass, [\freq, 36.midicps, \atk, 0.001, \duration, 0.1, \amp, 0.7, \out, 0, \fx, 0, \fxSend, -10]);

(
~test = Pbind(\instrument, \bass,
	\dur, (60/140)/4,
	\duration, 0.1,
	\atk, 0.001,
	\freq, (36+ Pseq([0, 10, 7, 3], 4)).midicps,
	\amp, Pseq([0.3, 0.26, 0.25, 0.27], inf),
	\fx, 0,
	\fxSend, -10
).play;
);
*/
(
var s, tempo, beat, map, pattern, pattern2, root;

s = Server.default;
s.freeAll;

s.bind{Synth(\reverb, [\in, ~vbus], s, \addToTail)};

tempo = 60/140;
beat = tempo/4;
root = 36;
map = Dictionary[
	$k -> \kick,
	$s -> \snare,
	$h -> \hat
];

~bassline0 = Pbind(\instrument, \bass,
	\dur, beat,
	\duration, beat,
	\atk, 0.001,
	\freq, (root + Pseq([0, 10, 7, 3], 8)).midicps,
	\amp, Pseq([0.3, 0.26, 0.25, 0.27], inf),
	\fx, 0,
	\fxSend, -10
);

~bassline1 = Pbind(\instrument, \bass,
	\dur, beat,
	\duration, beat,
	\atk, 0.001,
	\freq, ((root+1) + Pseq([0, 10, 7, 3], 8)).midicps,
	\amp, Pseq([0.3, 0.26, 0.25, 0.27], inf),
	\fx, 0,
	\fxSend, -10
);

~bassline2 = Pbind(\instrument, \bass,
	\dur, beat,
	\duration, beat,
	\atk, 0.001,
	\freq, ((root+5) + Pseq([2, 10, 5, 3], 8)).midicps,
	\amp, Pseq([0.3, 0.26, 0.25, 0.27], inf),
	\fx, 0,
	\fxSend, -10
);
~bassline3 = Pbind(\instrument, \bass,
	\dur, beat,
	\duration, beat,
	\atk, 0.001,
	\freq, ((root+6) + Pseq([0, 10, 4, 3], 8)).midicps,
	\amp, Pseq([0.3, 0.26, 0.25, 0.27], inf),
	\fx, 0,
	\fxSend, -10
);

~mel0 = Pbind(\instrument, \bass,
	\dur, beat,
	\duration, beat,
	\freq, ((root+36) + Prand([0, 3, 5, 7, 10], 32)).midicps,
	\amp, Pseries(0.1, 0.01, 32),
	\lcut, 2000,
	\hcut, 2500,
	\fx, ~vbus,
	\fxSend, -15
);
~mel1 = Pbind(\instrument, \bass,
	\dur, beat,
	\duration, beat,
	\freq, ((root+29) + Prand([2, 3, 5, 7, 9], 32)).midicps,
	\amp, Pseries(0.5, -0.01, 32),
	\lcut, 1000,
	\hcut, 2000,
	\fx, ~vbus,
	\fxSend, -15
);
~mel2 = Pbind(\instrument, \bass,
	\dur, beat,
	\duration, beat,
	\freq, ((root+31) + Prand([0,1, 3, 4, 6, 8, 10], 128)).midicps,
	\amp, Pseries(0.1, 0.01, 32),
	\lcut, 5000,
	\hcut, 10000,
	\fx, ~vbus,
	\fxSend, -15
);
pattern = "
k.k.s..s..k.s...
khkhshhshhkhshhh
";

pattern2 = "
khkhsk.hhhkhs..k
khkhshhhssssssss
";

Routine({
	2.do{ |count = 0|
		2.do{
			if(count == 1) {
			~mel0.play;
		};
			~bassline0.play;
			[0, 15, 7].do{|note|
				s.bind{Synth(\bass, [
					\freq, (root + note).midicps,
					\duration, (16*beat),
					\atk, 0.3,
					\out, 0,
					\fx, ~vbus,
					\fxsend, -5,
				])};
			};
			pattern.do{|character|
				if(character == $.){
					beat.wait;
				} {
					if(map[character].notNil) {
						s.bind{Synth(map[character]);};
						beat.wait;
					};
				};
			};
			~bassline1.play;
			[1, 16, 8].do{|note|
				s.bind{Synth(\bass, [
					\freq, (root + note).midicps,
					\duration, (16*beat),
					\out, 0,
					\fx, ~vbus,
					\fxsend, -1
				])};
			};
			pattern2.do{|character|
				if(character == $.){
					beat.wait;
				} {
					if(map[character].notNil) {
						s.bind{Synth(map[character]);};
						beat.wait;
					};
				};
			};
		};
		1.do{
			if(count == 1) {
			~mel1.play;
		};
			~bassline2.play;
			[0, 15, 7].do{|note|
				s.bind{Synth(\bass, [
					\freq, ((root+5) + note).midicps,
					\duration, (16*beat),
					\out, 0,
					\fx, ~vbus,
					\fxsend, 1
				])};
			};
			pattern.do{|character|
				if(character == $.){
					beat.wait;
				} {
					if(map[character].notNil) {
						s.bind{Synth(map[character]);};
						beat.wait;
					};
				};
			};
			~bassline3.play;
			[1, 15, 7].do{ |note|
				s.bind{Synth(\bass, [
					\freq, ((root+5) + note).midicps,
					\duration, (16*beat),
					\out, 0,
					\fx, ~vbus,
					\fxsend, 0
				])};
			};
			pattern2.do{|character|
				if(character == $.){
					beat.wait;
				} {
					if(map[character].notNil) {
						s.bind{Synth(map[character]);};
						beat.wait;
					};
				};
			};
		};
		1.do{
			if(count == 1) {
				~mel2.play;
			};
			[0, 16, 7, 10].do{ |note|
				s.bind{Synth(\bass, [
					\freq, ((root + 7) + note).midicps,
					\atk, 0.3,
					\duration, (64*beat),
					\out, 0,
					\fx, ~vbus,
					\fxsend, -1
				])};
			};
			pattern.do{|character|
				if(character == $.){
					beat.wait;
				} {
					if(map[character].notNil) {
						s.bind{Synth(map[character]);};
						beat.wait;
					};
				};
			};
			pattern2.do{|character|
				if(character == $.){
					beat.wait;
				} {
					if(map[character].notNil) {
						s.bind{Synth(map[character]);};
						beat.wait;
					};
				};
			};
		};
		count = count + 1;
	};
	//end
	s.bind{Synth(\bass, [
		\freq, root.midicps,
		\duration, (64*beat),
		\lcut, 250,
		\hcut, 1000,
		\amp, 0.5,
		\out, 0,
		\fx, 0
	])};

	[0, 15, 7].do{|note|
		s.bind{Synth(\bass, [
			\freq, (root+note).midicps,
			\duration, (64*beat),
			\out, 0,
			\fx, ~vbus,
			\fxsend, 2,
			\lcut, 750,
			\hcut, 5000,
			\amp, 0.5
		])};
	};
}).play;
)
1 Like