diff --git a/hvcc/generators/c2js/c2js.py b/hvcc/generators/c2js/c2js.py index 13e8c18..3bc47c7 100644 --- a/hvcc/generators/c2js/c2js.py +++ b/hvcc/generators/c2js/c2js.py @@ -204,9 +204,9 @@ def compile( externs=externs, pool_sizes_kb=externs["memoryPoolSizesKb"])) - pre_js_path = os.path.join(out_dir, "hv_worklet_start.js") + pre_js_path = os.path.join(out_dir, "midi_utils.js") with open(pre_js_path, "w") as f: - f.write(env.get_template("hv_worklet_start.js").render( + f.write(env.get_template("midi_utils.js").render( name=patch_name, copyright=copyright_js, externs=externs, @@ -296,4 +296,4 @@ def compile( "out_dir": out_dir, "out_file": "", "compile_time": time.time() - tick - } + } \ No newline at end of file diff --git a/hvcc/generators/c2js/template/hv_worklet.js b/hvcc/generators/c2js/template/hv_worklet.js index 2f14581..eec2471 100644 --- a/hvcc/generators/c2js/template/hv_worklet.js +++ b/hvcc/generators/c2js/template/hv_worklet.js @@ -205,4 +205,4 @@ var tableHashes = { {%- endfor %} }; -registerProcessor("{{name}}_AudioLibWorklet", {{name}}_AudioLibWorklet); \ No newline at end of file +registerProcessor("{{name}}_AudioLibWorklet", {{name}}_AudioLibWorklet); diff --git a/hvcc/generators/c2js/template/hv_worklet_start.js b/hvcc/generators/c2js/template/hv_worklet_start.js index 04df36b..e9cff20 100644 --- a/hvcc/generators/c2js/template/hv_worklet_start.js +++ b/hvcc/generators/c2js/template/hv_worklet_start.js @@ -8,156 +8,4 @@ var self = { function importScripts(){ console.warn('importScripts should not be called in an AudioWorklet', arguments); -} - -// midi_utils.js - -function sendMidiIn(hv_context, message) { - if (hv_context) { - var command = message[0] & 0xF0; - var channel = message[0] & 0x0F; - var data1 = message[1]; - var data2 = message[2]; - - // all events to [midiin] - for (var i = 1; i <= 2; i++) { - _hv_sendMessageToReceiverFF(hv_context, HV_HASH_MIDIIN, 0, - message[i], - channel - ); - } - - // realtime events to [midirealtimein] - if (MIDI_REALTIME.includes(message[0])) { - _hv_sendMessageToReceiverFF(hv_context, HV_HASH_MIDIREALTIMEIN, 0, - message[0] - ); - } - - switch(command) { - case 0x80: // note off - _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_NOTEIN, 0, - data1, - 0, - channel); - break; - case 0x90: // note on - _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_NOTEIN, 0, - data1, - data2, - channel); - break; - case 0xA0: // polyphonic aftertouch - _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_POLYTOUCHIN, 0, - data2, // pressure - data1, // note - channel); - break; - case 0xB0: // control change - _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_CTLIN, 0, - data2, // value - data1, // cc number - channel); - break; - case 0xC0: // program change - _hv_sendMessageToReceiverFF(hv_context, HV_HASH_PGMIN, 0, - data1, - channel); - break; - case 0xD0: // aftertouch - _hv_sendMessageToReceiverFF(hv_context, HV_HASH_TOUCHIN, 0, - data1, - channel); - break; - case 0xE0: // pitch bend - // combine 7bit lsb and msb into 32bit int - var value = (data2 << 7) | data1; - _hv_sendMessageToReceiverFF(hv_context, HV_HASH_BENDIN, 0, - value, - channel); - break; - default: - // console.error('No handler for midi message: ', message); - } - } - } - -function midiOutMsg(sendName, msg) { - switch (sendName) { - case "__hv_noteout": - var note = _hv_msg_getFloat(msg, 0); - var velocity = _hv_msg_getFloat(msg, 1); - var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports - return [ - ((velocity > 0) ? 144 : 128) | channel, - note, - velocity - ] - case "__hv_ctlout": - var value = _hv_msg_getFloat(msg, 0); - var cc = _hv_msg_getFloat(msg, 1); - var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports - return [ - 176 | channel, - cc, - value - ] - case "__hv_pgmout": - var program = _hv_msg_getFloat(msg, 0); - var channel = _hv_msg_getFloat(msg, 1) % 16; // no pd midi ports - return [ - 192 | channel, - program - ] - case "__hv_touchout": - var pressure = _hv_msg_getFloat(msg, 0); - var channel = _hv_msg_getFloat(msg, 1) % 16; // no pd midi ports - return [ - 208 | channel, - pressure, - ] - case "__hv_polytouchout": - var value = _hv_msg_getFloat(msg, 0); - var note = _hv_msg_getFloat(msg, 1); - var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midiports - return[ - 160 | channel, - note, - value - ] - case "__hv_bendout": - var value = _hv_msg_getFloat(msg, 0); - let lsb = value & 0x7F; - let msb = (value >> 7) & 0x7F; - var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports - return [ - 224 | channel, - lsb, - msb - ] - case "__hv_midiout": - let firstByte = _hv_msg_getFloat(msg, 0); - return (firstByte === 192 || firstByte === 208) ? - [_hv_msg_getFloat(msg, 0), _hv_msg_getFloat(msg, 1)] : - [_hv_msg_getFloat(msg, 0), _hv_msg_getFloat(msg, 1), _hv_msg_getFloat(msg, 2)]; - default: - console.warn(`Unhandled sendName: ${sendName}`); - return []; - } -} - - -/* -* MIDI Constants -*/ - -const HV_HASH_NOTEIN = 0x67E37CA3; -const HV_HASH_CTLIN = 0x41BE0f9C; -const HV_HASH_POLYTOUCHIN = 0xBC530F59; -const HV_HASH_PGMIN = 0x2E1EA03D; -const HV_HASH_TOUCHIN = 0x553925BD; -const HV_HASH_BENDIN = 0x3083F0F7; -const HV_HASH_MIDIIN = 0x149631bE; -const HV_HASH_MIDIREALTIMEIN = 0x6FFF0BCF; - -const MIDI_REALTIME = [0xF8, 0xFA, 0xFB, 0xFC, 0xFE, 0xFF]; \ No newline at end of file +} \ No newline at end of file diff --git a/hvcc/generators/c2js/template/hv_wrapper.js b/hvcc/generators/c2js/template/hv_wrapper.js index 5c5d9ce..13a6324 100644 --- a/hvcc/generators/c2js/template/hv_wrapper.js +++ b/hvcc/generators/c2js/template/hv_wrapper.js @@ -22,6 +22,7 @@ var AudioLibLoader = function() { * @param options.sendHook (Function) callback that gets triggered for messages sent via @hv_param/@hv_event */ AudioLibLoader.prototype.init = function(options) { + // use provided web audio context or create a new one this.webAudioContext = options.webAudioContext || (new (window.AudioContext || window.webkitAudioContext || null)); @@ -307,4 +308,4 @@ var tableHashes = { } } -Module.{{name}}_AudioLib = {{name}}_AudioLib; \ No newline at end of file +Module.{{name}}_AudioLib = {{name}}_AudioLib; diff --git a/hvcc/generators/c2js/template/midi_utils.js b/hvcc/generators/c2js/template/midi_utils.js new file mode 100644 index 0000000..63e38e8 --- /dev/null +++ b/hvcc/generators/c2js/template/midi_utils.js @@ -0,0 +1,150 @@ +// midi_utils.js + +function sendMidiIn(hv_context, message) { + if (hv_context) { + var command = message[0] & 0xF0; + var channel = message[0] & 0x0F; + var data1 = message[1]; + var data2 = message[2]; + + // all events to [midiin] + for (var i = 1; i <= 2; i++) { + _hv_sendMessageToReceiverFF(hv_context, HV_HASH_MIDIIN, 0, + message[i], + channel + ); + } + + // realtime events to [midirealtimein] + if (MIDI_REALTIME.includes(message[0])) { + _hv_sendMessageToReceiverFF(hv_context, HV_HASH_MIDIREALTIMEIN, 0, + message[0] + ); + } + + switch(command) { + case 0x80: // note off + _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_NOTEIN, 0, + data1, + 0, + channel); + break; + case 0x90: // note on + _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_NOTEIN, 0, + data1, + data2, + channel); + break; + case 0xA0: // polyphonic aftertouch + _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_POLYTOUCHIN, 0, + data2, // pressure + data1, // note + channel); + break; + case 0xB0: // control change + _hv_sendMessageToReceiverFFF(hv_context, HV_HASH_CTLIN, 0, + data2, // value + data1, // cc number + channel); + break; + case 0xC0: // program change + _hv_sendMessageToReceiverFF(hv_context, HV_HASH_PGMIN, 0, + data1, + channel); + break; + case 0xD0: // aftertouch + _hv_sendMessageToReceiverFF(hv_context, HV_HASH_TOUCHIN, 0, + data1, + channel); + break; + case 0xE0: // pitch bend + // combine 7bit lsb and msb into 32bit int + var value = (data2 << 7) | data1; + _hv_sendMessageToReceiverFF(hv_context, HV_HASH_BENDIN, 0, + value, + channel); + break; + default: + // console.error('No handler for midi message: ', message); + } + } + } + +function midiOutMsg(sendName, msg) { + switch (sendName) { + case "__hv_noteout": + var note = _hv_msg_getFloat(msg, 0); + var velocity = _hv_msg_getFloat(msg, 1); + var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports + return [ + ((velocity > 0) ? 144 : 128) | channel, + note, + velocity + ] + case "__hv_ctlout": + var value = _hv_msg_getFloat(msg, 0); + var cc = _hv_msg_getFloat(msg, 1); + var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports + return [ + 176 | channel, + cc, + value + ] + case "__hv_pgmout": + var program = _hv_msg_getFloat(msg, 0); + var channel = _hv_msg_getFloat(msg, 1) % 16; // no pd midi ports + return [ + 192 | channel, + program + ] + case "__hv_touchout": + var pressure = _hv_msg_getFloat(msg, 0); + var channel = _hv_msg_getFloat(msg, 1) % 16; // no pd midi ports + return [ + 208 | channel, + pressure, + ] + case "__hv_polytouchout": + var value = _hv_msg_getFloat(msg, 0); + var note = _hv_msg_getFloat(msg, 1); + var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midiports + return[ + 160 | channel, + note, + value + ] + case "__hv_bendout": + var value = _hv_msg_getFloat(msg, 0); + let lsb = value & 0x7F; + let msb = (value >> 7) & 0x7F; + var channel = _hv_msg_getFloat(msg, 2) % 16; // no pd midi ports + return [ + 224 | channel, + lsb, + msb + ] + case "__hv_midiout": + let firstByte = _hv_msg_getFloat(msg, 0); + return (firstByte === 192 || firstByte === 208) ? + [_hv_msg_getFloat(msg, 0), _hv_msg_getFloat(msg, 1)] : + [_hv_msg_getFloat(msg, 0), _hv_msg_getFloat(msg, 1), _hv_msg_getFloat(msg, 2)]; + default: + console.warn(`Unhandled sendName: ${sendName}`); + return []; + } +} + +/* + * MIDI Constants + */ + +const HV_HASH_NOTEIN = 0x67E37CA3; +const HV_HASH_CTLIN = 0x41BE0f9C; +const HV_HASH_POLYTOUCHIN = 0xBC530F59; +const HV_HASH_PGMIN = 0x2E1EA03D; +const HV_HASH_TOUCHIN = 0x553925BD; +const HV_HASH_BENDIN = 0x3083F0F7; +const HV_HASH_MIDIIN = 0x149631bE; +const HV_HASH_MIDIREALTIMEIN = 0x6FFF0BCF; + +const MIDI_REALTIME = [0xF8, 0xFA, 0xFB, 0xFC, 0xFE, 0xFF];