diff --git a/esp32_vroom_38pin/esp32_vroom_38pin.ino b/esp32_vroom_38pin/esp32_vroom_38pin.ino index 13ba1fc..697d2ed 100644 --- a/esp32_vroom_38pin/esp32_vroom_38pin.ino +++ b/esp32_vroom_38pin/esp32_vroom_38pin.ino @@ -38,6 +38,8 @@ 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 +const unsigned int localPort = 8888; // local port to listen for UDP packets (here's where we send the packets) + bool connected = false; #include WiFiUDP udp; @@ -49,9 +51,25 @@ WiFiUDP udp; #include #include #include +#include + /* OSC MSG channels */ OSCBundle bundle; +OSCErrorCode error; +unsigned int ledState = LOW; // LOW means led is *on* +unsigned int ledNum = 0; // LOW means led is *on* +unsigned int touchBoard = 0; // LOW means led is *on* + +#ifndef BUILTIN_LED +#ifdef LED_BUILTIN +#define BUILTIN_LED LED_BUILTIN +#else +#define BUILTIN_LED 13 +#endif +#endif + + // SERIAL ///////////////////////////////// #ifdef BOARD_HAS_USB_SERIAL #include @@ -69,11 +87,15 @@ byte KEYLEN = 12; void setup() { ws2812fx.init(); ws2812fx.setBrightness(10); + //ws2812fx.setPixelColor(11, ws2812fx.Color(0,0,0)); + // // parameters: index, start, stop, mode, color, speed, reverse - ws2812fx.setSegment(0, 0, 11, FX_MODE_BREATH, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9 + // ws2812fx.setSegment(0, 0, 11, FX_MODE_BREATH, 0xFFFFFF, 1000, false); // segment 0 is leds 0 - 9 //ws2812fx.setSegment(1, 0, 0, FX_MODE_BREATH, 0xFF0000, 300, false); // segment 1 is leds 10 - 19 //ws2812fx.setSegment(2, 6, 11, FX_MODE_BREATH, 0x0000FF, 400, true); // segment 2 is leds 20 - 29 + + ws2812fx.setSegment(0, 0, 11, 11, BLACK, 2000, false); ws2812fx.start(); @@ -81,6 +103,8 @@ void setup() { WiFi.mode(WIFI_AP); connectWiFi(); + udp.begin(localPort); // start udp for incoming OSC messages + const String macAddress = WiFi.macAddress(); ; // Default address is 0x5A, if tied to 3.3V its 0x5B @@ -111,9 +135,9 @@ void setup() { int colorCount = 0; - void loop() { - ws2812fx.service(); + rOSC(); + //ws2812fx.service(); sendCapacitive(cap0, 0); // from the 121 sendCapacitive(cap1, 1); // from the 121 } @@ -138,7 +162,101 @@ void connectWiFi(){ Serial.println(WiFi.localIP()); } -// detect touch events and send over OSC ////////////// +//NEOPIXEL COLOUR LOGIC ///////////////////////////////////////////// + +uint32_t colors[] = {RED, GREEN, BLUE, YELLOW, CYAN, MAGENTA, +PURPLE, ORANGE, PINK, GRAY, ULTRAWHITE, WHITE, BLACK }; + +void led(OSCMessage &msg) { + + ledNum = msg.getInt(0); // which sensor/led + ledState = msg.getInt(1); // which state + touchBoard = msg.getInt(2); // which touch board + + // increment led index based on which board input i.e. board 1 is 0-11, board 2 is 12 - 24 + if (touchBoard==0){ledNum = ledNum + 0; }; + if (touchBoard==1){ledNum = ledNum+6; }; // change to 12 when new strip wired! 6 for testing + + switch (msg.getInt(1)) { + ws2812fx.setMode(FX_MODE_BLINK); + case 0: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + break; + case 1: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + case 5: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + break; + case 6: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + break; + } + + switch (msg.getInt(1)) { + ws2812fx.setMode(FX_MODE_BLINK); + case 0: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + break; + case 1: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + break; + case 2: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + break; + case 3: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + break; + case 4: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + break; + case 5: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + break; + case 6: + ws2812fx.setPixelColor(ledNum, colors[ledState]); + break; + +ws2812fx.start(); + +} + + //ws2812fx.start(); + ws2812fx.show(); + +} + +void flashyNeoPixel(int x){ +Serial.print('asfd : ' + x); + if (x==2){ + while(x==2){ + ws2812fx.setPixelColor(11, ws2812fx.Color(0,222,222)); + ws2812fx.show(); + delay(100); + ws2812fx.setPixelColor(11, ws2812fx.Color(222,222,222)); + ws2812fx.show(); + delay(100); + } + } +} + +void rOSC(){ + //Serial.print("osc func called..."); + OSCMessage msg; + int size = udp.parsePacket(); + + if (size > 0) { + while (size--) { + msg.fill(udp.read()); + } + if (!msg.hasError()) { + msg.dispatch("/led", led); + } else { + error = msg.getError(); + Serial.print("error: "); + Serial.println(error); + } + } +} void sendCapacitive(Adafruit_MPR121 sensorboard, int index){ // Get the currently touched pads @@ -148,10 +266,9 @@ void sendCapacitive(Adafruit_MPR121 sensorboard, int index){ // it if *is* touched and *wasnt* touched before, alert! if ((currtouched[index] & _BV(i)) && !(lasttouched[index] & _BV(i)) ) { Serial.print(i); Serial.println(" touched"); - ws2812fx.setSegment(0, i, i, FX_MODE_STATIC, 0xFFFFFF, 700, false); // segment 0 is leds 0 - 9 +// ws2812fx.setSegment(0, i, i, FX_MODE_STATIC, 0x0096FF, 700, false); // segment 0 is leds 0 - 9 //ledState = !ledState; - OSCMessage msg("/touch"); msg.add(WiFi.macAddress().c_str()); // mac address of sender esp32 msg.add((int32_t)i); // send which sensor (0 - 11) was touched @@ -166,7 +283,7 @@ void sendCapacitive(Adafruit_MPR121 sensorboard, int index){ #endif String cap = "val for key num: " + String(i) + " === " + String(HIGH); - Serial.println("OSC SENT "); Serial.println(cap); + //Serial.println("OSC SENT "); Serial.println(cap); } // if it *was* touched and now *isnt*, alert! if (!(currtouched[index] & _BV(i)) && (lasttouched[index] & _BV(i)) ) { @@ -187,8 +304,8 @@ void sendCapacitive(Adafruit_MPR121 sensorboard, int index){ udp.endPacket(); #endif - String cap = "val for key num: " + String(i) + " === " + String(LOW); - Serial.println("OSC SENT "); Serial.println(cap); + // String cap = "val for key num: " + String(i) + " === " + String(LOW); + // Serial.println("OSC SENT "); Serial.println(cap); } } diff --git a/sc/live_touch_instrument.scd b/sc/live_touch_instrument.scd index 9c4ffcf..28202c5 100644 --- a/sc/live_touch_instrument.scd +++ b/sc/live_touch_instrument.scd @@ -3,6 +3,9 @@ s.options.numInputBusChannels = 4; s.options.numOutputBusChannels = 4; +b = NetAddr.new("192.168.0.116", 8888); // create the NetAddr +//b.sendMsg("/led", [0,1].choose); // send the application the message "hello" with the parameter "there" + //OSCFunc.trace(true); // Turn posting on //OSCFunc.trace(false); // Turn posting off @@ -33,15 +36,18 @@ s.waitForBoot{ // 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, + SynthDef.new(\splay, {| out=0, bufnum=0, tpse=1, t_trig=0, amp=0.8, 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 = PlayBuf.ar(1, bufnum, rate*tpse, t_trig, startPos: spos, loop:loop, doneAction: 0); sig = sig * env * amp; sig = Pan2.ar(sig, FSinOsc.kr(panRate)); Out.ar(out, sig); @@ -51,21 +57,41 @@ s.waitForBoot{ ~oPA = 8.collect({ arg itt, rate=1, out=0, sdir=\bowl, - amp=0.5, loop=1, panRate=rrand(0.05,0.75), group=~sGA; + amp=0.9, 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; + amp=0.5, loop=1, panRate=rrand(0.05,0.75), group=~sGB; Synth.new(\splay, [\bufnum, ~smp[sdir][rrand(0,~smp[sdir].size-1)], \out, out, \loop, loop, panRate: panRate], group); }); // RECEIVE OSC MESSAGES FROM ESP32s + ~modeA = 0; + ~modeB = 0; + ~modeC = 0; + ~modeD = 0; + + ~shiftA = 0; // shift state + ~shiftB = 0; // shift state + ~shiftC = 0; // shift state + ~shiftD = 0; // shift state + + ~scaleMode = [Scale.partch_o1, Scale.major, Scale.minor, Scale.chromatic]; + ~scaleA = ~scaleMode[0]; + ~scaleB = ~scaleMode[3]; + + + ~lsA=1; // loop state + ~lsB=1; // loop state + ~ssA = 0; + ~ssB = 0; + + //~scales[2].tuning; ~scales[2].size; ~scales[2].pitchesPerOcatave; + - ~shift = 0; // shift state - ~ls0=1; // loop state s.sync; ~esp32Receive = { arg name ,mac; OSCdef(name, { arg msg, time; @@ -75,46 +101,139 @@ s.waitForBoot{ // 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); } + if (msg[1] == mac && msg[3] == 1 && msg[4] == 0 && ~shiftA == 0 ) { + //12.0.rand.round; + // use an array to spread different patterns over the keys + ~rpitch = rrand(0,~scaleA.size -1); + postln("first board" + msg[2] + "pitchclass: " + ~rpitch ); + b.sendMsg("/led", msg[2], ~rpitch, msg[4]); + w = case + { msg[2] == 0} { ~oPA[0].set(\rate, ~scaleA[~rpitch].midiratio, \t_trig, 1, \gate, 1, \tpse, 1); } + { msg[2] == 1} { ~oPA[1].set(\rate, ~scaleA[0].midiratio, \t_trig, 1, \gate, 1, \tpse, 1); } + // always have a know root + { msg[2] == 2} { ~oPA[2].set(\rate, ~scaleA[~rpitch].midiratio, \t_trig, 1, \gate, 1, \tpse, 1); } + { msg[2] == 3} { ~oPA[3].set(\rate, ~scaleA[~rpitch].midiratio, \t_trig, 1, \gate, 1, \tpse, 1); } + { msg[2] == 4} { ~oPA[4].set(\rate, ~scaleA[~rpitch].midiratio, \t_trig, 1, \gate, 1, \tpse, 1); } + { msg[2] == 5} { ~oPA[5].set(\rate, ~scaleA[~rpitch].midiratio, \t_trig, 1, \gate, 1, \tpse, 1); } + { msg[2] == 6} { ~oPA[6].set(\rate, ~scaleA[~rpitch].midiratio, \t_trig, 1, \gate, 1, \tpse, 1); } + { msg[2] == 7} { ~oPA[7].set(\rate, ~scaleA[~rpitch].midiratio + 1 , \t_trig, 1, \gate, 1); } + + // LOOP mode on off { 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] ); + ~lsA = (~lsA + 1)% 2; + ~sGA.set(\loop, ~lsA ); // toggle this + b.sendMsg("/led", msg[2], ~lsA, msg[4]); + postln("loop state set as:" + ~lsA + " 7 " + msg[2] ); }; }; + // SHIFT logic for board A - 3 function= shift off on extra + ///if SHIFT IS DEPRESSED on board 0 - shift enabled while 11 depressed + + if (msg[1] == mac && msg[2] == 11 && msg[4] == 0 ) { + if (msg[3]==1){ + ~shiftA = (~shiftA + 1)% 3; + postln("SHIFT is: " + ~shiftA); + b.sendMsg("/led", msg[2], ~shiftA, msg[4]); + }; + }; + + if (~shiftA==1 && msg[3]==1) { + postln(" shift is pressed " + msg[2]); + w = case + { msg[2] == 0} { ~oPA[0].set(\tpse, 2, \t_trig, 1); } + { msg[2] == 1} { ~oPA[1].set(\tpse, 2, \t_trig, 1); } + { msg[2] == 2} { ~oPA[2].set(\tpse, 2, \t_trig, 1); } + { msg[2] == 3} { ~oPA[3].set(\tpse, 2, \t_trig, 1); } + { msg[2] == 4} { ~oPA[4].set(\tpse, 2, \t_trig, 1); } + { msg[2] == 5} { ~oPA[5].set(\tpse, 2, \t_trig, 1); } + { msg[2] == 6} { ~oPA[6].set(\tpse, 2, \t_trig, 1); } + { msg[2] == 7} { ~oPA[7].set(\tpse, 2, \t_trig, 1); } + }; + + // SCALE CHANGER + + if (~shiftA==1 && msg[2] == 8 && msg[3] == 1) { + ~ssA = (~ssA + 1) % 4; + // use key release to + ~scaleA = ~scaleMode[~ssA]; + postln(" shift is pressed - scale changed to: " + ~ssA); + b.sendMsg("/led", 9, ~ssA, msg[4]); + }; + + ////////////////////////////////////////////////////////////////////////// + // MODE logic for board A + + if (msg[1] == mac && msg[2] == 10 && msg[4] == 0 ) { + if (msg[3]==1){ + // send the esp32 an osc message + ~modeA = ~modeA+1 % 3; + b.sendMsg("/led", msg[2], ~modeA, msg[4]); postln(~modeA); }; + }; + + + if (msg[1] == mac && msg[3] == 1 && msg[4] == 0 && ~modeA == 1 ) { + w = case + { msg[2] == 0} { ~oPA[0].set(\tpse, -1); } + { msg[2] == 1} { ~oPA[1].set(\tpse, -1 ); } + { msg[2] == 2} { ~oPA[1].set(\tpse, -1 ); } + { msg[2] == 3} { ~oPA[1].set(\tpse, -1 ); } + { msg[2] == 4} { ~oPA[1].set(\tpse, -1 ); } + { msg[2] == 5} { ~oPA[1].set(\tpse, -1 ); } + { msg[2] == 6} { ~oPA[1].set(\tpse, -1 ); } + { msg[2] == 7} { ~oPA[1].set(\tpse, -1 ); } + }; + + // mode 2 randomize transposition + + if (msg[1] == mac && msg[3] == 1 && msg[4] == 0 && ~modeA == 2 ) { + w = case + { msg[2] == 0} { ~oPA[0].set(\tpse, [0.25].choose); } + { msg[2] == 1} { ~oPA[1].set(\tpse, [0.25].choose ); } + { msg[2] == 2} { ~oPA[2].set(\tpse, [0.25].choose); } + { msg[2] == 3} { ~oPA[3].set(\tpse, [0.25].choose ); } + { msg[2] == 4} { ~oPA[4].set(\tpse, [0.25].choose ); } + { msg[2] == 5} { ~oPA[5].set(\tpse, [0.25].choose ); } + { msg[2] == 6} { ~oPA[6].set(\tpse, [0.25].choose ); } + { msg[2] == 7} { ~oPA[7].set(\tpse, [0.25].choose ); } + + }; + + ////////////////////////////////////////////////////////////////////////// + + + + + + //////////// second board + if (msg[1] == mac && msg[3] == 1 && msg[4] == 1) { - postln("second board" + msg[2]); + + ~rpitch = rrand(0,47); + ~rpitch = ~rpitch%11; postln("second board" + msg[2] + "color: " + ~rpitch ); + b.sendMsg("/led", msg[2], ~rpitch, msg[4]); + + 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] == 0} { ~oPB[0].set(\rate, Scale.major[0].midiratio, \t_trig, 1, \gate, 1, \tpse, 1); } + { msg[2] == 1} { ~oPB[1].set(\rate, Scale.major[1].midiratio, \t_trig, 1, \gate, 1, \tpse, 1); } + { msg[2] == 2} { ~oPB[2].set(\rate, Scale.major[2].midiratio, \t_trig, 1, \gate, 1, \tpse, 1); } + { msg[2] == 3} { ~oPB[3].set(\rate, Scale.major[3].midiratio, \t_trig, 1, \gate, 1,\tpse, 1); } + { msg[2] == 4} { ~oPB[4].set(\rate, Scale.major[4].midiratio, \t_trig, 1, \gate, 1,\tpse, 1); } + { msg[2] == 5} { ~oPB[5].set(\rate, Scale.major[5].midiratio, \t_trig, 1, \gate, 1,\tpse, 1); } + { msg[2] == 6} { ~oPB[6].set(\rate, Scale.major[6].midiratio, \t_trig, 1, \gate, 1,\tpse, 1); } + { msg[2] == 7} { ~oPB[7].set(\rate, Scale.major[7].midiratio, \t_trig, 1, \gate, 1,\tpse, 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] ); + ~lsB = (~lsB + 1)% 2; + ~sGB.set(\loop, ~lsB ); // toggle this + b.sendMsg("/led", msg[2], ~lsB, msg[4]); + postln("loop state set as:" + ~lsB + " 7 " + msg[2] ); }; }; - // select with SHIFT key - toggle effect = apply with enter key + // 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 @@ -122,43 +241,41 @@ s.waitForBoot{ // 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 IS DEPRESSED on board 1 - shift enabled while 11 depressed + + if (msg[1] == mac && msg[2] == 11 && msg[4] == 1 ) { + if (msg[3]==1){ + ~shiftB = 1; postln("shift is enabled" )} + { ~shiftB = 0; postln("shift is disabled" )} + }; 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); } + { msg[2] == 0} { ~oPB[0].set(\rate, 16); } + { msg[2] == 1} { ~oPB[1].set(\rate, 14); } + { msg[2] == 2} { ~oPB[2].set(\rate, 12); } + { msg[2] == 3} { ~oPB[3].set(\rate, 10); } + { msg[2] == 4} { ~oPB[4].set(\rate, 8); } + { msg[2] == 5} { ~oPB[5].set(\rate, 6); } + { msg[2] == 6} { ~oPB[6].set(\rate, 4); } + { msg[2] == 7} { ~oPB[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; }; diff --git a/sc/samples/green/bowl1.wav b/sc/samples/green/bowl1.wav deleted file mode 100644 index cd1d3a4..0000000 Binary files a/sc/samples/green/bowl1.wav and /dev/null differ