spessasynth_lib
Version:
MIDI and SoundFont2/DLS library for the browsers with no compromises
217 lines (198 loc) • 6.62 kB
JavaScript
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);
}
}
);
}
}
}
}