Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

c2js - midi output and device select #204

Merged
merged 10 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions hvcc/generators/c2js/c2js.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,20 @@ def compile(
externs=externs,
pool_sizes_kb=externs["memoryPoolSizesKb"]))

pre_js_path = os.path.join(out_dir, "midi_utils.js")
with open(pre_js_path, "w") as f:
f.write(env.get_template("midi_utils.js").render(
name=patch_name,
copyright=copyright_js,
externs=externs,
pool_sizes_kb=externs["memoryPoolSizesKb"]))

js_path = cls.run_emscripten(c_src_dir=c_src_dir,
out_dir=out_dir,
patch_name=patch_name,
output_name=patch_name,
post_js_path=post_js_path,
pre_js_path=pre_js_path,
should_modularize=1,
environment="web")

Expand Down Expand Up @@ -241,14 +250,6 @@ def compile(
externs=externs,
pool_sizes_kb=externs["memoryPoolSizesKb"]))

pre_js_path = os.path.join(out_dir, "hv_worklet_start.js")
dromer marked this conversation as resolved.
Show resolved Hide resolved
with open(pre_js_path, "w") as f:
f.write(env.get_template("hv_worklet_start.js").render(
name=patch_name,
copyright=copyright_js,
externs=externs,
pool_sizes_kb=externs["memoryPoolSizesKb"]))

js_path = cls.run_emscripten(c_src_dir=c_src_dir,
out_dir=out_dir,
patch_name=patch_name,
Expand Down
99 changes: 13 additions & 86 deletions hvcc/generators/c2js/template/hv_worklet.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,24 @@ class {{name}}_AudioLibWorklet extends AudioWorkletProcessor {
var self = this;
// typedef void (HvSendHook_t) (HeavyContextInterface *context, const char *sendName, hv_uint32_t sendHash, const HvMessage *msg);
var sendHook = addFunction(function(context, sendName, sendHash, msg) {
// Filter out MIDI messages
const midiMessage = midiOutMsg(UTF8ToString(sendName), msg);
if (midiMessage.length > 0) {
self.port.postMessage({
type: 'midiOut',
payload: midiMessage
});
} else {
// Converts sendhook callback to (sendName, float) message
self.port.postMessage({
type: 'sendHook',
payload: [UTF8ToString(sendName), _hv_msg_getFloat(msg, 0)]
});
},
"viiii"
}
},
"viiii"
);
_hv_setSendHook(this.heavyContext, sendHook);
_hv_setSendHook(this.heavyContext, sendHook);
dromer marked this conversation as resolved.
Show resolved Hide resolved
}

