I took my webMidi experiments and tried to implement webMidi for Emscripten and OF with a more general approach. Basically, you just need to add the --bind flag to the Emscripten compiler and replace the template.html with the one that is in the bin folder.
For the webMidi functionality I started with this (great) code: https://github.com/cwilso/midi-synth/blob/master/js/midi.js added midi out and made some adjustments…
Here is the code (it is put upon the graphicsExample…): https://github.com/Jonathhhan/Pure-Data-Ofelia-Emscripten/tree/main/webMidiExample
And here you can try it (midi out works with mousePressed and mouseReleased):
https://webmidiexample.handmadeproductions.de/
It could be quite simple to implement…
On the OF side the only changes are in ofApp.cpp, basically two functions (I tried to keep it simple - and maybe some of the midi functionality is missing in my implementation).
For midi in:
void midiIn(int channel, int pitch, int velocity) {
inChannel = channel;
inPitch = pitch;
inVelocity = velocity;
}
EMSCRIPTEN_BINDINGS(Module) {
emscripten::function("midiIn", &midiIn);
}
and for midi out:
EM_ASM_(window["setMidiOut"] = ([128, 52, 32]));
In html.template I added those 3 lines:
<b>Input Ports: </b><select id="midiIn"><option>-no MIDI-</option></select><br></p>
<b>Outputs Ports: </b><select id="midiOut"><option>-no MIDI-</option></select></p>
<script type="text/javascript" src="midi.js"></script>
Sadly, webMidi does not seem to work with Firefox, but with Chrome, for example, it works very well (latency seems quite small)…
(could also be possible to choose the midi device from the Emscripten app, but didnt figured that out yet - and I made a selector for GM Instruments, but thats only needed in some cases…)
And this way its possible to send midiOut with variable array length:
size_t lengthOfArray = sizeof array / sizeof array[0];
EM_ASM_(
var data = new Uint32Array(HEAPU32.buffer, $0, $1);
window["setMidiOut"] = data, array, lengthOfArray);
}
And this for midiIn with variable length:
void midiIn(std::string ev) {
unsigned char* uEv = (unsigned char*)ev.c_str();
inChannel= uEv[0];
inPitch= uEv[1];
inVelocity= uEv[2];
}
EMSCRIPTEN_BINDINGS(Module) {
emscripten::function("midiIn", &midiIn);
}
(Of course it is also possible to send other data between C++ and Java Script with the same methods - and, I am not sure if they are well written. I am still a C++ beginner…)