Finish Mix-101 adapter / fix zero array in sampler
authorEugene Petkevich <nasedil.genio.code@gmail.com>
Sun, 22 May 2022 15:42:20 +0000 (18:42 +0300)
committerEugene Petkevich <nasedil.genio.code@gmail.com>
Sun, 22 May 2022 15:42:20 +0000 (18:42 +0300)
extensions/classes/midimix.sc
extensions/classes/sampler.sc
Хэзифу/mix101-control.scd

index fc3b3d2..2298c63 100644 (file)
@@ -1,15 +1,24 @@
 MidiMix {
-  classvar ledValues;
+  classvar ledValues, ledControls;
   classvar controlNotes;
   const <version = "0.1";
   var <name;
   var <channel = 5;
   var <midiout, <idin;
-  var <>caro;
-  var <>joro, <>viro, <>wipu, <>wire;
-  var <>sepu, <>sere;
-  var <>sewo, <>luwo, <>fewo, <>viwo;
-  var <>sypu, <>syre;
+  // channel selector
+  var <>chanrot;
+  // modes
+  var <>sampler, <>loop, <>fx, <>vinyl;
+  // wheel rotation
+  var <>jogrot, <>scratch;
+  // buttons
+  var <>lpfA, <>lpfB, <>but1, <>but1, <>select, <>sync, <>play, <>cue, <>deck, <>rotbut1, <>rotbut2, <>rotbutload, <>jogact;
+  // knobs
+  var <>again, <>bgain, <>ahi, <>amid, <>alow, <>bhi, <>bmid, <>blow;
+  // faders
+  var <>afade, <>bfade, <>crossfade;
+  // endless rotators
+  var <>rot1, <>rot2, <>rotload;
 
   *initClass {
     ledValues = IdentityDictionary[
@@ -21,16 +30,34 @@ MidiMix {
       false -> 0
     ];
 
-    controlNotes = IdentityDictionary[
-      1 -> \da,
-      2 -> \ze,
-      3 -> \ku,
-      4 -> \ta,
-      7 -> \be,
-      8 -> \bu,
-      9 -> \pe,
-      11 -> \gu,
+    ledControls = IdentityDictionary[
+      \pflA -> 1,
+      \pflB -> 2,
+      \but1 -> 3,
+      \but2 -> 4,
+      \play -> 7,
+      \cue -> 8,
+      \deck -> 9,
+      \sampler -> 17,
+      \loop -> 18,
+      \fx -> 19,
+      \vinyl -> 20,
+    ];
 
+    controlNotes = IdentityDictionary[
+      1 -> \lpfA,
+      2 -> \lpfB,
+      3 -> \but1,
+      4 -> \but2,
+      5 -> \select,
+      6 -> \sync,
+      7 -> \play,
+      8 -> \cue,
+      9 -> \deck,
+      11 -> \rotbut1,
+      12 -> \rotbut2,
+      13 -> \rotbutload,
+      21 -> \jogact,
     ];
   }
 
@@ -50,175 +77,127 @@ MidiMix {
 
     // MIDI out channel selector (back of the device)
     // velocity is the channel
-    MIDIdef.noteOn(\caro+name, {|...args|
+    MIDIdef.noteOn(\chanrot++name, {|...args|
       channel = args[0];
-      caro.value(*args);
+      chanrot.value(*args);
     }, 14, srcID: idin);
 
     // == Jog wheel
-    // Start rotating
-    MIDIdef.noteOn(\wipu+name, {|...args|
-      wipu.value(*args);
-    }, 21, srcID: idin);
-    // Stop rotating
-    MIDIdef.noteOff(\wire+name, {|...args|
-      wire.value(*args);
-    }, 21, srcID: idin);
     // Rotating in sampler/loop/fx mode: -1/1
-    MIDIdef.cc(\joro+name, {|...args|
-      joro.value(args[0]-64, *args);
+    MIDIdef.cc(\jogrot+name, {|...args|
+      jogrot.value(args[0]-64, *args);
     }, 19, srcID: idin);
     // Rotating in cue/vinyl mode: -1/1
-    MIDIdef.cc(\viro+name, {|...args|
-      viro.value(args[0]-64, *args);
+    MIDIdef.cc(\scratch+name, {|...args|
+      scratch.value(args[0]-64, *args);
     }, 21, srcID: idin);
 
-    // == sync/select buttons
-    // select button pushed
-    MIDIdef.noteOn(\sepu+name, {|...args|
-      sepu.value(*args);
-    }, 5, srcID: idin);
-    // select button released
-    MIDIdef.noteOff(\sere+name, {|...args|
-      sere.value(*args);
-    }, 5, srcID: idin);
-    // sync button pushed
-    MIDIdef.noteOn(\sypu+name, {|...args|
-      sypu.value(*args);
-    }, 6, srcID: idin);
-    // sync button released
-    MIDIdef.noteOff(\syre+name, {|...args|
-      syre.value(*args);
-    }, 6, srcID: idin);
+    // == modes
     // sampler mode activated
-    MIDIdef.noteOn(\sewo+name, {|...args|
-      sewo.value(*args);
+    MIDIdef.noteOn(\sampler++name, {|...args|
+      sampler.value(*args);
     }, 17, srcID: idin);
     // loop mode activated
-    MIDIdef.noteOn(\luwo+name, {|...args|
-      luwo.value(*args);
+    MIDIdef.noteOn(\loop++name, {|...args|
+      loop.value(*args);
     }, 18, srcID: idin);
     // fx mode activated
-    MIDIdef.noteOn(\fewo+name, {|...args|
-      fewo.value(*args);
+    MIDIdef.noteOn(\fx++name, {|...args|
+      fx.value(*args);
     }, 19, srcID: idin);
     // cue/vinyl mode activated
-    MIDIdef.noteOn(\viwo+name, {|...args|
-      viwo.value(*args);
+    MIDIdef.noteOn(\vinyl++name, {|...args|
+      vinyl.value(*args);
     }, 20, srcID: idin);
 
     // == faders
     // channel A fader
-    MIDIdef.cc(\dafe+name, {|...args|
-      dafe.value(args[0].linlin(0, 127, 0, 1), *args);
+    MIDIdef.cc(\afade+name, {|...args|
+      afade.value(args[0].linlin(0, 127, 0, 1), *args);
     }, 33, srcID: idin);
     // channel B fader
-    MIDIdef.cc(\zefe+name, {|...args|
-      zefe.value(args[0].linlin(0, 127, 0, 1), *args);
+    MIDIdef.cc(\bfade+name, {|...args|
+      bfade.value(args[0].linlin(0, 127, 0, 1), *args);
     }, 34, srcID: idin);
     // cross fader
-    MIDIdef.cc(\cofe+name, {|...args|
-      cofe.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
+    MIDIdef.cc(\crossfade+name, {|...args|
+      crossfade.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
     }, 35, srcID: idin);
 
     // == knobs
     // channel A gain
-    MIDIdef.cc(\dage+name, {|...args|
-      dage.value(args[0].linlin(0, 127, 0, 1), *args);
+    MIDIdef.cc(\again+name, {|...args|
+      again.value(args[0].linlin(0, 127, 0, 1), *args);
     }, 36, srcID: idin);
     // channel B gain
-    MIDIdef.cc(\zege+name, {|...args|
-      zege.value(args[0].linlin(0, 127, 0, 1), *args);
+    MIDIdef.cc(\bgain+name, {|...args|
+      bgain.value(args[0].linlin(0, 127, 0, 1), *args);
     }, 37, srcID: idin);
     // channel A hi
-    MIDIdef.cc(\daha+name, {|...args|
-      daha.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
+    MIDIdef.cc(\ahi+name, {|...args|
+      ahi.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
     }, 38, srcID: idin);
     // channel B hi
-    MIDIdef.cc(\zeha+name, {|...args|
-      zeha.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
+    MIDIdef.cc(\bhi+name, {|...args|
+      bhi.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
     }, 39, srcID: idin);
     // channel A mid
-    MIDIdef.cc(\dami+name, {|...args|
-      dami.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
+    MIDIdef.cc(\amid+name, {|...args|
+      amid.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
     }, 40, srcID: idin);
     // channel B mid
-    MIDIdef.cc(\zemi+name, {|...args|
-      zemi.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
+    MIDIdef.cc(\bmid+name, {|...args|
+      bmid.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
     }, 41, srcID: idin);
     // channel A low
-    MIDIdef.cc(\dalo+name, {|...args|
-      dalo.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
+    MIDIdef.cc(\alow+name, {|...args|
+      alow.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
     }, 42, srcID: idin);
     // channel B low
-    MIDIdef.cc(\zelo+name, {|...args|
-      zelo.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
+    MIDIdef.cc(\blow+name, {|...args|
+      blow.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
     }, 43, srcID: idin);
 
     // == endless rotators
     // channel A rotator: -1/1
-    MIDIdef.cc(\daro+name, {|...args|
-      daro.value(args[0]-64, *args);
+    MIDIdef.cc(\rot1+name, {|...args|
+      rot1.value(args[0]-64, *args);
     }, 16, srcID: idin);
     // channel B rotator: -1/1
-    MIDIdef.cc(\zero+name, {|...args|
-      zero.value(args[0]-64, *args);
-    }, 17, srcID: idin);
-    // load/preview rotator: -1/1
-    MIDIdef.cc(\loro+name, {|...args|
-      loro.value(args[0]-64, *args);
+    MIDIdef.cc(\rot2+name, {|...args|
+      rot2.value(args[0]-64, *args);
     }, 18, srcID: idin);
+    // load/preview rotator: -1/1
+    MIDIdef.cc(\rotload+name, {|...args|
+      rotload.value(args[0]-64, *args);
+    }, 17, srcID: idin);
 
-    // == buttons
-    MIDIdef.noteOn(\buttons+name, {|...args|
-
-      var handler = this.perform(); a.value(1);
-      dape.value(*args);
-    }, [1, 2, 3, 4, 7, 8, 9, 11, 12, 13], srcID: idin);
-
-    // channel A pfl button pushed
-    MIDIdef.noteOn(\dapu+name, {|...args|
-      dape.value(*args);
-    }, 1, srcID: idin);
-    // channel A pfl button released
-    MIDIdef.noteOff(\dare+name, {|...args|
-      dare.value(*args);
-    }, 1, srcID: idin);
-    // channel A pfl button pushed
-    MIDIdef.noteOn(\zepu+name, {|...args|
-      zepu.value(*args);
-    }, 2, srcID: idin);
-    // channel A pfl button released
-    MIDIdef.noteOff(\zere+name, {|...args|
-      zere.value(*args);
-    }, 2, srcID: idin);
-    // channel A pfl button pushed
-    MIDIdef.noteOn(\dapu+name, {|...args|
-      dape.value(*args);
-    }, 3, srcID: idin);
-    // channel A pfl button released
-    MIDIdef.noteOff(\dare+name, {|...args|
-      dare.value(*args);
-    }, 3, srcID: idin);
-    // channel A pfl button pushed
-    MIDIdef.noteOn(\zepu+name, {|...args|
-      zepu.value(*args);
-    }, 4, srcID: idin);
-    // channel A pfl button released
-    MIDIdef.noteOff(\zere+name, {|...args|
-      zere.value(*args);
-    }, 4, srcID: idin);
+    // == buttons, first arg is true if pressed, false if released
+    // button pressed
+    MIDIdef.noteOn(\buttonDown++name, {|...args|
+      var handler, buttonName;
+      buttonName = controlNotes[args[1]];
+      handler = this.perform(buttonName);
+      handler.value(true, *args);
+    }, controlNotes.keys.asArray, srcID: idin);
+    // button released
+    MIDIdef.noteOff(\buttonUp++name, {|...args|
+      var handler, buttonName;
+      buttonName = controlNotes[args[1]];
+      handler = this.perform(buttonName);
+      handler.value(false, *args);
+    }, controlNotes.keys.asArray, srcID: idin);
 
     // == Starter message and animation
-    this.animate;
+    //this.animate;
     "Шаҫиху готов к использованию 😊".postln;
   }
 
   // == LED control
-  // pfl a
-  leda {|value=true|
+  led {|control, value=true|
     value = ledValues[value] ? value;
-    midiout.noteOn(channel, 1, value);
+    control = ledControls[control] ? control;
+    midiout.noteOn(channel, control, value);
   }
 
   animate {|stretch=1|
index e193b5e..49a14f2 100644 (file)
@@ -69,7 +69,9 @@ Sampler {
       playsTuner = false;
     });
     buf.loadToFloatArray(startPos*buf.sampleRate, duration*buf.sampleRate, action: { |array|
-      var maxval = max(array.maxItem, array.minItem.neg);
+      var maxval;
+      if (array.size == 0) {array = [0]};
+      maxval = max(array.maxItem, array.minItem.neg);
       data = array;
       // resample and calculate moving average to make plot more consistent when browsing
       data = data.resamp1(data.size/sampDiv);
index e657462..cc33257 100644 (file)
@@ -24,26 +24,123 @@ MIDIdef.sysex(\testsysex, {|...args|
 
 MKtl.find;
 
+(
 ~mix = MidiMix();
-~mix.ledb(\off);
-~mout = MIDIOut.newByName("Mix-101", "Mix-101 MIDI 1").latency_(0);
-~mix.
-~mout.noteOn(5, 20, 127);
-
-~mix.joro = {|i| i.postln};
-a = ~mix.perform(\joro); a.value(1);
+~se = Sampler();
+)
 
 (
-(0..15).do {|i|
-  [i].postln;
-  ~mout.noteOn(i, 2, 0);
+~mix.cue_ {|down|
+  if (down) {
+    ~se.startRec();
+    ~mix.led(\cue, \on);
+  } {
+    ~se.stopRec();
+    ~mix.led(\cue, \off);
+  };
+};
+
+~mix.play_ {|down|
+  if (down) {
+    ~se.playSample();
+    ~mix.led(\play, \on);
+  } {
+    ~se.stopPlay();
+    ~mix.led(\play, \off);
+  };
+};
+
+~fine = 0.1;
+~coarse = 0.1;
+~fineActive = false;
+
+~mix.but1_{|d|
+  if (d) {
+    ~fineActive = ~fineActive.not;
+    ~mix.led(\but1, ~fineActive);
+  };
+};
+
+~mix.rot1_{|v|
+  var delta = v * ~coarse;
+  if (~fineActive) {
+    delta = delta * ~fine;
+  };
+  ~se.shiftPos(delta);
+  ~se.startPos.postln;
+};
+
+// granular
+~mix.again_{|v|
+  ~amp = v;
+  ~gran.set(\amp, ~amp);
+  "amp is %f".format(~amp).postln;
+};
+
+~mix.rotload_{|d|
+  var mul = 1.1;
+  if (d < 0) {mul = 1/mul; d = d.neg};
+  d.do{
+    ~density = ~density * mul;
+  };
+  ~gran.set(\density, ~density);
+  "density is %".format(~density).postln;
+};
+
+~mix.rot2_{|d|
+  var mul = 1.1;
+  if (d < 0) {mul = 1/mul; d = d.neg};
+  d.do{
+    ~len = ~len * mul;
+  };
+  ~gran.set(\len, ~len);
+  "len is %".format(~len).postln;
+};
+
+~mix.bfade_{|v|
+  ~rate = v.linexp(0, 1, 1/4, 4);
+  ~gran.set(\rate, ~rate);
+  "rate is %".format(~rate).postln;
+};
+
+~mix.jogrot_{|d|
+  var mul = 0.001;
+  ~pos = ~pos + (d*mul);
+  ~gran.set(\pos, ~pos);
+  "pos is %".format(~pos).postln;
 };
 )
 
 (
-~mix.joro = {|...args|
-  args.postln;
-};
+Pdef(\samploop, Pbind(*[
+  db: -5,
+  dur: 2,
+  midinote: 57,
+]) <> ~se.makeSynthBind).quant_(2).stop;
+)
+
+(
+SynthDef(\granular, {|out=0, amp=1, buf=0, density=10, len=0.1, rate=1, pos=0|
+  var sig;
+  sig = GrainBuf.ar(1, Dust.ar(density), len, buf, rate, pos+LFNoise2.ar().range(0, len/1000), 4, 0, -1, 1024, amp);
+  Out.ar(out, sig!2);
+}).add;
+)
+
+(
+~amp = 0.5;
+~density = 10;
+~len = 0.1;
+~rate = 1;
+~pos = 0;
+~gran = Synth(\granular, [
+  amp: ~amp,
+  buf: ~se.buf,
+  density: ~density,
+  len: ~len,
+  rate: ~rate,
+  pos: ~pos
+]);
 )
 
-~mix = MidiMix()
\ No newline at end of file
+~gran.free;
\ No newline at end of file