UNPKG

spessasynth_lib

Version:

MIDI and SoundFont2/DLS library for the browsers with no compromises

217 lines (198 loc) 6.62 kB
import { synthDisplayTypes } from "spessasynth_core"; /** * synth_event_handler.js * purpose: manages the synthesizer's event system, calling assigned functions when synthesizer requests dispatching the event */ /** * @typedef {Object} NoteOnCallback * @property {number} midiNote - The MIDI note number. * @property {number} channel - The MIDI channel number. * @property {number} velocity - The velocity of the note. */ /** * @typedef {Object} NoteOffCallback * @property {number} midiNote - The MIDI note number. * @property {number} channel - The MIDI channel number. */ /** * @typedef {Object} DrumChangeCallback * @property {number} channel - The MIDI channel number. * @property {boolean} isDrumChannel - Indicates if the channel is a drum channel. */ /** * @typedef {Object} ProgramChangeCallback * @property {number} channel - The MIDI channel number. * @property {number} program - The program number. * @property {number} bank - The bank number. */ /** * @typedef {Object} ControllerChangeCallback * @property {number} channel - The MIDI channel number. * @property {number} controllerNumber - The controller number. * @property {number} controllerValue - The value of the controller. */ /** * @typedef {Object} MuteChannelCallback * @property {number} channel - The MIDI channel number. * @property {boolean} isMuted - Indicates if the channel is muted. */ /** * @typedef {Object} PresetListChangeCallbackSingle * @property {string} presetName - The name of the preset. * @property {number} bank - The bank number. * @property {number} program - The program number. */ /** * @typedef {PresetListChangeCallbackSingle[]} PresetListChangeCallback - A list of preset objects. */ /** * @typedef {Object} SynthDisplayCallback * @property {Uint8Array} displayData - The data to display. * @property {synthDisplayTypes} displayType - The type of display. */ /** * @typedef {Object} PitchWheelCallback * @property {number} channel - The MIDI channel number. * @property {number} MSB - The most significant byte of the pitch-wheel value. * @property {number} LSB - The least significant byte of the pitch-wheel value. */ /** * @typedef {Object} ChannelPressureCallback * @property {number} channel - The MIDI channel number. * @property {number} pressure - The pressure value. */ /** * @typedef {Error} SoundfontErrorCallback - The error message for soundfont errors. */ /** * @typedef { * NoteOnCallback | * NoteOffCallback | * DrumChangeCallback | * ProgramChangeCallback | * ControllerChangeCallback | * MuteChannelCallback | * PresetListChangeCallback | * PitchWheelCallback | * SoundfontErrorCallback | * ChannelPressureCallback | * SynthDisplayCallback | * undefined * } EventCallbackData */ /** * @typedef { * "noteon"| * "noteoff"| * "pitchwheel"| * "controllerchange"| * "programchange"| * "channelpressure"| * "polypressure" | * "drumchange"| * "stopall"| * "newchannel"| * "mutechannel"| * "presetlistchange"| * "allcontrollerreset"| * "soundfonterror"| * "synthdisplay"} EventTypes */ export class EventHandler { /** * A new synthesizer event handler */ constructor() { /** * The main list of events * @type {Object<EventTypes, Object<string, function(EventCallbackData)>>} */ this.events = { "noteoff": {}, // called on a note off message "noteon": {}, // called on a note on message "pitchwheel": {}, // called on a pitch-wheel change "controllerchange": {}, // called on a controller change "programchange": {}, // called on a program change "channelpressure": {}, // called on a channel pressure message "polypressure": {}, // called on a poly pressure message "drumchange": {}, // called when a channel type changes "stopall": {}, // called when the synth receives stop all command "newchannel": {}, // called when a new channel is created "mutechannel": {}, // called when a channel is muted/unmuted "presetlistchange": {}, // called when the preset list changes (soundfont gets reloaded) "allcontrollerreset": {}, // called when all controllers are reset "soundfonterror": {}, // called when a soundfont parsing error occurs "synthdisplay": {} // called when there's a SysEx message to display some text }; /** * Set to 0 to disabled, otherwise in seconds * @type {number} */ this.timeDelay = 0; } /** * Adds a new event listener * @param name {EventTypes} * @param id {string} the unique identifier for the event (to delete it * @param callback {function(EventCallbackData)} */ addEvent(name, id, callback) { this.events[name][id] = callback; } // noinspection JSUnusedGlobalSymbols /** * Removes an event listener * @param name {EventTypes} * @param id {string} */ removeEvent(name, id) { delete this.events[name][id]; } /** * Calls the given event * @param name {EventTypes} * @param eventData {EventCallbackData} */ callEvent(name, eventData) { if (this.events[name]) { if (this.timeDelay > 0) { setTimeout(() => { Object.values(this.events[name]).forEach(ev => { try { ev(eventData); } catch (e) { console.error(`Error while executing an event callback for ${name}:`, e); } }); }, this.timeDelay * 1000); } else { Object.values(this.events[name]).forEach(ev => { try { ev(eventData); } catch (e) { console.error(`Error while executing an event callback for ${name}:`, e); } } ); } } } }