MM – Synth Arrays and routine iterations.

This one shows how to launch multiple synths using Arrays and iterate over the array to change parameters.

You’ll need this file (you can use your own)

https://drive.google.com/open?id=1qIVBwIhT5ZVZp5zKATAPuvf81BZwJCXF

//Synth Arrays and routine testing. 2020 - Matias Monteagudo.

//////////////////////////////////////////////////////////////////////////////////////////////////////
//Server settings. Change at will if needed, otherwise just boot.

(
Server.local.options.device = "ASIO : ASIO PreSonus FireStudio";
Server.local.options.sampleRate=48000;
Server.local.options.hardwareBufferSize=128;
)

//////////////////////////////////////////////////////////////////////////////////////////////////////
//Reverb. Will create a verb and refresh the node tree. Keep an eye on the Node tree window.
(
(
SynthDef(\verb, {
	|in, predelay=1, revtime=2, lpf=4500,mix=0.5,amp=1,out=0|
	var dry,wet,temp,sig;
	dry = In.ar(in, 2);
	temp = In.ar(in, 2);
	wet=0;
	temp=DelayN.ar(temp, 0.2, predelay);
	32.do {temp=AllpassN.ar(temp, 0.05, {Rand(0.001,0.05)}!2,revtime);
		temp=LPF.ar(temp,lpf);
		wet=wet+temp;
	};
	sig=XFade2.ar(dry,wet,mix*2-1,amp);
	Out.ar(out,sig);
}).add;
);

(
ServerTree.removeAll;
~revBus = Bus.audio(s,2);
~createReverb={~reverbSynth=Synth(\verb, [\mix,0.23, \in, ~revBus])};
ServerTree.add(~createReverb);
s.freeAll;
);
)

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Synth.
(
(
d=Buffer.readChannel(s,"C:/Audio/VCV/Mat VCV/Guitar 1.wav",channels:0);
e=Buffer.readChannel(s,"C:/Audio/VCV/Mat VCV/Guitar 1.wav",channels:1);
);

(
SynthDef(\gloop2,{
	| tfq=0.01,vel=1,freq=1,pos=0,apos=0,pmean=0,gate=1,bal=1, vol=1,bend=0,lpCutoff=10000,lpRes=0,hpCutoff=30,hpRes=0|
	var sig, env, sigL, sigR ,ggt, env2;
	ggt = Impulse.kr(tfq);
	sigL = GrainBuf.ar(1,ggt,1/tfq*2,d,freq* bend.midiratio,(Latch.ar(WhiteNoise.ar(0.5,0.5),ggt)*pmean)+(LFTri.ar(0.05,0,0.5)*apos)+pos,4,mul:0.5);
	sigR = GrainBuf.ar(1,ggt,1/tfq*2,e,freq* bend.midiratio,(Latch.ar(WhiteNoise.ar(0.5,0.5),ggt)*pmean)+(LFTri.ar(0.05,0,0.5)*apos)+pos,4,mul:0.5);
	env = EnvGen.ar(Env([0,vel,vel,0],[0.01,1/tfq-0.02,0.01]), ggt);
	env2= EnvGen.ar(Env.adsr(0.005, 0.005,1,0.1,vel,[-10,10]),gate,doneAction:2);
	bal = Balance2.ar(sigL,sigR,Latch.ar(WhiteNoise.ar(1),ggt)*bal,vol);
	sig=LPF18.ar(bal,lpCutoff.lag(2),lpRes);
	sig=RHPF.ar(sig, hpCutoff.lag(2), hpRes* -1+1);
	Out.ar(~revBus, (sig*env)*env2)
}).add;
);

)

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Test your buffer so you know how the original source sounds
{Out.ar(~revBus,  [   PlayBuf.ar(1,d,1,doneAction:2), PlayBuf.ar(1,e,1,doneAction:2)  ]  )}.play;
//////////////////////////////////////////////////////////////////////////////////////////////////////
//Iterations

