UNPKG

video-bubbles

Version:

<img src="images/bubbles-logo.svg" alt="Bubbles logo" width="50%" />

125 lines (106 loc) 3.71 kB
/* Copyright 2019 Colin Clark Licensed under the MIT license. https://github.com/colinbdclark/bubbles/raw/master/LICENSE */ "use strict"; var bubbles = fluid.registerNamespace("bubbles"); fluid.defaults("bubbles.midiSource", { gradeNames: "fluid.modelComponent", ports: 0, model: { numActiveNotes: 0, notes: "@expand:bubbles.midiSource.initMIDIModel(128, 0)", controls: "@expand:bubbles.midiSource.initMIDIModel(128, 0)" }, modelListeners: { "notes.*": { excludeSource: "init", funcName: "bubbles.midiSource.recordNumActiveNotes", args: ["{that}", "{change}"] } }, components: { sender: { type: "fluid.mustBeOverridden" } }, events: { control: "{sender}.events.control", noteOn: "{sender}.events.noteOn", noteOff: "{sender}.events.noteOff" }, listeners: { "control.mapToModel": { funcName: "bubbles.midiSource.modelizeMessage", args: [ "controls", "number", "value", "{arguments}.0", "{that}.applier" ] }, "noteOn.mapToModel": { funcName: "bubbles.midiSource.modelizeMessage", args: [ "notes", "note", "velocity", "{arguments}.0", "{that}.applier" ] }, "noteOff.mapToModel": { funcName: "bubbles.midiSource.modelizeNoteOffMessage", args: [ "notes", "note", "{arguments}.0", "{that}.applier" ] } } }); bubbles.midiSource.recordNumActiveNotes = function (that, change) { if (change.value > 0 && change.oldValue === 0) { that.applier.change("numActiveNotes", that.model.numActiveNotes + 1); } else if (change.value === 0 && change.oldValue > 0) { that.applier.change("numActiveNotes", that.model.numActiveNotes - 1); } }; // Save garbage, reuse the change segments array. bubbles.midiSource.messageChangeSegs = new Array(2); bubbles.midiSource.applyMIDIMessageValue = function (firstSeg, secondSegKey, msg, value, applier) { bubbles.midiSource.messageChangeSegs[0] = firstSeg; bubbles.midiSource.messageChangeSegs[1] = msg[secondSegKey]; applier.change(bubbles.midiSource.messageChangeSegs, value); }; bubbles.midiSource.modelizeMessage = function (firstSeg, secondSegKey, valueKey, msg, applier) { var value = msg[valueKey]; bubbles.midiSource.applyMIDIMessageValue(firstSeg, secondSegKey, msg, value, applier); }; bubbles.midiSource.modelizeNoteOffMessage = function (firstSeg, secondSegKey, msg, applier) { // Regardless of the incoming release velocity, normalize the note's // velocity to zero. // // This is required due to Bubbles' assumption that any MIDI note // with a non-zero velocity is active (i.e. "on"). // A more authentic modelization of MIDI's semantic // should involve a separate boolean value in each note's model, // signifying whether or not the note is currently active. // // TODO: Bubbles should support non-zero note off velocities, // perhaps by mapping it to a fade out trigger or something? bubbles.midiSource.applyMIDIMessageValue(firstSeg, secondSegKey, msg, 0, applier); }; bubbles.midiSource.initMIDIModel = function (numKeys, initialValue) { var modelEntry = {}; for (var i = 0; i < numKeys; i++) { modelEntry[i.toString()] = initialValue; } return modelEntry; };