sendEvent(name) {
Expand All @@ -132,73 +141,7 @@ class {{name}}_AudioLibWorklet extends AudioWorkletProcessor {
}

sendMidi(message) {
if (this.heavyContext) {
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(this.heavyContext, HV_HASH_MIDIIN, 0,
message[i],
channel
);
}

// realtime events to [midirealtimein]
if (MIDI_REALTIME.includes(message[0])) {
_hv_sendMessageToReceiverFF(this.heavyContext, HV_HASH_MIDIREALTIMEIN, 0,
message[0]
);
}

switch(command) {
case 0x80: // note off
_hv_sendMessageToReceiverFFF(this.heavyContext, HV_HASH_NOTEIN, 0,
data1,
0,
channel);
break;
case 0x90: // note on
_hv_sendMessageToReceiverFFF(this.heavyContext, HV_HASH_NOTEIN, 0,
data1,
data2,
channel);
break;
case 0xA0: // polyphonic aftertouch
_hv_sendMessageToReceiverFFF(this.heavyContext, HV_HASH_POLYTOUCHIN, 0,
data2, // pressure
data1, // note
channel);
break;
case 0xB0: // control change
_hv_sendMessageToReceiverFFF(this.heavyContext, HV_HASH_CTLIN, 0,
data2, // value
data1, // cc number
channel);
break;
case 0xC0: // program change
_hv_sendMessageToReceiverFF(this.heavyContext, HV_HASH_PGMIN, 0,
data1,
channel);
break;
case 0xD0: // aftertouch
_hv_sendMessageToReceiverFF(this.heavyContext, 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(this.heavyContext, HV_HASH_BENDIN, 0,
value,
channel);
break;
default:
// console.error('No handler for midi message: ', message);
}
}
sendMidiIn(this.heavyContext, message);
}

sendStringToReceiver(name, message) {
Expand Down Expand Up @@ -263,19 +206,3 @@ var tableHashes = {
};

registerProcessor("{{name}}_AudioLibWorklet", {{name}}_AudioLibWorklet);


/*
* 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];
2 changes: 1 addition & 1 deletion hvcc/generators/c2js/template/hv_worklet_start.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ var self = {

function importScripts(){
console.warn('importScripts should not be called in an AudioWorklet', arguments);
}
}
99 changes: 13 additions & 86 deletions hvcc/generators/c2js/template/hv_wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -43,6 +44,8 @@ AudioLibLoader.prototype.init = function(options) {
options.printHook(event.data.payload);
} else if (event.data.type === 'sendHook' && options.sendHook) {
options.sendHook(event.data.payload[0], event.data.payload[1]);
} else if (event.data.type === 'midiOut' && options.sendHook) {
options.sendHook("midiOutMessage", event.data.payload);
} else {
console.log('Unhandled message from {{name}}_AudioLibWorklet:', event.data);
}
Expand All @@ -54,7 +57,7 @@ AudioLibLoader.prototype.init = function(options) {
sampleRate: this.webAudioContext.sampleRate,
blockSize: blockSize,
printHook: options.printHook,
sendHook: options.sendHook
sendHook: options.sendHook,
dromer marked this conversation as resolved.
Show resolved Hide resolved
});
this.audiolib = instance;
this.webAudioProcessor = this.webAudioContext.createScriptProcessor(blockSize, instance.getNumInputChannels(), Math.max(instance.getNumOutputChannels(), 1));
Expand Down Expand Up @@ -244,8 +247,14 @@ var tableHashes = {
if (hook) {
// typedef void (HvSendHook_t) (HeavyContextInterface *context, const char *sendName, hv_uint32_t sendHash, const HvMessage *msg);
var sendHook = addFunction(function(context, sendName, sendHash, msg) {
// Converts sendhook callback to (sendName, float) message
hook(UTF8ToString(sendName), _hv_msg_getFloat(msg, 0));
// Filter out MIDI messages
const midiMessage = midiOutMsg(UTF8ToString(sendName), msg);
if (midiMessage.length > 0) {
hook("midiOutMessage", midiMessage);
} else {
// Converts sendhook callback to (sendName, float) message
hook(UTF8ToString(sendName), _hv_msg_getFloat(msg, 0));
}
},
"viiii"
);
Expand All @@ -260,73 +269,7 @@ var tableHashes = {
}

{{name}}_AudioLib.prototype.sendMidi = function(message) {
if (this.heavyContext) {
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(this.heavyContext, HV_HASH_MIDIIN, 0,
message[i],
channel
);
}

// realtime events to [midirealtimein]
if (MIDI_REALTIME.includes(message[0])) {
_hv_sendMessageToReceiverFF(this.heavyContext, HV_HASH_MIDIREALTIMEIN, 0,
message[0]
);
}

switch(command) {
case 0x80: // note off
_hv_sendMessageToReceiverFFF(this.heavyContext, HV_HASH_NOTEIN, 0,
data1,
0,
channel);
break;
case 0x90: // note on
_hv_sendMessageToReceiverFFF(this.heavyContext, HV_HASH_NOTEIN, 0,
data1,
data2,
channel);
break;
case 0xA0: // polyphonic aftertouch
_hv_sendMessageToReceiverFFF(this.heavyContext, HV_HASH_POLYTOUCHIN, 0,
data2, // pressure
data1, // note
channel);
break;
case 0xB0: // control change
_hv_sendMessageToReceiverFFF(this.heavyContext, HV_HASH_CTLIN, 0,
data2, // value
data1, // cc number
channel);
break;
case 0xC0: // program change
_hv_sendMessageToReceiverFF(this.heavyContext, HV_HASH_PGMIN, 0,
data1,
channel);
break;
case 0xD0: // aftertouch
_hv_sendMessageToReceiverFF(this.heavyContext, 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(this.heavyContext, HV_HASH_BENDIN, 0,
value,
channel);
break;
default:
// console.error('No handler for midi message: ', message);
}
}
sendMidiIn(this.heavyContext, message);
}

{{name}}_AudioLib.prototype.setFloatParameter = function(name, floatValue) {
Expand Down Expand Up @@ -366,19 +309,3 @@ var tableHashes = {
}

Module.{{name}}_AudioLib = {{name}}_AudioLib;


/*
* 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];
Loading
Loading