//Executes an array of synth instances with a ranged random choice for grain size, all inside a group. You can even interpret this without freeing first and instances will not pile up.
//Keep an eye on the node tree.

//3 nodes.
(
~gr1.free;//To free the group before restarting
~gr1=Group.new;//Creates new group
l = Array.fill(3,{
	~s=Synth(\gloop2,[\vel,0.7,\out,0,\tfq,rrand(0.02,5)],~gr1,addAction:\addToHead).register;
});
)

// 10 nodes
(
~gr1.free;//To free the group before restarting
~gr1=Group.new;//Creates new group
l = Array.fill(10,{
	~s=Synth(\gloop2,[\vel,0.7,\out,0,\tfq,rrand(0.02,5)],~gr1,\addToHead).register; //Note we need to register the synths, otherwise the conditional "if" on the Routines will not work.
});
)

//40 nodes.
(
~gr1.free;//To free the group before restarting
~gr1=Group.new;//Creates new group
l = Array.fill(40,{
	~s=Synth(\gloop2,[\vel,0.5,\out,0,\tfq,rrand(0.02,5)],~gr1,\addToHead).register;
});
)

//100 nodes.
(
~gr1.free;//To free the group before restarting
~gr1=Group.new;//Creates new group
l = Array.fill(100,{
	~s=Synth(\gloop2,[\vel,0.2,\out,0,\tfq,rrand(0.02,5)],~gr1,\addToHead).register;
});
)

~gr1.freeAll//This will free the nodes without freeing the group.

//////////////////////////////////////////////////////////////////////////////////////////////////////
//Routines to iterate on all the present nodes and change some parameters. (try first on the Array with 10 nodes)

//This changes the grain size and freq (octaves).
(
~routine.stop;
~routine = Routine({
	inf.do({
		l.do({ arg node;
			if(~s.isPlaying, {
				node.set(\tfq, rrand(0.02,22).debug("Grain size"));
				node.set(\pos, 0);
				node.set(\apos,0.6);
				node.set(\freq,rrand(-1,2).debug("Pitch"));
			});
			0.2.wait;
		});
	})
});
~routine.play;
)

//This will produce bigger grains. Rhythm is more steady. (fades in slower)
(
~routine.stop;
~routine = Routine({
	inf.do({
		l.do({ arg node;
			if(~s.isPlaying, {
				node.set(\tfq, 0.05);
				node.set(\apos,0);
				node.set(\pmean,0);
				node.set(\pos, 0);
				node.set(\freq,rrand(-1,2).debug("Pitch"));
				node.set(\hpCutoff, 20);
				node.set(\hpRes, 0);
			});
			0.2.wait;
		});
	});
});
~routine.play;
)

//This will also modulate filter and resonance.
(
~routine.stop;
~routine = Routine({
	inf.do({
		l.do({ arg node;
			if(~s.isPlaying, {
				node.set(\tfq, 0.4);
				node.set(\apos,0);
				node.set(\pmean,1);
				node.set(\pos, 0.5);
				node.set(\freq, rrand(-1,2).debug("Pitch"));
				node.set(\hpCutoff, rrand(100,3000).debug("HPCutoff"));
				node.set(\hpRes, rrand(0,0.82).debug("Res"));
			});
			0.2.wait;
		});
	});
});
~routine.play;
)

// This will alter the starting points. Rhythm becomes more syncopated as the sample loops are phased from eachother. Creates clusters when used with 40 nodes.
(
~routine.stop;
~routine = Routine({
	inf.do({
		l.do({ arg node;
			if(~s.isPlaying, {
				node.set(\tfq, 0.1);
				node.set(\apos,0);
				node.set(\pmean,0);
				node.set(\pos, rrand(0.0,1).debug("Position"));
				node.set(\freq,rrand(-1,2).debug("Pitch"));
				node.set(\hpCutoff, 20);
				node.set(\hpRes, 0);
			});
			0.2.wait;
		});
	})
});
~routine.play;
)


