spessasynth_lib 3.23.14 → 3.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@types/sequencer/sequencer.d.ts +63 -28
- package/@types/sequencer/worklet_sequencer/sequencer_message.d.ts +1 -0
- package/@types/synthetizer/synth_event_handler.d.ts +157 -60
- package/README.md +1 -1
- package/midi_parser/midi_loader.js +43 -23
- package/package.json +1 -1
- package/sequencer/sequencer.js +134 -77
- package/sequencer/worklet_sequencer/process_event.js +4 -1
- package/sequencer/worklet_sequencer/process_tick.js +4 -4
- package/sequencer/worklet_sequencer/sequencer_message.js +2 -1
- package/synthetizer/audio_effects/effects_config.js +0 -0
- package/synthetizer/synth_event_handler.js +92 -71
- package/synthetizer/worklet_processor.min.js +11 -12
- package/synthetizer/worklet_system/message_protocol/message_sending.js +1 -1
- package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +77 -0
package/sequencer/sequencer.js
CHANGED
|
@@ -12,7 +12,8 @@ import { BasicMIDI } from "../midi_parser/basic_midi.js";
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* sequencer.js
|
|
15
|
-
* purpose: plays back the midi file decoded by midi_loader.js, including support for
|
|
15
|
+
* purpose: plays back the midi file decoded by midi_loader.js, including support for multichannel midis
|
|
16
|
+
* (adding channels when more than one midi port is detected)
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -63,7 +64,7 @@ export class Sequencer
|
|
|
63
64
|
* Fires on text event
|
|
64
65
|
* @type {function}
|
|
65
66
|
* @param data {Uint8Array} the data text
|
|
66
|
-
* @param type {number} the status byte of the message (the meta
|
|
67
|
+
* @param type {number} the status byte of the message (the meta-status byte)
|
|
67
68
|
* @param lyricsIndex {number} if the text is a lyric, the index of the lyric in midiData.lyrics, otherwise -1
|
|
68
69
|
*/
|
|
69
70
|
onTextEvent;
|
|
@@ -79,6 +80,51 @@ export class Sequencer
|
|
|
79
80
|
*/
|
|
80
81
|
onSongEnded = {};
|
|
81
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Fires on tempo change
|
|
85
|
+
* @type {Object<string, function(number)>}
|
|
86
|
+
*/
|
|
87
|
+
onTempoChange = {};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Current song's tempo in BPM
|
|
91
|
+
* @type {number}
|
|
92
|
+
*/
|
|
93
|
+
currentTempo = 120;
|
|
94
|
+
/**
|
|
95
|
+
* Current song index
|
|
96
|
+
* @type {number}
|
|
97
|
+
*/
|
|
98
|
+
songIndex = 0;
|
|
99
|
+
/**
|
|
100
|
+
* @type {function(BasicMIDI)}
|
|
101
|
+
* @private
|
|
102
|
+
*/
|
|
103
|
+
_getMIDIResolve = undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Indicates if the current midiData property has fake data in it (not yet loaded)
|
|
106
|
+
* @type {boolean}
|
|
107
|
+
*/
|
|
108
|
+
hasDummyData = true;
|
|
109
|
+
/**
|
|
110
|
+
* Indicates whether the sequencer has finished playing a sequence
|
|
111
|
+
* @type {boolean}
|
|
112
|
+
*/
|
|
113
|
+
isFinished = false;
|
|
114
|
+
/**
|
|
115
|
+
* The current sequence's length, in seconds
|
|
116
|
+
* @type {number}
|
|
117
|
+
*/
|
|
118
|
+
duration = 0;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Indicates if the sequencer is paused.
|
|
122
|
+
* Paused if a number, undefined if playing
|
|
123
|
+
* @type {undefined|number}
|
|
124
|
+
* @private
|
|
125
|
+
*/
|
|
126
|
+
pausedTime = undefined;
|
|
127
|
+
|
|
82
128
|
/**
|
|
83
129
|
* Creates a new Midi sequencer for playing back MIDI files
|
|
84
130
|
* @param midiBinaries {MIDIFile[]} List of the buffers of the MIDI files
|
|
@@ -97,47 +143,6 @@ export class Sequencer
|
|
|
97
143
|
*/
|
|
98
144
|
this.absoluteStartTime = this.synth.currentTime;
|
|
99
145
|
|
|
100
|
-
/**
|
|
101
|
-
* @type {function(BasicMIDI)}
|
|
102
|
-
* @private
|
|
103
|
-
*/
|
|
104
|
-
this._getMIDIResolve = undefined;
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Controls the playback's rate
|
|
108
|
-
* @type {number}
|
|
109
|
-
*/
|
|
110
|
-
this._playbackRate = 1;
|
|
111
|
-
|
|
112
|
-
this.songIndex = 0;
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Indicates if the current midiData property has dummy data in it (not yet loaded)
|
|
116
|
-
* @type {boolean}
|
|
117
|
-
*/
|
|
118
|
-
this.hasDummyData = true;
|
|
119
|
-
|
|
120
|
-
this._loop = true;
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Indicates whether the sequencer has finished playing a sequence
|
|
124
|
-
* @type {boolean}
|
|
125
|
-
*/
|
|
126
|
-
this.isFinished = false;
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Indicates if the sequencer is paused.
|
|
130
|
-
* Paused if a number, undefined if playing
|
|
131
|
-
* @type {undefined|number}
|
|
132
|
-
*/
|
|
133
|
-
this.pausedTime = undefined;
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* The current sequence's length, in seconds
|
|
137
|
-
* @type {number}
|
|
138
|
-
*/
|
|
139
|
-
this.duration = 0;
|
|
140
|
-
|
|
141
146
|
this.synth.sequencerCallbackFunction = this._handleMessage.bind(this);
|
|
142
147
|
|
|
143
148
|
/**
|
|
@@ -167,6 +172,49 @@ export class Sequencer
|
|
|
167
172
|
window.addEventListener("beforeunload", this.resetMIDIOut.bind(this));
|
|
168
173
|
}
|
|
169
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Internal loop marker
|
|
177
|
+
* @type {boolean}
|
|
178
|
+
* @private
|
|
179
|
+
*/
|
|
180
|
+
_loop = true;
|
|
181
|
+
|
|
182
|
+
get loop()
|
|
183
|
+
{
|
|
184
|
+
return this._loop;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
set loop(value)
|
|
188
|
+
{
|
|
189
|
+
this._sendMessage(WorkletSequencerMessageType.setLoop, value);
|
|
190
|
+
this._loop = value;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Controls the playback's rate
|
|
195
|
+
* @type {number}
|
|
196
|
+
* @private
|
|
197
|
+
*/
|
|
198
|
+
_playbackRate = 1;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @returns {number}
|
|
202
|
+
*/
|
|
203
|
+
get playbackRate()
|
|
204
|
+
{
|
|
205
|
+
return this._playbackRate;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @param value {number}
|
|
210
|
+
*/
|
|
211
|
+
set playbackRate(value)
|
|
212
|
+
{
|
|
213
|
+
this._sendMessage(WorkletSequencerMessageType.setPlaybackRate, value);
|
|
214
|
+
this.highResTimeOffset *= (value / this._playbackRate);
|
|
215
|
+
this._playbackRate = value;
|
|
216
|
+
}
|
|
217
|
+
|
|
170
218
|
/**
|
|
171
219
|
* Indicates if the sequencer should skip to first note on
|
|
172
220
|
* @return {boolean}
|
|
@@ -230,17 +278,6 @@ export class Sequencer
|
|
|
230
278
|
this._sendMessage(WorkletSequencerMessageType.setTime, time);
|
|
231
279
|
}
|
|
232
280
|
|
|
233
|
-
get loop()
|
|
234
|
-
{
|
|
235
|
-
return this._loop;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
set loop(value)
|
|
239
|
-
{
|
|
240
|
-
this._sendMessage(WorkletSequencerMessageType.setLoop, value);
|
|
241
|
-
this._loop = value;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
281
|
/**
|
|
245
282
|
* Use for visualization as it's not affected by the audioContext stutter
|
|
246
283
|
* @returns {number}
|
|
@@ -271,24 +308,6 @@ export class Sequencer
|
|
|
271
308
|
return currentPerformanceTime;
|
|
272
309
|
}
|
|
273
310
|
|
|
274
|
-
/**
|
|
275
|
-
* @returns {number}
|
|
276
|
-
*/
|
|
277
|
-
get playbackRate()
|
|
278
|
-
{
|
|
279
|
-
return this._playbackRate;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* @param value {number}
|
|
284
|
-
*/
|
|
285
|
-
set playbackRate(value)
|
|
286
|
-
{
|
|
287
|
-
this._sendMessage(WorkletSequencerMessageType.setPlaybackRate, value);
|
|
288
|
-
this.highResTimeOffset *= (value / this._playbackRate);
|
|
289
|
-
this._playbackRate = value;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
311
|
/**
|
|
293
312
|
* true if paused, false if playing or stopped
|
|
294
313
|
* @returns {boolean}
|
|
@@ -328,6 +347,16 @@ export class Sequencer
|
|
|
328
347
|
this.onTimeChange[id] = callback;
|
|
329
348
|
}
|
|
330
349
|
|
|
350
|
+
/**
|
|
351
|
+
* Adds a new event that gets called when the tempo changes
|
|
352
|
+
* @param callback {function(number)} the new tempo, in BPM
|
|
353
|
+
* @param id {string} must be unique
|
|
354
|
+
*/
|
|
355
|
+
addOnTempoChangeEvent(callback, id)
|
|
356
|
+
{
|
|
357
|
+
this.onTempoChange[id] = callback;
|
|
358
|
+
}
|
|
359
|
+
|
|
331
360
|
resetMIDIOut()
|
|
332
361
|
{
|
|
333
362
|
if (!this.MIDIout)
|
|
@@ -369,6 +398,26 @@ export class Sequencer
|
|
|
369
398
|
this._sendMessage(WorkletSequencerMessageType.changeSong, false);
|
|
370
399
|
}
|
|
371
400
|
|
|
401
|
+
/**
|
|
402
|
+
* @param type {Object<string, function>}
|
|
403
|
+
* @param params {any}
|
|
404
|
+
* @private
|
|
405
|
+
*/
|
|
406
|
+
_callEvents(type, params)
|
|
407
|
+
{
|
|
408
|
+
Object.entries(type).forEach((callback) =>
|
|
409
|
+
{
|
|
410
|
+
try
|
|
411
|
+
{
|
|
412
|
+
callback[1](params);
|
|
413
|
+
}
|
|
414
|
+
catch (e)
|
|
415
|
+
{
|
|
416
|
+
SpessaSynthWarn(`Failed to execute callback for ${callback[0]}:`, e);
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
372
421
|
/**
|
|
373
422
|
* @param {WorkletSequencerReturnMessageType} messageType
|
|
374
423
|
* @param {any} messageData
|
|
@@ -411,7 +460,7 @@ export class Sequencer
|
|
|
411
460
|
this.hasDummyData = false;
|
|
412
461
|
this.absoluteStartTime = 0;
|
|
413
462
|
this.duration = this.midiData.duration;
|
|
414
|
-
|
|
463
|
+
this._callEvents(this.onSongChange, songChangeData);
|
|
415
464
|
// if is auto played, unpause
|
|
416
465
|
if (messageData[2] === true)
|
|
417
466
|
{
|
|
@@ -429,7 +478,7 @@ export class Sequencer
|
|
|
429
478
|
case WorkletSequencerReturnMessageType.timeChange:
|
|
430
479
|
// message data is absolute time
|
|
431
480
|
const time = this.synth.currentTime - messageData;
|
|
432
|
-
|
|
481
|
+
this._callEvents(this.onTimeChange, time);
|
|
433
482
|
this._recalculateStartTime(time);
|
|
434
483
|
if (this.paused && this._preservePlaybackState)
|
|
435
484
|
{
|
|
@@ -446,7 +495,7 @@ export class Sequencer
|
|
|
446
495
|
this.isFinished = messageData;
|
|
447
496
|
if (this.isFinished)
|
|
448
497
|
{
|
|
449
|
-
|
|
498
|
+
this._callEvents(this.onSongEnded, undefined);
|
|
450
499
|
}
|
|
451
500
|
break;
|
|
452
501
|
|
|
@@ -466,6 +515,14 @@ export class Sequencer
|
|
|
466
515
|
{
|
|
467
516
|
this._getMIDIResolve(BasicMIDI.copyFrom(messageData));
|
|
468
517
|
}
|
|
518
|
+
break;
|
|
519
|
+
|
|
520
|
+
case WorkletSequencerReturnMessageType.tempoChange:
|
|
521
|
+
this.currentTempo = messageData;
|
|
522
|
+
if (this.onTempoChange)
|
|
523
|
+
{
|
|
524
|
+
this._callEvents(this.onTempoChange, this.currentTempo);
|
|
525
|
+
}
|
|
469
526
|
}
|
|
470
527
|
}
|
|
471
528
|
|
|
@@ -499,7 +556,7 @@ export class Sequencer
|
|
|
499
556
|
loadNewSongList(midiBuffers, autoPlay = true)
|
|
500
557
|
{
|
|
501
558
|
this.pause();
|
|
502
|
-
// add some
|
|
559
|
+
// add some fake data
|
|
503
560
|
this.midiData = DUMMY_MIDI_DATA;
|
|
504
561
|
this.hasDummyData = true;
|
|
505
562
|
this.duration = 99999;
|
|
@@ -549,7 +606,7 @@ export class Sequencer
|
|
|
549
606
|
|
|
550
607
|
/**
|
|
551
608
|
* Starts the playback
|
|
552
|
-
* @param resetTime {boolean} If true, time is set to
|
|
609
|
+
* @param resetTime {boolean} If true, time is set to 0 s
|
|
553
610
|
*/
|
|
554
611
|
play(resetTime = false)
|
|
555
612
|
{
|
|
@@ -90,12 +90,15 @@ export function _processEvent(event, trackIndex)
|
|
|
90
90
|
break;
|
|
91
91
|
|
|
92
92
|
case messageTypes.setTempo:
|
|
93
|
-
|
|
93
|
+
let tempoBPM = getTempo(event);
|
|
94
|
+
this.oneTickToSeconds = 60 / (tempoBPM * this.midiData.timeDivision);
|
|
94
95
|
if (this.oneTickToSeconds === 0)
|
|
95
96
|
{
|
|
96
97
|
this.oneTickToSeconds = 60 / (120 * this.midiData.timeDivision);
|
|
97
98
|
SpessaSynthWarn("invalid tempo! falling back to 120 BPM");
|
|
99
|
+
tempoBPM = 120;
|
|
98
100
|
}
|
|
101
|
+
this.post(WorkletSequencerReturnMessageType.tempoChange, Math.floor(tempoBPM * 100) / 100);
|
|
99
102
|
break;
|
|
100
103
|
|
|
101
104
|
// recongized but ignored
|
|
@@ -8,18 +8,18 @@ export function _processTick()
|
|
|
8
8
|
let current = this.currentTime;
|
|
9
9
|
while (this.playedTime < current)
|
|
10
10
|
{
|
|
11
|
-
// find next event
|
|
11
|
+
// find the next event
|
|
12
12
|
let trackIndex = this._findFirstEventIndex();
|
|
13
13
|
let event = this.tracks[trackIndex][this.eventIndex[trackIndex]];
|
|
14
14
|
this._processEvent(event, trackIndex);
|
|
15
15
|
|
|
16
16
|
this.eventIndex[trackIndex]++;
|
|
17
17
|
|
|
18
|
-
// find next event
|
|
18
|
+
// find the next event
|
|
19
19
|
trackIndex = this._findFirstEventIndex();
|
|
20
20
|
if (this.tracks[trackIndex].length <= this.eventIndex[trackIndex])
|
|
21
21
|
{
|
|
22
|
-
// song has ended
|
|
22
|
+
// the song has ended
|
|
23
23
|
if (this.loop)
|
|
24
24
|
{
|
|
25
25
|
this.setTimeTicks(this.midiData.loop.start);
|
|
@@ -43,7 +43,7 @@ export function _processTick()
|
|
|
43
43
|
this.setTimeTicks(this.midiData.loop.start);
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
// if song has ended
|
|
46
|
+
// if the song has ended
|
|
47
47
|
else if (current >= this.duration)
|
|
48
48
|
{
|
|
49
49
|
if (this.loop && this.currentLoopCount > 0)
|
|
@@ -39,5 +39,6 @@ export const WorkletSequencerReturnMessageType = {
|
|
|
39
39
|
timeChange: 3, // newAbsoluteTime<number>
|
|
40
40
|
pause: 4, // no data
|
|
41
41
|
getMIDI: 5, // midiData<MIDI>
|
|
42
|
-
midiError: 6
|
|
42
|
+
midiError: 6, // errorMSG<string>
|
|
43
|
+
tempoChange: 7 // newTempoBPM<number>
|
|
43
44
|
};
|
|
File without changes
|
|
@@ -4,62 +4,80 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
* @
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* @typedef {
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* }
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* }
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*
|
|
35
|
-
* }
|
|
36
|
-
*
|
|
37
|
-
* @
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
* @
|
|
43
|
-
*
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* @
|
|
50
|
-
*
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
*
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
* }
|
|
59
|
-
*
|
|
60
|
-
* @
|
|
61
|
-
|
|
62
|
-
|
|
7
|
+
* @typedef {Object} NoteOnCallback
|
|
8
|
+
* @property {number} midiNote - The MIDI note number.
|
|
9
|
+
* @property {number} channel - The MIDI channel number.
|
|
10
|
+
* @property {number} velocity - The velocity of the note.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {Object} NoteOffCallback
|
|
15
|
+
* @property {number} midiNote - The MIDI note number.
|
|
16
|
+
* @property {number} channel - The MIDI channel number.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {Object} DrumChangeCallback
|
|
21
|
+
* @property {number} channel - The MIDI channel number.
|
|
22
|
+
* @property {boolean} isDrumChannel - Indicates if the channel is a drum channel.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {Object} ProgramChangeCallback
|
|
27
|
+
* @property {number} channel - The MIDI channel number.
|
|
28
|
+
* @property {number} program - The program number.
|
|
29
|
+
* @property {number} bank - The bank number.
|
|
30
|
+
* @property {boolean} userCalled - Indicates if the change was user-initiated.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @typedef {Object} ControllerChangeCallback
|
|
35
|
+
* @property {number} channel - The MIDI channel number.
|
|
36
|
+
* @property {number} controllerNumber - The controller number.
|
|
37
|
+
* @property {number} controllerValue - The value of the controller.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @typedef {Object} MuteChannelCallback
|
|
42
|
+
* @property {number} channel - The MIDI channel number.
|
|
43
|
+
* @property {boolean} isMuted - Indicates if the channel is muted.
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @typedef {Object} PresetListChangeCallbackSingle
|
|
48
|
+
* @property {string} presetName - The name of the preset.
|
|
49
|
+
* @property {number} bank - The bank number.
|
|
50
|
+
* @property {number} program - The program number.
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @typedef {PresetListChangeCallbackSingle[]} PresetListChangeCallback - A list of preset objects.
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @typedef {Object} SynthDisplayCallback
|
|
59
|
+
* @property {Uint8Array} displayData - The data to display.
|
|
60
|
+
* @property {SynthDisplayType} displayType - The type of display.
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @typedef {Object} PitchWheelCallback
|
|
65
|
+
* @property {number} channel - The MIDI channel number.
|
|
66
|
+
* @property {number} MSB - The most significant byte of the pitch wheel value.
|
|
67
|
+
* @property {number} LSB - The least significant byte of the pitch wheel value.
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @typedef {Object} ChannelPressureCallback
|
|
72
|
+
* @property {number} channel - The MIDI channel number.
|
|
73
|
+
* @property {number} pressure - The pressure value.
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @typedef {Error} SoundfontErrorCallback - The error message for soundfont errors.
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
/**
|
|
63
81
|
* @typedef {
|
|
64
82
|
* NoteOnCallback |
|
|
65
83
|
* NoteOffCallback |
|
|
@@ -71,6 +89,7 @@
|
|
|
71
89
|
* PitchWheelCallback |
|
|
72
90
|
* SoundfontErrorCallback |
|
|
73
91
|
* ChannelPressureCallback |
|
|
92
|
+
* SynthDisplayCallback |
|
|
74
93
|
* undefined
|
|
75
94
|
* } EventCallbackData
|
|
76
95
|
*/
|
|
@@ -90,7 +109,8 @@
|
|
|
90
109
|
* "mutechannel"|
|
|
91
110
|
* "presetlistchange"|
|
|
92
111
|
* "allcontrollerreset"|
|
|
93
|
-
* "soundfonterror"
|
|
112
|
+
* "soundfonterror"|
|
|
113
|
+
* "synthdisplay"} EventTypes
|
|
94
114
|
*/
|
|
95
115
|
export class EventHandler
|
|
96
116
|
{
|
|
@@ -104,20 +124,21 @@ export class EventHandler
|
|
|
104
124
|
* @type {Object<EventTypes, Object<string, function(EventCallbackData)>>}
|
|
105
125
|
*/
|
|
106
126
|
this.events = {
|
|
107
|
-
"noteoff": {},
|
|
108
|
-
"noteon": {},
|
|
109
|
-
"pitchwheel": {},
|
|
110
|
-
"controllerchange": {},
|
|
111
|
-
"programchange": {},
|
|
112
|
-
"channelpressure": {},
|
|
113
|
-
"polypressure": {},
|
|
114
|
-
"drumchange": {},
|
|
115
|
-
"stopall": {},
|
|
116
|
-
"newchannel": {},
|
|
117
|
-
"mutechannel": {},
|
|
118
|
-
"presetlistchange": {},
|
|
119
|
-
"allcontrollerreset": {},
|
|
120
|
-
"soundfonterror": {}
|
|
127
|
+
"noteoff": {}, // called on note off message
|
|
128
|
+
"noteon": {}, // called on note on message
|
|
129
|
+
"pitchwheel": {}, // called on pitch wheel change
|
|
130
|
+
"controllerchange": {}, // called on controller change
|
|
131
|
+
"programchange": {}, // called on program change
|
|
132
|
+
"channelpressure": {}, // called on channel pressure message
|
|
133
|
+
"polypressure": {}, // called on poly pressure message
|
|
134
|
+
"drumchange": {}, // called when channel type changes
|
|
135
|
+
"stopall": {}, // called when synth receives stop all command
|
|
136
|
+
"newchannel": {}, // called when a new channel is created
|
|
137
|
+
"mutechannel": {}, // called when a channel is muted/unmuted
|
|
138
|
+
"presetlistchange": {}, // called when the preset list changes (soundfont gets reloaded)
|
|
139
|
+
"allcontrollerreset": {}, // called when all controllers are reset
|
|
140
|
+
"soundfonterror": {}, // called when a soundfont parsing error occurs
|
|
141
|
+
"synthdisplay": {} // called when there's a SysEx message to display some text
|
|
121
142
|
};
|
|
122
143
|
|
|
123
144
|
/**
|