Example Class
2016-05-04 23:30
supercollider
Here is a very basic SuperCollider class I wrote as an example of why and how to write classes.
//save this as MySequencerTrack.sc in your extensions folder and recompile
MySequencerTrack {
var <steps;
var <>array;
*new {|steps= 16|
^super.newCopyArgs(steps).init;
}
init {
array= Array.fill(4, {Array.fill(steps, 0)}); //4 here because of the four params: amp, freq, mod, pan
}
//array get/set
amps {^array[0]}
amps_ {|arr| array[0]= arr}
freqs {^array[1]}
freqs_ {|arr| array[1]= arr}
mods {^array[2]}
mods_ {|arr| array[2]= arr}
pans {^array[3]}
pans_ {|arr| array[3]= arr}
//single value get/set
amp {|index| ^array[0][index]}
amp_ {|index, val| array[0].put(index, val)}
freq {|index| ^array[1][index]}
freq_ {|index, val| array[1].put(index, val)}
mod {|index| ^array[2][index]}
mod_ {|index, val| array[2].put(index, val)}
pan {|index| ^array[3][index]}
pan_ {|index, val| array[3].put(index, val)}
}
And here is some test code for it...
a= MySequencerTrack.new;
a.freqs
a.steps
a.amps= {1.0.rand}!a.steps
a.amps
a.amp(10) //first one
//and then the same for a.freqs etc
(
s.waitForBoot{
a.amps= {[0.5, 0.25, 0, 0, 0].choose}!a.steps;
a.freqs= {[60, 66, 70].choose.midicps}!a.steps;
a.mods= {1.0.linrand}!a.steps;
a.pans= {1.0.rand2}!a.steps;
b= {|freq= 400, amp= 0, mod= 0, pan= 0| Pan2.ar(SinOsc.ar(freq, SinOsc.ar*mod, amp), pan)}.play;
s.sync;
r= Routine.run({
inf.do{
a.steps.do{|i|
b.set(\freq, a.freq(i), \amp, a.amp(i), \mod, a.mod(i), \pan, a.pan(i));
0.125.wait;
};
};
});
};
)
//and while it is running... replace freqs
a.freqs= {[52, 66, 70, 80].choose.midicps}!a.steps;
a.amp_(0, 1) //set first amp to 1.0
a.amps
a.amps= a.amps.rotate(-1) //rotate amps left
a.freqs= a.freqs.rotate(2) //rotate freqs right
a.freqs= a.freqs+10 //transpose up
a.freqs= a.freqs.scramble //reorder
r.stop
b.free
//now the important thing and why classes are good...
//here we make 10 tracks all 32 values in length...
~mysequencer= {MySequencerTrack(32)}!10;
~mysequencer[0].amps //amplitudes for first track
~mysequencer[0].amps= {1.0.rand}!a.steps
~mysequencer[0].amps
~mysequencer[0].amp(0) //first one
(
s.waitForBoot{
10.do{|i|
var steps= ~mysequencer[i].steps;
~mysequencer[i].amps= {[0.5, 0.25, 0, 0, 0, 0, 0, 0].choose}!steps;
~mysequencer[i].freqs= {[60, 66, 70, 90].choose.midicps}!steps;
~mysequencer[i].mods= {1.0.linrand}!steps;
~mysequencer[i].pans= {1.0.rand2}!steps;
};
~synths= {
{|freq= 400, amp= 0, mod= 0, pan= 0| Pan2.ar(SinOsc.ar(freq, SinOsc.ar*mod, amp/2), pan)}.play;
}!10;
s.sync;
r= ~mysequencer.collect{|trk, i|
var syn= ~synths[i];
Routine.run({
inf.do{|j|
var x= j%trk.steps;
syn.set(\freq, trk.freq(x), \amp, trk.amp(x), \mod, trk.mod(x), \pan, trk.pan(x));
0.125.wait;
};
});
};
};
)
//while the above is running
~mysequencer[0..7].do{|trk| trk.amps= 0!32} //mute all tracks except 8&9
~mysequencer[8..9].do{|trk| trk.mods= {4.0.linrand}!32} //more fmod on tracks 8&9
~mysequencer[0..1].do{|trk, i| trk.freqs= {i+1*150}!32; trk.mods= {0}!32; trk.amps= {|j| [0, 1].wrapAt(i+j)}!32} //renew and add tracks 0&1
~mysequencer[8..9].do{|trk| trk.amps= {0.75.linrand*[1, 0].choose}!32} //new amps for track 8&9
~mysequencer[8..9].do{|trk| trk.freqs= {8.linrand+1*150}!32} //new freqs for track 8&9
~mysequencer[6].amps= {0.4}!9++({0}!23); ~mysequencer[6].freqs= {|i| 2**i*50+50}!32; //add arpeggio on track 6
~mysequencer.do{|x| x.freqs= x.freqs*1.1} //transpose all frequencies
~mysequencer.do{|x| x.amps= x.amps.rotate(-3)} //rotate all amps
r.do{|x| x.stop}
~synths.do{|x| x.free}