//(Pseudo)Transposition.
(
~routine.stop;
~routine = Routine({
	inf.do({
		l.do({ arg node;
			if(~s.isPlaying, {
				node.set(\tfq,rrand(0.02,12).debug("Grain size"));
				node.set(\pmean,rrand(0.0,1).debug("Position meander"));
				node.set(\pos, rrand(0.000,1).debug("Position"));
				node.set(\freq, ([1, 2].choose+0.065).debug("Pitch"));
				node.set(\hpCutoff, 20);
				node.set(\hpRes, 0);
			});
			0.2.wait;
		});
	})
});
~routine.play;
)

//This one produces a deep chord Drone.
(
~routine.stop;
~routine = Routine({
	inf.do({
		l.do({ arg node;
			if(~s.isPlaying, {
				node.set(\tfq,rrand(0.02,6).debug("Grain size"));
				node.set(\pmean,rrand(0,1).debug("Position meander"));
				node.set(\freq,[-0.35,0.35,0.70,0.835].choose.debug("Pitch"));
				node.set(\hpCutoff, 20);
				node.set(\hpRes, 0);
			});
			0.2.wait;
		});
	})
});
~routine.play;
)

//This one produces random pitches.V1
(
~routine.stop;
~routine = Routine({
	inf.do({
		l.do({ arg node;
			if(~s.isPlaying, {
				node.set(\tfq,rrand(0.02,6).debug("Grain size"));
				node.set(\pmean,rrand(0.0,1).debug("Position meander"));
				node.set(\freq,rrand(0.5,1.5).debug("Pitch"));
				node.set(\hpCutoff, 20);
				node.set(\hpRes, 0);
			});
			0.2.wait;
		});
	})
});
~routine.play;
)

//This one produces random pitches. V2
(
~routine.stop;
~routine = Routine({
	inf.do({
		l.do({ arg node;
			if(~s.isPlaying.postln, {
				node.set(\tfq,rrand(0.02,6).debug("Grain size"));
				node.set(\pmean, rrand(0.0,1).debug("Position meander"));
				node.set(\freq,rrand(0.1,1.1).debug("Pitch"));
				node.set(\hpCutoff, rrand(100,900).debug("HPCutoff"));
				node.set(\hpRes, rrand(0,0.4).debug("Res"));
			});
			0.2.wait;
		});
	})
});
~routine.play;
)

//This one produces random pitches. V3
(
~routine.stop;
~routine = Routine({
	inf.do({
		l.do({ arg node;
			if(~s.isPlaying, {
				node.set(\tfq,rrand(0.02,6).debug("Grain size"));
				node.set(\pmean,rrand(0.0,1).debug("Position meander"));
				node.set(\freq,rrand(0.5,2.1).debug("Pitch"));
				node.set(\hpCutoff, rrand(100,800).debug("HPCutoff"));
				node.set(\hpRes, rrand(0,0.82).debug("Res"));
			});
			0.2.wait;
		});
	})
});
~routine.play;
)

//This one produces random pitches. V4
(
~routine.stop;
~routine = Routine({
	inf.do({
		l.do({ arg node;
			if(~s.isPlaying, {
				node.set(\tfq,rrand(0.02,6).debug("Grain size"));
				node.set(\pmean,rrand(0.0,1).debug("Position meander"));
				node.set(\freq,rrand(1.5,3.1).debug("Pitch"));
				node.set(\hpCutoff, rrand(100,3000).debug("HPCutoff"));
				node.set(\hpRes, rrand(0,0.82).debug("Res"));
			});
			0.2.wait;
		});
	})
});
~routine.play;
)

~routine.stop; //To stop any running routine.
Author
418 PM
  • Platform:
  • Category: Other Utility
  • Revision: 1.2 changed postln to debug lines
  • License: GNU General Public License family
  • Views: 154
  • Modified: 5 months ago
Chat about this patch on Discord!
Appreciate

Leave a Reply