//http://fortyseveneffects.github.io/arduino_midi_library/a00041.html//http://fortyseveneffects.github.io/arduino_midi_library/a00043.html
OSCFunc.trace(true, true);
OSCFunc.trace(false);
n= NetAddr("f0mid.local", 18120); //ip of esp8266
n.sendMsg(\ip, 192, 168, 1, 99); //receiver ip (laptop - by default this is x.x.x.255 (broadcast))
n.sendMsg(\port, 57120); //set receiver port (by default this is 57120)
n.sendMsg(\thru, 0); //off
n.sendMsg(\thru, 1); //full (default)
n.sendMsg(\thru, 2); //same channel
n.sendMsg(\thru, 3); //different channel
n.sendMsg(\noteOn, 66, 127, 1); //(note, velo, chan)
n.sendMsg(\noteOff, 66, 0, 1); //(note, velo, chan)
n.sendMsg(\afterTouchPoly, 50, 60, 3); //poly pressure (note, press, chan)
n.sendMsg(\controlChange, 1, 64, 3); //(num, val, chan)
n.sendMsg(\programChange, 10, 4); //(num, chan) note the -1 offset
n.sendMsg(\afterTouchChannel, 40, 2); //(press, chan)
n.sendMsg(\pitchBend, -8000, 1); //(bend, chan) -8192 - 8191
n.sendMsg(\sysEx, 240, 14, 5, 0, 5, 247); //(sysex) - 240 a b c d e ... 247
//realtime
(
var clock= 0xf8; //248
var start= 0xfa; //250
var continue= 0xfb; //251
var stop= 0xfc; //252
Routine.run({
n.sendMsg(\realTime, start);
100.do{
n.sendMsg(\realTime, clock);
0.02.wait;
};
n.sendMsg(\realTime, stop);
1.wait;
n.sendMsg(\realTime, continue);
100.do{
n.sendMsg(\realTime, clock);
0.02.wait;
};
n.sendMsg(\realTime, stop);
});
)
n.sendMsg(\realTime, 0xfe); //active sensing
n.sendMsg(\realTime, 0xff); //system reset
n.sendMsg(\songPosition, 100);
n.sendMsg(\songSelect, 3);
n.sendMsg(\tuneRequest);
n.sendMsg(\beginNrpn, 10, 3); //(number, channel)
n.sendMsg(\nrpnDecrement, 40, 3); //(amount, channel)
n.sendMsg(\nrpnIncrement, 30, 3); //(amount, channel)
n.sendMsg(\endNrpn, 3); //(channel)
n.sendMsg(\beginRpn, 10, 4); //(number, channel)
n.sendMsg(\rpnDecrement, 40, 4); //(amount, channel)
n.sendMsg(\rpnIncrement, 30, 4); //(amount, channel)
n.sendMsg(\endRpn, 4); //(channel)
//--simple midi synth example
(
s.latency= 0.02;
s.waitForBoot{
var busBend= Bus.control(s);
var busCF= Bus.control(s);
var busRQ= Bus.control(s);
var busVol= Bus.control(s);
var busPan= Bus.control(s);
busBend.value= 0;
busCF.value= 1000;
busRQ.value= 0.5;
busVol.value= 0.5;
busPan.value= 0;
SynthDef(\note, {|freq= 400, amp= 0.5, gate= 1, busBend, busCF, busRQ, busVol, busPan|
var env= EnvGen.ar(Env.adsr(0.01, 1, 0.85, 0.1), gate, amp, doneAction:2);
var bend= In.kr(busBend).lag(0.01);
var cf= In.kr(busCF).lag(0.01);
var rq= In.kr(busRQ).lag(0.01);
var vol= In.kr(busVol).lag(0.01);
var pan= In.kr(busPan).lag(0.01);
var src= BLowPass4.ar(VarSaw.ar((freq+bend).midicps), cf, rq);
OffsetOut.ar(0, Pan2.ar(src*env, pan, vol));
}).add;
d= ();
OSCdef(\f0mid, {|msg|
switch(msg[1],
\activeSensing, {},
\noteOn, {
d.at(msg[2]).set(\gate, 0);
d.put(msg[2], Synth(\note, [
\freq, msg[2],
\amp, msg[3].lincurve(0, 127, 0, 0.75, 4),
\busBend, busBend,
\busCF, busCF,
\busRQ, busRQ,
\busVol, busVol,
\busPan, busPan
]));
},
\noteOff, {
d.at(msg[2]).set(\gate, 0);
d.put(msg[2], nil);
},
\pitchBend, {
busBend.value= msg[2]/8192;
},
\controlChange, {
switch(msg[2],
1, {
busCF.value= msg[3].linexp(0, 127, 400, 4000);
},
7, {
busVol.value= msg[3].lincurve(0, 127, 0, 1, 0);
},
10, {
busPan.value= msg[3].linlin(0, 127, -1, 1);
},
74, {
busRQ.value= msg[3].linlin(0, 127, 2, 0.1);
},
{("todo control: "+msg).postln}
);
},
{("todo command: "+msg).postln}
);
}, \f0mid);
CmdPeriod.doOnce({
busBend.free;
busCF.free;
busRQ.free;
busVol.free;
busPan.free;
});
};
)
//mtc - receive
(
var a= MIDISMPTEAssembler({|time, format, dropFrame, srcID|
[time, format, dropFrame, srcID].postln;
//time.postln;
});
OSCdef(\f0mid, {|msg, time, addr|
var chan, valu;
if(msg[1]==\mtcQF, {
chan= msg[2].rightShift(4); //nibble high
valu= msg[2].bitAnd(15); //nibble low
if(chan==7, {
valu= switch(valu,
6, {valu= 96}, //30fps
4, {valu= 64}, //30fps drop
2, {valu= 32}, //25fps
0, {valu= 0} //24fps
);
});
a.value(addr.addr.bitAnd(255), chan, valu);
});
}, \f0mid);
)
//mtc - send (kind of works - wslib quark required)
(
var startSec= 0;
var t= Main.elapsedTime-startSec;
var a= SMPTE(0, 30);
Routine.run({
var chan= 0, valu= 0;
inf.do{
a.newSeconds(Main.elapsedTime-t);
switch(chan,
0, {valu= a.frames.asInteger.bitAnd(15)},
1, {valu= a.frames.asInteger.rightShift(4)},
2, {valu= a.seconds.asInteger.bitAnd(15)},
3, {valu= a.seconds.asInteger.rightShift(4)},
4, {valu= a.minutes.asInteger.bitAnd(15)},
5, {valu= a.minutes.asInteger.rightShift(4)},
6, {valu= a.hours.asInteger.bitAnd(15)},
7, {
valu= a.hours.asInteger.bitAnd(1).rightShift(4);
switch(a.fps,
30, {valu= valu.bitOr(6)}, //30fps
//30fps drop not supported
25, {valu= valu.bitOr(2)}, //25fps
//24, {valu= valu.bitOr(0)} //24fps
);
}
);
n.sendMsg(\mtcQF, chan.leftShift(4)+valu.bitAnd(15));
chan= chan+1;
if(chan==8, {
chan= 0;
});
(1/(a.fps*4)).wait;
};
});
)