From 394ae3ad2f548a60398df86d09d59cec84319ceb Mon Sep 17 00:00:00 2001 From: Rob Canning Date: Tue, 12 Sep 2023 18:17:02 +0200 Subject: [PATCH] added live patch for 2xmpr121 --- esp32_S2_USB_Olimex/esp32_S2_USB_Olimex.ino | 180 ++++++++++++------- sc/collaborative_capacative.scd | 186 +++++++++++--------- sc/live_touch_instrument.scd | 164 +++++++++++++++++ 3 files changed, 385 insertions(+), 145 deletions(-) create mode 100644 sc/live_touch_instrument.scd diff --git a/esp32_S2_USB_Olimex/esp32_S2_USB_Olimex.ino b/esp32_S2_USB_Olimex/esp32_S2_USB_Olimex.ino index 033fe22..f6ed948 100644 --- a/esp32_S2_USB_Olimex/esp32_S2_USB_Olimex.ino +++ b/esp32_S2_USB_Olimex/esp32_S2_USB_Olimex.ino @@ -27,64 +27,16 @@ Adafruit_NeoPixel pixels(1, PIN, NEO_GRB + NEO_KHZ800); #ifndef _BV #define _BV(bit) (1 << (bit)) -#endif -// You can have up to 4 on one i2c bus but one is enough for testing! -Adafruit_MPR121 cap = Adafruit_MPR121(); -// Keeps track of the last pins touched -// so we know when buttons are 'released' -uint16_t lasttouched = 0; -uint16_t currtouched = 0; +#endif/ +.//./ You can have up to 4 on one i2c bus but one is enough for testing! -// Wi-Fi SETTINGS ///////////// +Adafruit_MPR121 cap0 = Adafruit_MPR121(); -#include -const char* ssid = "zavod rizoma_EXT"; -const char* password = "cermozise"; -// BROADCAST TO ALL IP / port -const IPAddress castIp = IPAddress(192,168,0,255); // 255 FOR BROADCAST -const int port = 57120; // SUPERCOLLIDERS DEFAULT INCOMING OSC PORT -bool connected = false; -#include -WiFiUDP udp; +Adafruit_MPR121 cap1 = Adafruit_MPR121(); + pixels.begin(); // INITIALIZE NeoPixel (REQUIRED) -// OSC and serial communications //////////////////////////// -#define SERIAL_OSC -#define WIFI_OSC -#include -#include -#include -/* OSC MSG channels */ -OSCBundle bundle; -// SERIAL ///////////////////////////////// - -#ifdef BOARD_HAS_USB_SERIAL -#include -SLIPEncodedUSBSerial SLIPSerial( thisBoardsSerialUSB ); -#else -#include -SLIPEncodedSerial SLIPSerial(Serial); -#endif - -// CAPACITIVE TOUCH SETUP /////////////////// - -byte keys[] = {1,2,3,4,5,6,7,10,11,12,13,14}; -byte KEYLEN = 12; -byte pressed[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -byte lastTouchState[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -byte touchState[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -byte lastDebounceTime[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers -//int THRESH = 40; // capacitive noise threshold - -/////////////////////////////////////////// - -void setup() { - - pixels.setBrightness(5); - pixels.begin(); // INITIALIZE NeoPixel (REQUIRED) - pinMode(ledPin, OUTPUT); //Define ledPin as output pinMode(shiftLedPin, OUTPUT); //Define ledPin as output pinMode(loopLedPin, OUTPUT); //Define ledPin as output @@ -99,13 +51,22 @@ void setup() { // Default address is 0x5A, if tied to 3.3V its 0x5B // If tied to SDA its 0x5C and if SCL then 0x5D - if (!cap.begin(0x5A)) { - Serial.println("MPR121 not found, check wiring?"); + if (!cap1.begin(0x5A)) { + Serial.println("MPR121 not found, check wiring?"); while (1); } Serial.println("MPR121 found!"); + + if (!cap2.begin(0x5C)) { + Serial.println("MPR121 not found, check wiring?"); + while (1); + } + + Serial.println("MPR121 found!"); + + // I2C init //Serial.println("Starting up I2C"); //Wire.begin(); @@ -126,7 +87,9 @@ void setup() { } // setup ends ////////////////////////////////////////////////// // MAIN LOOP ///////////////////////////////////////////////////////// + int colorCount = 0; + void loop() { //Set the new color on the pixel. pixels.setPixelColor(0, Wheel(colorCount++)); @@ -135,8 +98,9 @@ void loop() { if (colorCount > 255) colorCount = 0; - sendCapacitive(); - sendCapacitiveOlimex(); + sendCapacitiveA(); // from the 121 + sendCapacitiveB(); // from the 121 + sendCapacitiveOlimex(); // from the board } @@ -185,13 +149,13 @@ void connectWiFi(){ // detect touch events and send over OSC ////////////// -void sendCapacitive(void){ +void sendCapacitiveA(void){ // Get the currently touched pads - currtouched = cap.touched(); + currtouched0 = cap1.touched(); for (uint8_t i=0; i"); + +} ////////////////// + diff --git a/sc/collaborative_capacative.scd b/sc/collaborative_capacative.scd index b150ba1..77e08e2 100644 --- a/sc/collaborative_capacative.scd +++ b/sc/collaborative_capacative.scd @@ -1,20 +1,16 @@ /*RUN*/ -//supercollider file for spellcaster - s.options.numInputBusChannels = 4; s.options.numOutputBusChannels = 4; -OSCFunc.trace(true); // Turn posting on -OSCFunc.trace(false); // Turn posting off +//OSCFunc.trace(true); // Turn posting on +//OSCFunc.trace(false); // Turn posting off -//s.boot; -//( s.waitForBoot{ /////////////////////////////////////////////////////////////////////////// // set path for sample location and make dictionary of subdirectories //~samplepath = thisProcess.nowExecutingPath.dirname ++ "/samples"; - ~samplepath = "/home/rizoma/pifcamp2023/sc/samples"; // CHANGE THIS TO YOUR OWN PATH + ~samplepath = "/home/rob/pifcamp2023/sc/samples"; // CHANGE THIS TO YOUR OWN PATH ~smp = Dictionary.new; PathName(~samplepath).entries.do{ @@ -27,9 +23,7 @@ s.waitForBoot{ ) ); }; - // e.g. green sample subdirectory of ~samplepath: ~smp[\green][1] // - /////////////////////////////////////////////////////////////////////// // allocate busses @@ -37,104 +31,138 @@ s.waitForBoot{ ~ringModBus = Bus.audio(s, 1); // create group order - ~smpGrp = Group.new; - - // 4 BUFFERS ALLOCATED ... - ~b1 = Buffer.alloc(s, s.sampleRate * 10, 1); // Allocate a 10 second mono buffer - ~b0 = Buffer.alloc(s, s.sampleRate * 4, 1); // - //~b1 = Buffer.alloc(s, s.sampleRate * 4, 1); // - ~b2 = Buffer.alloc(s, s.sampleRate * 4, 1); // - ~b3 = Buffer.alloc(s, s.sampleRate * 4, 1); // - - //////////////////////////////////////////////////////////// - // function to save audio recordings to timestamped wav files - // make the MIZA directory manually for now and store audio recording archive there - // this gets triggered by the osc responder below // ~archiveInputs.value(~b0); - - ~path = thisProcess.platform.recordingsDir +/+ "MIZA/"; - ~archiveInputs = { | buf| buf.write( - path: ~path ++ "MIZA_" ++ Date.localtime.stamp ++ ".wav", - headerFormat: "wav", - sampleFormat: 'int16'); - }; - - // load archive directories into array and scramble - ~archiveDir = PathName.new(~path).files.scramble.copyFromStart(5); - ~archiveDir[0]; // get a random file from archive + ~sGA = Group.new; ~sGB = Group.new; ~sGC = Group.new; ~sGD = Group.new; s.sync; + //// SYNTHS ////////////////////////////////// - SynthDef.new(\splay, {| out = 0, bufnum = 0, trig = 1, amp = 1, rate=1, - atk=1, rel=1, loop=0, spos=0, gate=1 | + SynthDef.new(\splay, {| out=0, bufnum=0, t_trig=0, amp=0.5, rate=1, + atk=1, rel=1, loop=0, spos=0, gate=0, panRate=0.2 | var env, sig; env= EnvGen.kr(Env.asr(atk,1,rel),gate, doneAction:2); - sig = PlayBuf.ar(1, bufnum, - //BufRateScale.kr(bufnum) * - rate, trig, startPos: spos, loop:loop, - doneAction: Done.freeSelf); + sig = PlayBuf.ar(1, bufnum, rate, t_trig, startPos: spos, loop:loop, doneAction: 0); sig = sig * env * amp; + sig = Pan2.ar(sig, FSinOsc.kr(panRate)); Out.ar(out, sig); }).add; -//////////////////////////////////////////////////////// s.sync; -~oscPlay = { - arg chan=1, rates=1, sdir=\bowl, amp=0.5, loop=0, group=~smpGrp; - Synth(\splay, [\bufnum, ~smp[sdir][rrand(0,~smp[sdir].size)], - \out, rrand(0,1), \rate, rates, \amp, rrand(0.4, 0.8), \loop, loop], group); // recorder - postln("chan:" + chan + "rates: " + rates + "sdir:" + sdir.asString + "amp: " + amp ); - }; + ~oPA = 8.collect({ + arg itt, rate=1, out=0, sdir=\bowl, + amp=0.5, loop=1, panRate=rrand(0.05,0.75), group=~sGA; + //var deg = Scale.major[deg].midiratio; + //postln( itt + " bufnum" + \bufnum + "sdir:" + sdir.asString + "amp: " + amp + "out: " + out); + Synth.new(\splay, [\bufnum, ~smp[sdir][rrand(0,~smp[sdir].size-1)], \out, out, \loop, loop, panRate: panRate], group); + }); -// 'A8:42:E3:4B:10:AC' -~ls0=1; //loop state + ~oPB = 8.collect({ + arg itt, rate=1, out=0, sdir=\green, + amp=0.1, loop=1, panRate=rrand(0.05,0.75), group=~sGA; + //var deg = Scale.major[deg].midiratio; + //postln( itt + " bufnum" + \bufnum + "sdir:" + sdir.asString + "amp: " + amp + "out: " + out); + Synth.new(\splay, [\bufnum, ~smp[sdir][rrand(0,~smp[sdir].size-1)], \out, out, \loop, loop, panRate: panRate], group); + }); -/////////////////////////////////////////////////////////////////// + + // RECEIVE OSC MESSAGES FROM ESP32s + + ~shift = 0; // shift state + ~ls0=1; // loop state s.sync; -// RECEIVE OSC MESSAGES FROM ESP32s -~esp32Receive = { arg name ,mac; OSCdef(name, { arg msg, time; -/* postln("from esp32: " + mac + " name: " + name + " sensor: " + msg[2] ); // which ESP instrument and sensor is message coming from - "~esp32Receive function declared".postln;*/ + ~esp32Receive = { arg name ,mac; OSCdef(name, { arg msg, time; - if (msg[1] == mac) { // use esp32 mac address to determine source of msg + // msg[1] sender mac address + // msg[2] which of the [0 - 11] sensors is touched + // msg[3] is it a touch [1] or a release [0] + // msg[4] which of the connected mpr121 boards is sending - postln("from esp32: " + mac + " name: " + name + " sensor: " + msg[2] ); // which ESP instrument and sensor is message coming from + if (msg[1] == mac && msg[3] == 1 && msg[4] == 0 && ~shift == 0 ) { + postln("first board" + msg[2]); + ~scale = Scale.partch_o1; w = case - { msg[2] == 0} { ~oscPlay.value( chan: rrand(0,1), rates:[0.125, 0.5,1].choose + 0.1, sdir: \green, amp:rrand(0.4, 0.8), loop:0, group:~smpGrp ); } - { msg[2] == 1} { ~oscPlay.value( chan: rrand(0,1), rates:[8,16,24].choose + 0.2, sdir: \bowl, amp:rrand(0.4, 0.8), loop:1, group:~smpGrp ); } - { msg[2] == 2} { ~oscPlay.value( chan: rrand(0,1), rates:[0.125, 0.5, 1].choose + 0.3, sdir: \bowl, amp:rrand(0.4, 0.8), loop:0, group:~smpGrp ); } - { msg[2] == 3} { ~oscPlay.value( chan: rrand(0,1), rates:[0.5, 1,2,3].choose + 0.5, sdir: \bowl, amp:rrand(0.4, 0.8), loop:0, group:~smpGrp ); } - { msg[2] == 4} { ~oscPlay.value( chan: rrand(0,1), rates:[0.5, 1,2,3].choose + 0.8, sdir: \bowl, amp:rrand(0.4, 0.8), loop:0, group:~smpGrp ); } - { msg[2] == 5} { ~oscPlay.value( chan: rrand(0,1), rates:[0.5, 1,2,3].choose + 1.3, sdir: \bowl, amp:rrand(0.4, 0.8), loop:0, group:~smpGrp ); } - { msg[2] == 6} { ~oscPlay.value( chan: rrand(0,1), rates:[0.5, 1,2,3].choose + 2.1, sdir: \bowl, amp:rrand(0.4, 0.8), loop:0, group:~smpGrp ); } + { msg[2] == 0} { ~oPA[0].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \loop, 1, \gate, 1); } + { msg[2] == 1} { ~oPA[1].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 2} { ~oPA[2].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 3} { ~oPA[3].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 4} { ~oPA[4].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 5} { ~oPA[5].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 6} { ~oPA[6].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 7} { ~oPA[7].set(\rate, ~scale[rrand(0,47)].midiratio + 1 , \t_trig, 1, \gate, 1); } - // touch 7 = toggle looping of all samplers - { msg[2] == 7} { + { msg[2] == 8 } { // touch 7 = toggle looping of all samplers ~ls0 = (~ls0 + 1)% 2; - ~smpGrp.set(\loop, ~ls0 ); // toggle this + ~sGA.set(\loop, ~ls0 ); // toggle this postln("loop state set as:" + ~ls0 + " 7 " + msg[2] ); }; + }; + + if (msg[1] == mac && msg[3] == 1 && msg[4] == 1) { + postln("second board" + msg[2]); + w = case + { msg[2] == 0} { ~oPB[0].set(\rate, Scale.major[0].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 1} { ~oPB[1].set(\rate, Scale.major[1].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 2} { ~oPB[2].set(\rate, Scale.major[2].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 3} { ~oPB[3].set(\rate, Scale.major[3].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 4} { ~oPB[4].set(\rate, Scale.major[4].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 5} { ~oPB[5].set(\rate, Scale.major[5].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 6} { ~oPB[6].set(\rate, Scale.major[6].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 7} { ~oPB[7].set(\rate, Scale.major[7].midiratio, \t_trig, 1, \gate, 1); } + + { msg[2] == 8 } { // touch 7 = toggle looping of all samplers + ~ls0 = (~ls0 + 1)% 2; + ~sGB.set(\loop, ~ls0 ); // toggle this + postln("loop state set as:" + ~ls0 + " 7 " + msg[2] ); + }; + }; + + // select with SHIFT key - toggle effect = apply with enter key + // set a state // release of shift key acts as enter + + // msg[1] sender mac address + // msg[2] which of the [0 - 11] sensors is touched + // msg[3] is it a touch [1] or a release [0] + // msg[4] which of the connected mpr121 boards is sending + + // if SHIFT IS DEPRESSED on board 1 - shift enabled while 11 depressed + if (msg[1] == mac && msg[2] == 11 && msg[4] == 0 ) { + if (msg[3]==1){ + ~shift = 1; postln("shift is enabled" )} + { ~shift = 0; postln("shift is disabled" )} + }; + + // when finished apply effect/change and set state to unselected + + if (~shift==1) { + postln(" shift is pressed " + msg[2]); + w = case + { msg[2] == 0} { ~oPA[0].set(\rate, 16); } + { msg[2] == 1} { ~oPA[1].set(\rate, 14); } + { msg[2] == 2} { ~oPA[2].set(\rate, 12); } + { msg[2] == 3} { ~oPA[3].set(\rate, 10); } + { msg[2] == 4} { ~oPA[4].set(\rate, 8); } + { msg[2] == 5} { ~oPA[5].set(\rate, 6); } + { msg[2] == 6} { ~oPA[6].set(\rate, 4); } + { msg[2] == 7} { ~oPA[7].set(\rate, 2); } } -},'/touch') } ; + //~oPA[0].get(\rate.poll).poll + + },'/touch') } ; + + ~oPA[0].get(\rate).value; s.sync; - "asdfasdfasdf".postln; + ~esp32Receive.('anything', '3C:E9:0E:AD:A5:48'); - ~esp32Receive.('bendy_wires', 'A8:42:E3:4B:10:AC'); - ~esp32Receive.('tetractys', '48:E7:29:C3:EF:BC'); - ~esp32Receive.('roger', '48:E7:29:C3:EF:BC'); - ~esp32Receive.('robbie', 'A8:42:E3:57:A1:38'); - ~esp32Receive.('tina', 'A8:42:E3:47:5E:3C '); + ~sG.set(\amp, 1); + ~sG.set(\rate, -1); + ~sGB.set(\amp, 0.2); + + + "patch loaded and ready...".postln; }; - -//} -/// mesages from tetractys esp32 -// 3C:E9:0E:AD:E5:00 - general -// 48:E7:29:C3:EF:BC - tetractys -// A0:B7:65:4A:AB:40 // white clip -// A8:42:E3:4B:10:AC // testing thin case diff --git a/sc/live_touch_instrument.scd b/sc/live_touch_instrument.scd new file mode 100644 index 0000000..9c4ffcf --- /dev/null +++ b/sc/live_touch_instrument.scd @@ -0,0 +1,164 @@ +/*RUN*/ + +s.options.numInputBusChannels = 4; +s.options.numOutputBusChannels = 4; + +//OSCFunc.trace(true); // Turn posting on +//OSCFunc.trace(false); // Turn posting off + +s.waitForBoot{ + /////////////////////////////////////////////////////////////////////////// + // set path for sample location and make dictionary of subdirectories + //~samplepath = thisProcess.nowExecutingPath.dirname ++ "/samples"; + ~samplepath = "/home/rob/pifcamp2023/sc/samples"; // CHANGE THIS TO YOUR OWN PATH + ~smp = Dictionary.new; + + PathName(~samplepath).entries.do{ + arg subfolder; + ~smp.add( + subfolder.folderName.asSymbol -> + Array.fill( + subfolder.entries.size, + { arg i; Buffer.read(s, subfolder.entries[i].fullPath).normalize;} + ) + ); + }; + // e.g. green sample subdirectory of ~samplepath: ~smp[\green][1] // + /////////////////////////////////////////////////////////////////////// + + // allocate busses + ~reverbBus = Bus.audio(s, 1); + ~ringModBus = Bus.audio(s, 1); + + // create group order + ~sGA = Group.new; ~sGB = Group.new; ~sGC = Group.new; ~sGD = Group.new; + + s.sync; + + //// SYNTHS ////////////////////////////////// + + SynthDef.new(\splay, {| out=0, bufnum=0, t_trig=0, amp=0.5, rate=1, + atk=1, rel=1, loop=0, spos=0, gate=0, panRate=0.2 | + var env, sig; + env= EnvGen.kr(Env.asr(atk,1,rel),gate, doneAction:2); + sig = PlayBuf.ar(1, bufnum, rate, t_trig, startPos: spos, loop:loop, doneAction: 0); + sig = sig * env * amp; + sig = Pan2.ar(sig, FSinOsc.kr(panRate)); + Out.ar(out, sig); + }).add; + + s.sync; + + ~oPA = 8.collect({ + arg itt, rate=1, out=0, sdir=\bowl, + amp=0.5, loop=1, panRate=rrand(0.05,0.75), group=~sGA; + Synth.new(\splay, [\bufnum, ~smp[sdir][rrand(0,~smp[sdir].size-1)], \out, out, \loop, loop, panRate: panRate], group); + }); + + ~oPB = 8.collect({ + arg itt, rate=1, out=0, sdir=\green, + amp=0.1, loop=1, panRate=rrand(0.05,0.75), group=~sGA; + Synth.new(\splay, [\bufnum, ~smp[sdir][rrand(0,~smp[sdir].size-1)], \out, out, \loop, loop, panRate: panRate], group); + }); + + + // RECEIVE OSC MESSAGES FROM ESP32s + + ~shift = 0; // shift state + ~ls0=1; // loop state + s.sync; + + ~esp32Receive = { arg name ,mac; OSCdef(name, { arg msg, time; + + // msg[1] sender mac address + // msg[2] which of the [0 - 11] sensors is touched + // msg[3] is it a touch [1] or a release [0] + // msg[4] which of the connected mpr121 boards is sending + + if (msg[1] == mac && msg[3] == 1 && msg[4] == 0 && ~shift == 0 ) { + postln("first board" + msg[2]); + ~scale = Scale.partch_o1; + w = case + { msg[2] == 0} { ~oPA[0].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \loop, 1, \gate, 1); } + { msg[2] == 1} { ~oPA[1].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 2} { ~oPA[2].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 3} { ~oPA[3].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 4} { ~oPA[4].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 5} { ~oPA[5].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 6} { ~oPA[6].set(\rate, ~scale[rrand(0,47)].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 7} { ~oPA[7].set(\rate, ~scale[rrand(0,47)].midiratio + 1 , \t_trig, 1, \gate, 1); } + + { msg[2] == 8 } { // touch 7 = toggle looping of all samplers + ~ls0 = (~ls0 + 1)% 2; + ~sGA.set(\loop, ~ls0 ); // toggle this + postln("loop state set as:" + ~ls0 + " 7 " + msg[2] ); + }; + }; + + if (msg[1] == mac && msg[3] == 1 && msg[4] == 1) { + postln("second board" + msg[2]); + w = case + { msg[2] == 0} { ~oPB[0].set(\rate, Scale.major[0].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 1} { ~oPB[1].set(\rate, Scale.major[1].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 2} { ~oPB[2].set(\rate, Scale.major[2].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 3} { ~oPB[3].set(\rate, Scale.major[3].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 4} { ~oPB[4].set(\rate, Scale.major[4].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 5} { ~oPB[5].set(\rate, Scale.major[5].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 6} { ~oPB[6].set(\rate, Scale.major[6].midiratio, \t_trig, 1, \gate, 1); } + { msg[2] == 7} { ~oPB[7].set(\rate, Scale.major[7].midiratio, \t_trig, 1, \gate, 1); } + + { msg[2] == 8 } { // touch 7 = toggle looping of all samplers + ~ls0 = (~ls0 + 1)% 2; + ~sGB.set(\loop, ~ls0 ); // toggle this + postln("loop state set as:" + ~ls0 + " 7 " + msg[2] ); + }; + }; + + // select with SHIFT key - toggle effect = apply with enter key + // set a state // release of shift key acts as enter + + // msg[1] sender mac address + // msg[2] which of the [0 - 11] sensors is touched + // msg[3] is it a touch [1] or a release [0] + // msg[4] which of the connected mpr121 boards is sending + + // if SHIFT IS DEPRESSED on board 1 - shift enabled while 11 depressed + if (msg[1] == mac && msg[2] == 11 && msg[4] == 0 ) { + if (msg[3]==1){ + ~shift = 1; postln("shift is enabled" )} + { ~shift = 0; postln("shift is disabled" )} + }; + + // when finished apply effect/change and set state to unselected + + if (~shift==1) { + postln(" shift is pressed " + msg[2]); + w = case + { msg[2] == 0} { ~oPA[0].set(\rate, 16); } + { msg[2] == 1} { ~oPA[1].set(\rate, 14); } + { msg[2] == 2} { ~oPA[2].set(\rate, 12); } + { msg[2] == 3} { ~oPA[3].set(\rate, 10); } + { msg[2] == 4} { ~oPA[4].set(\rate, 8); } + { msg[2] == 5} { ~oPA[5].set(\rate, 6); } + { msg[2] == 6} { ~oPA[6].set(\rate, 4); } + { msg[2] == 7} { ~oPA[7].set(\rate, 2); } + } + //~oPA[0].get(\rate.poll).poll + + },'/touch') } ; + + ~oPA[0].get(\rate).value; + + s.sync; + + ~esp32Receive.('anything', '3C:E9:0E:AD:A5:48'); + + ~sG.set(\amp, 1); + ~sG.set(\rate, -1); + + ~sGB.set(\amp, 0.2); + + + "patch loaded and ready...".postln; + +};