openframeworks / openFrameworks

openFrameworks is a community-developed cross platform toolkit for creative coding in C++.
http://openframeworks.cc
Other
9.83k stars 2.56k forks source link

About webMidi and Emscripten #7221

Open Jonathhhan opened 1 year ago

Jonathhhan commented 1 year ago

I added webMidi to OF / Emscripten and search for a better implementation. This is how I did it: Add PLATFORM_LDFLAGS += --post-js $(OF_ADDONS_PATH)/ofxEmscripten/libs/html5audio/lib/emscripten/library_webMidi.js to config.emscripten.default.mk. This is the webMidi library that I use: https://github.com/Jonathhhan/openFrameworks/blob/AudioWorklet/addons/ofxEmscripten/libs/html5audio/lib/emscripten/library_webMidi.js And this is the original file (I added output): https://github.com/cwilso/midi-synth/blob/master/js/midi.js

And I had to add this:

<b>Input Ports:&nbsp;</b><select id="midiIn"><option>-no MIDI-</option></select><br></p>
<b>Outputs Ports:&nbsp;</b><select id="midiOut"><option>-no MIDI-</option></select></p>

to template.html (for recognizing and selecting midi devices).

Then I can just send MIDI from ofApp.cpp to the MIDI device like this (for example):

            int array[3] = {val_0, val_1, val_2};
            size_t lengthOfArray = sizeof array / sizeof array[0];
            EM_ASM_(
            var data = new Uint32Array(HEAPU32.buffer, $0, $1);
            sendMIDI(data), array, lengthOfArray);

The most crucial part is how to select the MIDI devices (it all happens on the JS side now), but also other parts can be optimized. I guess, all in all it should not be very difficult to implement.

Jonathhhan commented 1 year ago

Here is an example how to list the midi devices in OF:

    EM_ASM_INT({
        function onMIDISuccess(midiAccess) {
            // console.log(midiAccess);
            var inputDeviceCount = midiAccess.inputs.size;
            if(inputDeviceCount > 0) {
                var inputs=midiAccess.inputs.values();
                for ( var input = inputs.next(); input && !input.done; input = inputs.next()) {
                    var deviceName = input.value.name;
                    console.log(deviceName);
                }
            }
        }
        function onMIDIFailure(e) {
            console.log('No access to MIDI devices' + e);
        }
        if(navigator.requestMIDIAccess)
            navigator.requestMIDIAccess({ sysex: false }).then(onMIDISuccess, onMIDIFailure);
        else
            alert("No MIDI support in your browser.");
    });

Maybe an own class (something like ofxEmscriptenWebMidi) would make sense. But I would keep it rather simple. Methods for list in-devices / list out-devices / select in-devices / select in-devices could be enough.