‹ MP3 Speakers ESP8266 OpenSound Control Teensy ›

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}

‹ MP3 Speakers ESP8266 OpenSound Control Teensy ›