spessasynth_lib 3.25.0 → 3.25.1
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/midi_editor.js +5 -16
- package/midi_parser/rmidi_writer.js +64 -33
- package/midi_parser/used_keys_loaded.js +47 -32
- package/package.json +1 -1
- package/sequencer/sequencer.js +0 -1
- package/synthetizer/synthetizer.js +48 -1
- package/synthetizer/worklet_processor.min.js +12 -12
- package/synthetizer/worklet_system/main_processor.js +17 -2
- package/synthetizer/worklet_system/message_protocol/handle_message.js +3 -0
- package/synthetizer/worklet_system/message_protocol/worklet_message.js +5 -6
- package/synthetizer/worklet_system/snapshot/channel_snapshot.js +1 -1
- package/synthetizer/worklet_system/snapshot/synthesizer_snapshot.js +1 -1
- package/synthetizer/worklet_system/worklet_methods/controller_control/controller_change.js +67 -131
- package/synthetizer/worklet_system/worklet_methods/controller_control/reset_controllers.js +2 -2
- package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +6 -6
- package/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +35 -2
- package/utils/sysex_detector.js +46 -0
- package/utils/xg_hacks.js +128 -0
|
@@ -5,6 +5,7 @@ import { consoleColors } from "../utils/other.js";
|
|
|
5
5
|
|
|
6
6
|
import { customControllers } from "../synthetizer/worklet_system/worklet_utilities/controller_tables.js";
|
|
7
7
|
import { DEFAULT_PERCUSSION } from "../synthetizer/synth_constants.js";
|
|
8
|
+
import { isGMOn, isGSOn, isXGOn } from "../utils/sysex_detector.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* @param ticks {number}
|
|
@@ -450,12 +451,7 @@ export function modifyMIDI(
|
|
|
450
451
|
|
|
451
452
|
case messageTypes.systemExclusive:
|
|
452
453
|
// check for xg on
|
|
453
|
-
if (
|
|
454
|
-
e.messageData[0] === 0x43 && // Yamaha
|
|
455
|
-
e.messageData[2] === 0x4C && // XG ON
|
|
456
|
-
e.messageData[5] === 0x7E &&
|
|
457
|
-
e.messageData[6] === 0x00
|
|
458
|
-
)
|
|
454
|
+
if (isXGOn(e))
|
|
459
455
|
{
|
|
460
456
|
SpessaSynthInfo("%cXG system on detected", consoleColors.info);
|
|
461
457
|
system = "xg";
|
|
@@ -479,11 +475,7 @@ export function modifyMIDI(
|
|
|
479
475
|
}
|
|
480
476
|
else
|
|
481
477
|
// check for GS on
|
|
482
|
-
if (
|
|
483
|
-
e.messageData[0] === 0x41 // roland
|
|
484
|
-
&& e.messageData[2] === 0x42 // GS
|
|
485
|
-
&& e.messageData[6] === 0x7F // Mode set
|
|
486
|
-
)
|
|
478
|
+
if (isGSOn(e))
|
|
487
479
|
{
|
|
488
480
|
// that's a GS on, we're done here
|
|
489
481
|
addedGs = true;
|
|
@@ -495,10 +487,7 @@ export function modifyMIDI(
|
|
|
495
487
|
}
|
|
496
488
|
else
|
|
497
489
|
// check for GM/2 on
|
|
498
|
-
if (
|
|
499
|
-
e.messageData[0] === 0x7E // non realtime
|
|
500
|
-
&& e.messageData[2] === 0x09 // gm system
|
|
501
|
-
)
|
|
490
|
+
if (isGMOn(e))
|
|
502
491
|
{
|
|
503
492
|
// that's a GM/2 system change, remove it!
|
|
504
493
|
SpessaSynthInfo(
|
|
@@ -511,7 +500,7 @@ export function modifyMIDI(
|
|
|
511
500
|
}
|
|
512
501
|
}
|
|
513
502
|
// check for gs
|
|
514
|
-
if (!addedGs)
|
|
503
|
+
if (!addedGs && desiredProgramChanges.length > 0)
|
|
515
504
|
{
|
|
516
505
|
// gs is not on, add it on the first track at index 0 (or 1 if track name is first)
|
|
517
506
|
let index = 0;
|
|
@@ -7,6 +7,8 @@ import { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo } from "../utils
|
|
|
7
7
|
import { consoleColors } from "../utils/other.js";
|
|
8
8
|
import { writeLittleEndian } from "../utils/byte_functions/little_endian.js";
|
|
9
9
|
import { DEFAULT_PERCUSSION } from "../synthetizer/synth_constants.js";
|
|
10
|
+
import { chooseBank, parseBankSelect } from "../utils/xg_hacks.js";
|
|
11
|
+
import { isGMOn, isGSDrumsOn, isGSOn, isXGOn } from "../utils/sysex_detector.js";
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* @enum {string}
|
|
@@ -122,6 +124,7 @@ export function writeRMIDI(
|
|
|
122
124
|
* program: number,
|
|
123
125
|
* drums: boolean,
|
|
124
126
|
* lastBank: MIDIMessage,
|
|
127
|
+
* lastBankLSB: MIDIMessage,
|
|
125
128
|
* hasBankSelect: boolean
|
|
126
129
|
* }[]}
|
|
127
130
|
*/
|
|
@@ -132,6 +135,7 @@ export function writeRMIDI(
|
|
|
132
135
|
program: 0,
|
|
133
136
|
drums: i % 16 === DEFAULT_PERCUSSION, // drums appear on 9 every 16 channels,
|
|
134
137
|
lastBank: undefined,
|
|
138
|
+
lastBankLSB: undefined,
|
|
135
139
|
hasBankSelect: false
|
|
136
140
|
});
|
|
137
141
|
}
|
|
@@ -166,37 +170,18 @@ export function writeRMIDI(
|
|
|
166
170
|
if (status === messageTypes.systemExclusive)
|
|
167
171
|
{
|
|
168
172
|
// check for drum sysex
|
|
169
|
-
if (
|
|
170
|
-
e.messageData[0] !== 0x41 || // roland
|
|
171
|
-
e.messageData[2] !== 0x42 || // GS
|
|
172
|
-
e.messageData[3] !== 0x12 || // GS
|
|
173
|
-
e.messageData[4] !== 0x40 || // system parameter
|
|
174
|
-
(e.messageData[5] & 0x10) === 0 || // part parameter
|
|
175
|
-
e.messageData[6] !== 0x15 // drum part
|
|
176
|
-
)
|
|
173
|
+
if (!isGSDrumsOn(e))
|
|
177
174
|
{
|
|
178
175
|
// check for XG
|
|
179
|
-
if (
|
|
180
|
-
e.messageData[0] === 0x43 && // yamaha
|
|
181
|
-
e.messageData[2] === 0x4C && // sXG ON
|
|
182
|
-
e.messageData[5] === 0x7E &&
|
|
183
|
-
e.messageData[6] === 0x00
|
|
184
|
-
)
|
|
176
|
+
if (isXGOn(e))
|
|
185
177
|
{
|
|
186
178
|
system = "xg";
|
|
187
179
|
}
|
|
188
|
-
else if (
|
|
189
|
-
e.messageData[0] === 0x41 // roland
|
|
190
|
-
&& e.messageData[2] === 0x42 // GS
|
|
191
|
-
&& e.messageData[6] === 0x7F // Mode set
|
|
192
|
-
)
|
|
180
|
+
else if (isGSOn(e))
|
|
193
181
|
{
|
|
194
182
|
system = "gs";
|
|
195
183
|
}
|
|
196
|
-
else if (
|
|
197
|
-
e.messageData[0] === 0x7E // non realtime
|
|
198
|
-
&& e.messageData[2] === 0x09 // gm system
|
|
199
|
-
)
|
|
184
|
+
else if (isGMOn(e))
|
|
200
185
|
{
|
|
201
186
|
system = "gm";
|
|
202
187
|
unwantedSystems.push({
|
|
@@ -213,6 +198,9 @@ export function writeRMIDI(
|
|
|
213
198
|
|
|
214
199
|
// program change
|
|
215
200
|
const chNum = (e.messageStatusByte & 0xF) + portOffset;
|
|
201
|
+
/**
|
|
202
|
+
* @type {{program: number, drums: boolean, lastBank: MIDIMessage, lastBankLSB: MIDIMessage, hasBankSelect: boolean}}
|
|
203
|
+
*/
|
|
216
204
|
const channel = channelsInfo[chNum];
|
|
217
205
|
if (status === messageTypes.programChange)
|
|
218
206
|
{
|
|
@@ -236,15 +224,24 @@ export function writeRMIDI(
|
|
|
236
224
|
channel.program = e.messageData[0];
|
|
237
225
|
// check if this preset exists for program and bank
|
|
238
226
|
const realBank = Math.max(0, channel.lastBank?.messageData[1] - mid.bankOffset); // make sure to take the previous bank offset into account
|
|
239
|
-
|
|
227
|
+
let bank = channel.drums ? 128 : realBank;
|
|
240
228
|
if (channel.lastBank === undefined)
|
|
241
229
|
{
|
|
242
230
|
continue;
|
|
243
231
|
}
|
|
244
|
-
if (system === "xg"
|
|
232
|
+
if (system === "xg")
|
|
245
233
|
{
|
|
246
|
-
|
|
247
|
-
|
|
234
|
+
if (channel.drums)
|
|
235
|
+
{
|
|
236
|
+
// drums override: set the bank to 127
|
|
237
|
+
channelsInfo[chNum].lastBank.messageData[1] = 127;
|
|
238
|
+
}
|
|
239
|
+
else
|
|
240
|
+
{
|
|
241
|
+
// potential bank lsb override
|
|
242
|
+
const bankLSB = (channel?.lastBankLSB?.messageData[1] - mid.bankOffset) || 0;
|
|
243
|
+
bank = chooseBank(bank, bankLSB);
|
|
244
|
+
}
|
|
248
245
|
}
|
|
249
246
|
|
|
250
247
|
if (soundfont.presets.findIndex(p => p.bank === bank && p.program === e.messageData[0]) === -1)
|
|
@@ -252,6 +249,10 @@ export function writeRMIDI(
|
|
|
252
249
|
// no preset with this bank. find this program with any bank
|
|
253
250
|
const targetBank = (soundfont.presets.find(p => p.program === e.messageData[0])?.bank + bankOffset) || bankOffset;
|
|
254
251
|
channel.lastBank.messageData[1] = targetBank;
|
|
252
|
+
if (channel?.lastBankLSB?.messageData)
|
|
253
|
+
{
|
|
254
|
+
channel.lastBankLSB.messageData[1] = targetBank;
|
|
255
|
+
}
|
|
255
256
|
SpessaSynthInfo(
|
|
256
257
|
`%cNo preset %c${bank}:${e.messageData[0]}%c. Changing bank to ${targetBank}.`,
|
|
257
258
|
consoleColors.info,
|
|
@@ -265,6 +266,10 @@ export function writeRMIDI(
|
|
|
265
266
|
let drumBank = system === "xg" ? 127 : 0;
|
|
266
267
|
const newBank = (bank === 128 ? drumBank : realBank) + bankOffset;
|
|
267
268
|
channel.lastBank.messageData[1] = newBank;
|
|
269
|
+
if (channel?.lastBankLSB?.messageData)
|
|
270
|
+
{
|
|
271
|
+
channel.lastBankLSB.messageData[1] = channel.lastBankLSB.messageData[1] - mid.bankOffset + bankOffset;
|
|
272
|
+
}
|
|
268
273
|
SpessaSynthInfo(
|
|
269
274
|
`%cPreset %c${bank}:${e.messageData[0]}%c exists. Changing bank to ${newBank}.`,
|
|
270
275
|
consoleColors.info,
|
|
@@ -274,19 +279,45 @@ export function writeRMIDI(
|
|
|
274
279
|
}
|
|
275
280
|
continue;
|
|
276
281
|
}
|
|
277
|
-
|
|
278
|
-
|
|
282
|
+
|
|
283
|
+
// controller change
|
|
284
|
+
// we only care about bank-selects
|
|
285
|
+
const isLSB = e.messageData[0] === midiControllers.lsbForControl0BankSelect;
|
|
286
|
+
if (e.messageData[0] !== midiControllers.bankSelect && !isLSB)
|
|
279
287
|
{
|
|
280
288
|
continue;
|
|
281
289
|
}
|
|
282
290
|
// bank select
|
|
283
291
|
channel.hasBankSelect = true;
|
|
284
|
-
|
|
292
|
+
const bankNumber = e.messageData[1];
|
|
293
|
+
// interpret
|
|
294
|
+
const intepretation = parseBankSelect(
|
|
295
|
+
channel?.lastBank?.messageData[1] || 0,
|
|
296
|
+
bankNumber,
|
|
297
|
+
system,
|
|
298
|
+
isLSB,
|
|
299
|
+
channel.drums,
|
|
300
|
+
chNum
|
|
301
|
+
);
|
|
302
|
+
if (intepretation.drumsStatus === 2)
|
|
285
303
|
{
|
|
286
|
-
|
|
287
|
-
|
|
304
|
+
channel.drums = true;
|
|
305
|
+
}
|
|
306
|
+
else if (intepretation.drumsStatus === 1)
|
|
307
|
+
{
|
|
308
|
+
channel.drums = false;
|
|
309
|
+
}
|
|
310
|
+
if (bankNumber === intepretation.newBank || channel.drums)
|
|
311
|
+
{
|
|
312
|
+
if (isLSB)
|
|
313
|
+
{
|
|
314
|
+
channel.lastBankLSB = e;
|
|
315
|
+
}
|
|
316
|
+
else
|
|
317
|
+
{
|
|
318
|
+
channel.lastBank = e;
|
|
319
|
+
}
|
|
288
320
|
}
|
|
289
|
-
channel.lastBank = e;
|
|
290
321
|
}
|
|
291
322
|
|
|
292
323
|
// add missing bank selects
|
|
@@ -2,6 +2,8 @@ import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo } from
|
|
|
2
2
|
import { consoleColors } from "../utils/other.js";
|
|
3
3
|
import { messageTypes, midiControllers } from "./midi_message.js";
|
|
4
4
|
import { DEFAULT_PERCUSSION } from "../synthetizer/synth_constants.js";
|
|
5
|
+
import { chooseBank, parseBankSelect } from "../utils/xg_hacks.js";
|
|
6
|
+
import { isGSDrumsOn, isXGOn } from "../utils/sysex_detector.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Gets the used programs and keys for this MIDI file with a given sound bank
|
|
@@ -19,7 +21,7 @@ export function getUsedProgramsAndKeys(soundfont)
|
|
|
19
21
|
// Find every bank:program combo and every key:velocity for each. Make sure to care about ports and drums
|
|
20
22
|
const channelsAmount = 16 + mid.midiPortChannelOffsets.reduce((max, cur) => cur > max ? cur : max);
|
|
21
23
|
/**
|
|
22
|
-
* @type {{program: number, bank: number, drums: boolean, string: string}[]}
|
|
24
|
+
* @type {{program: number, bank: number, bankLSB: number, drums: boolean, string: string}[]}
|
|
23
25
|
*/
|
|
24
26
|
const channelPresets = [];
|
|
25
27
|
for (let i = 0; i < channelsAmount; i++)
|
|
@@ -28,6 +30,7 @@ export function getUsedProgramsAndKeys(soundfont)
|
|
|
28
30
|
channelPresets.push({
|
|
29
31
|
program: 0,
|
|
30
32
|
bank: bank,
|
|
33
|
+
bankLSB: 0,
|
|
31
34
|
drums: i % 16 === DEFAULT_PERCUSSION, // drums appear on 9 every 16 channels,
|
|
32
35
|
string: `${bank}:0`
|
|
33
36
|
});
|
|
@@ -35,9 +38,11 @@ export function getUsedProgramsAndKeys(soundfont)
|
|
|
35
38
|
|
|
36
39
|
function updateString(ch)
|
|
37
40
|
{
|
|
41
|
+
const bank = chooseBank(ch.bank, ch.bankLSB);
|
|
38
42
|
// check if this exists in the soundfont
|
|
39
|
-
let exists = soundfont.getPreset(
|
|
43
|
+
let exists = soundfont.getPreset(bank, ch.program);
|
|
40
44
|
ch.bank = exists.bank;
|
|
45
|
+
ch.bankLSB = 0;
|
|
41
46
|
ch.program = exists.program;
|
|
42
47
|
ch.string = ch.bank + ":" + ch.program;
|
|
43
48
|
if (!usedProgramsAndKeys[ch.string])
|
|
@@ -124,7 +129,8 @@ export function getUsedProgramsAndKeys(soundfont)
|
|
|
124
129
|
break;
|
|
125
130
|
|
|
126
131
|
case messageTypes.controllerChange:
|
|
127
|
-
|
|
132
|
+
const isLSB = event.messageData[0] === midiControllers.lsbForControl0BankSelect;
|
|
133
|
+
if (event.messageData[0] !== midiControllers.bankSelect && !isLSB)
|
|
128
134
|
{
|
|
129
135
|
// we only care about bank select
|
|
130
136
|
continue;
|
|
@@ -136,24 +142,46 @@ export function getUsedProgramsAndKeys(soundfont)
|
|
|
136
142
|
}
|
|
137
143
|
const bank = event.messageData[1];
|
|
138
144
|
const realBank = Math.max(0, bank - mid.bankOffset);
|
|
139
|
-
|
|
145
|
+
// interpret the bank
|
|
146
|
+
const intepretation = parseBankSelect(
|
|
147
|
+
ch.bank,
|
|
148
|
+
realBank,
|
|
149
|
+
system,
|
|
150
|
+
isLSB,
|
|
151
|
+
ch.drums,
|
|
152
|
+
channel
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
switch (intepretation.drumsStatus)
|
|
140
156
|
{
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
157
|
+
case 0:
|
|
158
|
+
// no change
|
|
159
|
+
break;
|
|
160
|
+
|
|
161
|
+
case 1:
|
|
162
|
+
// drums changed to off
|
|
145
163
|
// drum change is a program change
|
|
146
|
-
ch.drums =
|
|
147
|
-
ch.bank =
|
|
164
|
+
ch.drums = false;
|
|
165
|
+
ch.bank = realBank;
|
|
148
166
|
updateString(ch);
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
167
|
+
break;
|
|
168
|
+
|
|
169
|
+
case 2:
|
|
170
|
+
// drums changed to on
|
|
171
|
+
// drum change is a program change
|
|
172
|
+
ch.drums = true;
|
|
173
|
+
ch.bank = 128;
|
|
174
|
+
updateString(ch);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
if (isLSB)
|
|
178
|
+
{
|
|
179
|
+
ch.bankLSB = intepretation.newBank;
|
|
180
|
+
}
|
|
181
|
+
else
|
|
182
|
+
{
|
|
183
|
+
ch.bank = ch.drums ? 128 : intepretation.newBank;
|
|
155
184
|
}
|
|
156
|
-
channelPresets[channel].bank = realBank;
|
|
157
185
|
// do not update the data, bank change doesn't change the preset
|
|
158
186
|
break;
|
|
159
187
|
|
|
@@ -169,23 +197,10 @@ export function getUsedProgramsAndKeys(soundfont)
|
|
|
169
197
|
|
|
170
198
|
case messageTypes.systemExclusive:
|
|
171
199
|
// check for drum sysex
|
|
172
|
-
if (
|
|
173
|
-
event.messageData[0] !== 0x41 || // roland
|
|
174
|
-
event.messageData[2] !== 0x42 || // GS
|
|
175
|
-
event.messageData[3] !== 0x12 || // GS
|
|
176
|
-
event.messageData[4] !== 0x40 || // system parameter
|
|
177
|
-
(event.messageData[5] & 0x10) === 0 || // part parameter
|
|
178
|
-
event.messageData[6] !== 0x15 // drum pars
|
|
179
|
-
|
|
180
|
-
)
|
|
200
|
+
if (!isGSDrumsOn(event))
|
|
181
201
|
{
|
|
182
202
|
// check for XG
|
|
183
|
-
if (
|
|
184
|
-
event.messageData[0] === 0x43 && // yamaha
|
|
185
|
-
event.messageData[2] === 0x4C && // sXG ON
|
|
186
|
-
event.messageData[5] === 0x7E &&
|
|
187
|
-
event.messageData[6] === 0x00
|
|
188
|
-
)
|
|
203
|
+
if (isXGOn(event))
|
|
189
204
|
{
|
|
190
205
|
system = "xg";
|
|
191
206
|
}
|
package/package.json
CHANGED
package/sequencer/sequencer.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { MIDI } from "../midi_parser/midi_loader.js";
|
|
2
1
|
import { Synthetizer } from "../synthetizer/synthetizer.js";
|
|
3
2
|
import { messageTypes } from "../midi_parser/midi_message.js";
|
|
4
3
|
import { workletMessageType } from "../synthetizer/worklet_system/message_protocol/worklet_message.js";
|
|
@@ -15,7 +15,13 @@ import { DEFAULT_SYNTH_CONFIG } from "./audio_effects/effects_config.js";
|
|
|
15
15
|
import { SoundfontManager } from "./synth_soundfont_manager.js";
|
|
16
16
|
import { KeyModifierManager } from "./key_modifier_manager.js";
|
|
17
17
|
import { channelConfiguration } from "./worklet_system/worklet_utilities/controller_tables.js";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
DEFAULT_PERCUSSION,
|
|
20
|
+
DEFAULT_SYNTH_MODE,
|
|
21
|
+
MIDI_CHANNEL_COUNT,
|
|
22
|
+
VOICE_CAP,
|
|
23
|
+
WORKLET_PROCESSOR_NAME
|
|
24
|
+
} from "./synth_constants.js";
|
|
19
25
|
|
|
20
26
|
|
|
21
27
|
/**
|
|
@@ -239,6 +245,30 @@ export class Synthetizer
|
|
|
239
245
|
});
|
|
240
246
|
}
|
|
241
247
|
|
|
248
|
+
/**
|
|
249
|
+
* @type {"gm"|"gm2"|"gs"|"xg"}
|
|
250
|
+
* @private
|
|
251
|
+
*/
|
|
252
|
+
_midiSystem = DEFAULT_SYNTH_MODE;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* The current MIDI system used by the synthesizer
|
|
256
|
+
* @returns {"gm"|"gm2"|"gs"|"xg"}
|
|
257
|
+
*/
|
|
258
|
+
get midiSystem()
|
|
259
|
+
{
|
|
260
|
+
return this._midiSystem;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* The current MIDI system used by the synthesizer
|
|
265
|
+
* @param value {"gm"|"gm2"|"gs"|"xg"}
|
|
266
|
+
*/
|
|
267
|
+
set midiSystem(value)
|
|
268
|
+
{
|
|
269
|
+
this._midiSystem = value;
|
|
270
|
+
}
|
|
271
|
+
|
|
242
272
|
/**
|
|
243
273
|
* current voice amount
|
|
244
274
|
* @type {number}
|
|
@@ -383,6 +413,23 @@ export class Synthetizer
|
|
|
383
413
|
}
|
|
384
414
|
break;
|
|
385
415
|
|
|
416
|
+
case returnMessageType.masterParameterChange:
|
|
417
|
+
/**
|
|
418
|
+
* @type {masterParameterType}
|
|
419
|
+
*/
|
|
420
|
+
const param = messageData[0];
|
|
421
|
+
const value = messageData[1];
|
|
422
|
+
switch (param)
|
|
423
|
+
{
|
|
424
|
+
default:
|
|
425
|
+
break;
|
|
426
|
+
|
|
427
|
+
case masterParameterType.midiSystem:
|
|
428
|
+
this._midiSystem = value;
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
break;
|
|
432
|
+
|
|
386
433
|
case returnMessageType.synthesizerSnapshot:
|
|
387
434
|
if (this._snapshotCallback)
|
|
388
435
|
{
|