spessasynth_lib 3.25.8 → 3.25.9
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/midi_parser/README.md +29 -1
- package/midi_parser/midi_loader.js +4 -3
- package/package.json +1 -1
- package/soundfont/basic_soundfont/basic_soundfont.js +8 -2
- package/synthetizer/synthetizer.js +25 -5
- package/synthetizer/worklet_processor.min.js +9 -9
- package/synthetizer/worklet_system/main_processor.js +10 -11
- package/synthetizer/worklet_system/message_protocol/message_sending.js +0 -42
- package/synthetizer/worklet_system/message_protocol/worklet_message.js +5 -6
- package/synthetizer/worklet_system/worklet_methods/create_worklet_channel.js +1 -1
- package/synthetizer/worklet_system/worklet_methods/mute_channel.js +1 -1
- package/synthetizer/worklet_system/worklet_methods/note_on.js +1 -1
- package/synthetizer/worklet_system/worklet_methods/program_change.js +11 -2
- package/synthetizer/worklet_system/worklet_methods/stopping_notes/stop_all_notes.js +1 -1
- package/synthetizer/worklet_system/worklet_methods/tuning_control/pitch_wheel.js +1 -1
- package/synthetizer/worklet_system/worklet_methods/tuning_control/transpose_channel.js +1 -1
- package/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +53 -2
package/midi_parser/README.md
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
1
|
## This is the MIDI file parsing folder.
|
|
2
2
|
|
|
3
3
|
The code here is responsible for parsing the MIDI files and interpreting the messsages.
|
|
4
|
-
All the events are defined in the `midi_message.js` file.
|
|
4
|
+
All the events are defined in the `midi_message.js` file.
|
|
5
|
+
|
|
6
|
+
### MIDI Classes hierarchy
|
|
7
|
+
|
|
8
|
+
#### MIDI Sequence
|
|
9
|
+
- The most basic class, containing all the metadata that inheritors have.
|
|
10
|
+
- It does not contain track data or embedded sound bank.
|
|
11
|
+
- Contains the function for calculating time from ticks.
|
|
12
|
+
- Contains the copying code.
|
|
13
|
+
|
|
14
|
+
#### MIDI Data
|
|
15
|
+
- Inherits from MIDI Sequence.
|
|
16
|
+
- Has an `isEmbedded` property to mark the existence of embedded bank. This is the class that is available in `sequencer.midiData`.
|
|
17
|
+
|
|
18
|
+
#### Basic MIDI
|
|
19
|
+
- Inherits from MIDI Sequence.
|
|
20
|
+
- The actual MIDI representation, containing the track data and embedded sound banks.
|
|
21
|
+
- Contains the code for parsing the MIDI and filling in the metadata automatically.
|
|
22
|
+
- Contains the SMF/RMI writing functions.
|
|
23
|
+
- Contains the code for determining used channels on tracks.
|
|
24
|
+
|
|
25
|
+
#### MIDI Builder
|
|
26
|
+
- Inherits from Basic MIDI.
|
|
27
|
+
- Used for building MIDIs from scratch.
|
|
28
|
+
|
|
29
|
+
### MIDI
|
|
30
|
+
- Inherits from Basic MIDI.
|
|
31
|
+
- The SMF/RMI/XMF file parser.
|
|
32
|
+
- Called by the sequencer if an `ArrayBuffer` is provided.
|
|
@@ -155,7 +155,7 @@ class MIDI extends BasicMIDI
|
|
|
155
155
|
{
|
|
156
156
|
fileByteArray = binaryData;
|
|
157
157
|
}
|
|
158
|
-
const headerChunk = this.
|
|
158
|
+
const headerChunk = this._readMIDIChunk(fileByteArray);
|
|
159
159
|
if (headerChunk.type !== "MThd")
|
|
160
160
|
{
|
|
161
161
|
SpessaSynthGroupEnd();
|
|
@@ -181,7 +181,7 @@ class MIDI extends BasicMIDI
|
|
|
181
181
|
* @type {MIDIMessage[]}
|
|
182
182
|
*/
|
|
183
183
|
const track = [];
|
|
184
|
-
const trackChunk = this.
|
|
184
|
+
const trackChunk = this._readMIDIChunk(fileByteArray);
|
|
185
185
|
|
|
186
186
|
if (trackChunk.type !== "MTrk")
|
|
187
187
|
{
|
|
@@ -303,8 +303,9 @@ class MIDI extends BasicMIDI
|
|
|
303
303
|
/**
|
|
304
304
|
* @param fileByteArray {IndexedByteArray}
|
|
305
305
|
* @returns {{type: string, size: number, data: IndexedByteArray}}
|
|
306
|
+
* @private
|
|
306
307
|
*/
|
|
307
|
-
|
|
308
|
+
_readMIDIChunk(fileByteArray)
|
|
308
309
|
{
|
|
309
310
|
const chunk = {};
|
|
310
311
|
// type
|
package/package.json
CHANGED
|
@@ -166,11 +166,11 @@ class BasicSoundBank
|
|
|
166
166
|
// MUST be a valid XG bank.
|
|
167
167
|
// allowed banks: (see XG specification)
|
|
168
168
|
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 24,
|
|
169
|
-
// 25, 27, 28, 29, 30, 31, 32, 33, 40, 41, 48,
|
|
169
|
+
// 25, 27, 28, 29, 30, 31, 32, 33, 40, 41, 48, 56, 57, 58,
|
|
170
170
|
// 64, 65, 66, 126, 127
|
|
171
171
|
const allowedPrograms = new Set([
|
|
172
172
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 24,
|
|
173
|
-
25, 27, 28, 29, 30, 31, 32, 33, 40, 41, 48,
|
|
173
|
+
25, 27, 28, 29, 30, 31, 32, 33, 40, 41, 48, 56, 57, 58,
|
|
174
174
|
64, 65, 66, 126, 127
|
|
175
175
|
]);
|
|
176
176
|
for (const preset of this.presets)
|
|
@@ -182,6 +182,12 @@ class BasicSoundBank
|
|
|
182
182
|
{
|
|
183
183
|
// not valid!
|
|
184
184
|
this.isXGBank = false;
|
|
185
|
+
SpessaSynthInfo(
|
|
186
|
+
`%cThis bank is not valid XG. Preset %c${preset.bank}:${preset.program}%c is not a valid XG drum. XG mode will use presets on bank 128.`,
|
|
187
|
+
consoleColors.info,
|
|
188
|
+
consoleColors.value,
|
|
189
|
+
consoleColors.info
|
|
190
|
+
);
|
|
185
191
|
break;
|
|
186
192
|
}
|
|
187
193
|
}
|
|
@@ -77,6 +77,12 @@ export class Synthetizer
|
|
|
77
77
|
*/
|
|
78
78
|
channelProperties = [];
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* The current preset list
|
|
82
|
+
* @type {{presetName: string, bank: number, program: number}[]}
|
|
83
|
+
*/
|
|
84
|
+
presetList = [];
|
|
85
|
+
|
|
80
86
|
/**
|
|
81
87
|
* Creates a new instance of the SpessaSynth synthesizer.
|
|
82
88
|
* @param targetNode {AudioNode}
|
|
@@ -242,10 +248,16 @@ export class Synthetizer
|
|
|
242
248
|
}
|
|
243
249
|
|
|
244
250
|
// attach a new channel to keep track of channels count
|
|
245
|
-
this.eventHandler.addEvent("newchannel",
|
|
251
|
+
this.eventHandler.addEvent("newchannel", `synth-new-channel-${Math.random()}`, () =>
|
|
246
252
|
{
|
|
247
253
|
this.channelsAmount++;
|
|
248
254
|
});
|
|
255
|
+
|
|
256
|
+
// attach a new event for preset list change
|
|
257
|
+
this.eventHandler.addEvent("presetlistchange", `synth-preset-list-change-${Math.random()}`, e =>
|
|
258
|
+
{
|
|
259
|
+
this.presetList = e;
|
|
260
|
+
});
|
|
249
261
|
}
|
|
250
262
|
|
|
251
263
|
/**
|
|
@@ -396,11 +408,17 @@ export class Synthetizer
|
|
|
396
408
|
const messageData = message.messageData;
|
|
397
409
|
switch (message.messageType)
|
|
398
410
|
{
|
|
399
|
-
case returnMessageType.
|
|
411
|
+
case returnMessageType.channelPropertyChange:
|
|
412
|
+
/**
|
|
413
|
+
* @type {number}
|
|
414
|
+
*/
|
|
415
|
+
const channelNumber = messageData[0];
|
|
400
416
|
/**
|
|
401
|
-
* @type {ChannelProperty
|
|
417
|
+
* @type {ChannelProperty}
|
|
402
418
|
*/
|
|
403
|
-
|
|
419
|
+
const property = messageData[1];
|
|
420
|
+
|
|
421
|
+
this.channelProperties[channelNumber] = property;
|
|
404
422
|
|
|
405
423
|
this._voicesAmount = this.channelProperties.reduce((sum, voices) => sum + voices.voicesAmount, 0);
|
|
406
424
|
break;
|
|
@@ -485,7 +503,9 @@ export class Synthetizer
|
|
|
485
503
|
pitchBendRangeSemitones: 0,
|
|
486
504
|
isMuted: false,
|
|
487
505
|
isDrum: false,
|
|
488
|
-
transposition: 0
|
|
506
|
+
transposition: 0,
|
|
507
|
+
program: 0,
|
|
508
|
+
bank: this.channelsAmount % 16 === DEFAULT_PERCUSSION ? 128 : 0
|
|
489
509
|
});
|
|
490
510
|
if (!postMessage)
|
|
491
511
|
{
|