‹ MP3 SpeakersESP8266 OpenSound Control Teensy ›

Example Class

2016-05-04 23:30:37 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}
‹ MP3 SpeakersESP8266 OpenSound Control Teensy ›