spessasynth_core 4.0.22 → 4.0.24
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/dist/index.d.ts +18 -11
- package/dist/index.js +1125 -960
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3007,6 +3007,32 @@ var BasicMIDI2 = class _BasicMIDI {
|
|
|
3007
3007
|
getUsedProgramsAndKeys(soundbank) {
|
|
3008
3008
|
return getUsedProgramsAndKeys(this, soundbank);
|
|
3009
3009
|
}
|
|
3010
|
+
/**
|
|
3011
|
+
* Preloads all voices for this sequence in a given synth.
|
|
3012
|
+
* This caches all the needed voices for playing back this sequencer, resulting in a smooth playback.
|
|
3013
|
+
* The sequencer calls this function by default when loading the songs.
|
|
3014
|
+
* @param synth
|
|
3015
|
+
*/
|
|
3016
|
+
preloadSynth(synth) {
|
|
3017
|
+
SpessaSynthGroupCollapsed(
|
|
3018
|
+
`%cPreloading samples...`,
|
|
3019
|
+
consoleColors.info
|
|
3020
|
+
);
|
|
3021
|
+
const used = this.getUsedProgramsAndKeys(synth.soundBankManager);
|
|
3022
|
+
used.forEach((combos, preset) => {
|
|
3023
|
+
SpessaSynthInfo(
|
|
3024
|
+
`%cPreloading used samples on %c${preset.name}%c...`,
|
|
3025
|
+
consoleColors.info,
|
|
3026
|
+
consoleColors.recognized,
|
|
3027
|
+
consoleColors.info
|
|
3028
|
+
);
|
|
3029
|
+
for (const combo of combos) {
|
|
3030
|
+
const [midiNote, velocity] = combo.split("-").map(Number);
|
|
3031
|
+
synth.getVoicesForPreset(preset, midiNote, velocity, midiNote);
|
|
3032
|
+
}
|
|
3033
|
+
});
|
|
3034
|
+
SpessaSynthGroupEnd();
|
|
3035
|
+
}
|
|
3010
3036
|
/**
|
|
3011
3037
|
* Updates all internal values of the MIDI.
|
|
3012
3038
|
* @param sortEvents if the events should be sorted by ticks. Recommended to be true.
|
|
@@ -3438,6 +3464,10 @@ var BasicMIDI2 = class _BasicMIDI {
|
|
|
3438
3464
|
loopEnd = this.lastVoiceEventTick;
|
|
3439
3465
|
}
|
|
3440
3466
|
this.loop = { start: loopStart, end: loopEnd, type: loopType };
|
|
3467
|
+
this.lastVoiceEventTick = Math.max(
|
|
3468
|
+
this.lastVoiceEventTick,
|
|
3469
|
+
this.loop.end
|
|
3470
|
+
);
|
|
3441
3471
|
SpessaSynthInfo(
|
|
3442
3472
|
`%cLoop points: start: %c${this.loop.start}%c end: %c${this.loop.end}`,
|
|
3443
3473
|
consoleColors.info,
|
|
@@ -3958,33 +3988,9 @@ function loadNewSequenceInternal(parsedMidi) {
|
|
|
3958
3988
|
this._midiData.embeddedSoundBank,
|
|
3959
3989
|
this._midiData.bankOffset
|
|
3960
3990
|
);
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
"%cPreloading samples...",
|
|
3965
|
-
consoleColors.info
|
|
3966
|
-
);
|
|
3967
|
-
const used = this._midiData.getUsedProgramsAndKeys(
|
|
3968
|
-
this.synth.soundBankManager
|
|
3969
|
-
);
|
|
3970
|
-
used.forEach((combos, preset) => {
|
|
3971
|
-
SpessaSynthInfo(
|
|
3972
|
-
`%cPreloading used samples on %c${preset.name}%c...`,
|
|
3973
|
-
consoleColors.info,
|
|
3974
|
-
consoleColors.recognized,
|
|
3975
|
-
consoleColors.info
|
|
3976
|
-
);
|
|
3977
|
-
for (const combo of combos) {
|
|
3978
|
-
const [midiNote, velocity] = combo.split("-").map(Number);
|
|
3979
|
-
this.synth.getVoicesForPreset(
|
|
3980
|
-
preset,
|
|
3981
|
-
midiNote,
|
|
3982
|
-
velocity,
|
|
3983
|
-
midiNote
|
|
3984
|
-
);
|
|
3985
|
-
}
|
|
3986
|
-
});
|
|
3987
|
-
SpessaSynthGroupEnd();
|
|
3991
|
+
if (this.preload) {
|
|
3992
|
+
this._midiData.preloadSynth(this.synth);
|
|
3993
|
+
}
|
|
3988
3994
|
}
|
|
3989
3995
|
this.currentMIDIPorts = this._midiData.tracks.map((t) => t.port);
|
|
3990
3996
|
this.midiPortChannelOffset = 0;
|
|
@@ -4582,8 +4588,6 @@ setResetValue(midiControllers.registeredParameterLSB, 127);
|
|
|
4582
4588
|
setResetValue(midiControllers.registeredParameterMSB, 127);
|
|
4583
4589
|
setResetValue(midiControllers.nonRegisteredParameterLSB, 127);
|
|
4584
4590
|
setResetValue(midiControllers.nonRegisteredParameterMSB, 127);
|
|
4585
|
-
var PORTAMENTO_CONTROL_UNSET = 1;
|
|
4586
|
-
defaultMIDIControllerValues[midiControllers.portamentoControl] = PORTAMENTO_CONTROL_UNSET;
|
|
4587
4591
|
setResetValue(
|
|
4588
4592
|
NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel,
|
|
4589
4593
|
64
|
|
@@ -4597,12 +4601,9 @@ var customResetArray = new Float32Array(CUSTOM_CONTROLLER_TABLE_SIZE);
|
|
|
4597
4601
|
customResetArray[customControllers.modulationMultiplier] = 1;
|
|
4598
4602
|
|
|
4599
4603
|
// src/synthesizer/audio_engine/engine_methods/controller_control/reset_controllers.ts
|
|
4600
|
-
function resetAllControllersInternal(
|
|
4601
|
-
if (log) {
|
|
4602
|
-
SpessaSynthInfo("%cResetting all controllers!", consoleColors.info);
|
|
4603
|
-
}
|
|
4604
|
+
function resetAllControllersInternal(system = DEFAULT_SYNTH_MODE) {
|
|
4604
4605
|
this.privateProps.callEvent("allControllerReset", void 0);
|
|
4605
|
-
this.setMasterParameter("midiSystem",
|
|
4606
|
+
this.setMasterParameter("midiSystem", system);
|
|
4606
4607
|
this.privateProps.tunings.length = 0;
|
|
4607
4608
|
for (let i = 0; i < 128; i++) {
|
|
4608
4609
|
this.privateProps.tunings.push([]);
|
|
@@ -4642,27 +4643,34 @@ function resetAllControllersInternal(log = true) {
|
|
|
4642
4643
|
}
|
|
4643
4644
|
}
|
|
4644
4645
|
}
|
|
4646
|
+
function resetPortamento(sendCC) {
|
|
4647
|
+
if (this.lockedControllers[midiControllers.portamentoControl]) return;
|
|
4648
|
+
if (this.channelSystem === "xg") {
|
|
4649
|
+
this.controllerChange(midiControllers.portamentoControl, 60, sendCC);
|
|
4650
|
+
} else {
|
|
4651
|
+
this.controllerChange(midiControllers.portamentoControl, 0, sendCC);
|
|
4652
|
+
}
|
|
4653
|
+
}
|
|
4645
4654
|
function resetControllers(sendCCEvents = true) {
|
|
4646
4655
|
this.channelOctaveTuning.fill(0);
|
|
4647
|
-
for (let
|
|
4648
|
-
if (this.lockedControllers[
|
|
4656
|
+
for (let cc = 0; cc < defaultMIDIControllerValues.length; cc++) {
|
|
4657
|
+
if (this.lockedControllers[cc]) {
|
|
4649
4658
|
continue;
|
|
4650
4659
|
}
|
|
4651
|
-
const resetValue = defaultMIDIControllerValues[
|
|
4652
|
-
if (this.midiControllers[
|
|
4653
|
-
if (
|
|
4654
|
-
this.midiControllers[i] = PORTAMENTO_CONTROL_UNSET;
|
|
4655
|
-
} else if (i !== midiControllers.portamentoControl && i !== midiControllers.dataEntryMSB && i !== midiControllers.registeredParameterMSB && i !== midiControllers.registeredParameterLSB && i !== midiControllers.nonRegisteredParameterMSB && i !== midiControllers.nonRegisteredParameterLSB) {
|
|
4660
|
+
const resetValue = defaultMIDIControllerValues[cc];
|
|
4661
|
+
if (this.midiControllers[cc] !== resetValue && cc < 127) {
|
|
4662
|
+
if (cc !== midiControllers.portamentoControl && cc !== midiControllers.dataEntryMSB && cc !== midiControllers.registeredParameterMSB && cc !== midiControllers.registeredParameterLSB && cc !== midiControllers.nonRegisteredParameterMSB && cc !== midiControllers.nonRegisteredParameterLSB) {
|
|
4656
4663
|
this.controllerChange(
|
|
4657
|
-
|
|
4664
|
+
cc,
|
|
4658
4665
|
resetValue >> 7,
|
|
4659
4666
|
sendCCEvents
|
|
4660
4667
|
);
|
|
4661
4668
|
}
|
|
4662
4669
|
} else {
|
|
4663
|
-
this.midiControllers[
|
|
4670
|
+
this.midiControllers[cc] = resetValue;
|
|
4664
4671
|
}
|
|
4665
4672
|
}
|
|
4673
|
+
resetPortamento.call(this, sendCCEvents);
|
|
4666
4674
|
this.channelVibrato = { rate: 0, depth: 0, delay: 0 };
|
|
4667
4675
|
this.randomPan = false;
|
|
4668
4676
|
this.sysExModulators.resetModulators();
|
|
@@ -4708,13 +4716,12 @@ function resetControllersRP15Compliant() {
|
|
|
4708
4716
|
for (let i = 0; i < 128; i++) {
|
|
4709
4717
|
const resetValue = defaultMIDIControllerValues[i];
|
|
4710
4718
|
if (!nonResettableCCs.has(i) && resetValue !== this.midiControllers[i]) {
|
|
4711
|
-
if (i
|
|
4712
|
-
this.midiControllers[i] = PORTAMENTO_CONTROL_UNSET;
|
|
4713
|
-
} else {
|
|
4719
|
+
if (i !== midiControllers.portamentoControl) {
|
|
4714
4720
|
this.controllerChange(i, resetValue >> 7);
|
|
4715
4721
|
}
|
|
4716
4722
|
}
|
|
4717
4723
|
}
|
|
4724
|
+
resetPortamento.call(this, true);
|
|
4718
4725
|
this.resetGeneratorOverrides();
|
|
4719
4726
|
this.resetGeneratorOffsets();
|
|
4720
4727
|
}
|
|
@@ -5166,6 +5173,15 @@ var SpessaSynthSequencer = class {
|
|
|
5166
5173
|
this._songIndex = 0;
|
|
5167
5174
|
this.shuffleSongIndexes();
|
|
5168
5175
|
this.callEvent("songListChange", { newSongList: [...this.songs] });
|
|
5176
|
+
if (this.preload) {
|
|
5177
|
+
SpessaSynthGroup("%cPreloading all songs...", consoleColors.info);
|
|
5178
|
+
this.songs.forEach((song) => {
|
|
5179
|
+
if (song.embeddedSoundBank === void 0) {
|
|
5180
|
+
song.preloadSynth(this.synth);
|
|
5181
|
+
}
|
|
5182
|
+
});
|
|
5183
|
+
SpessaSynthGroupEnd();
|
|
5184
|
+
}
|
|
5169
5185
|
this.loadCurrentSong();
|
|
5170
5186
|
}
|
|
5171
5187
|
callEvent(type, data) {
|
|
@@ -5202,7 +5218,7 @@ var SpessaSynthSequencer = class {
|
|
|
5202
5218
|
this.sendMIDIAllOff();
|
|
5203
5219
|
}
|
|
5204
5220
|
/**
|
|
5205
|
-
* @returns
|
|
5221
|
+
* @returns The track number of the next closest event, based on eventIndexes.
|
|
5206
5222
|
*/
|
|
5207
5223
|
findFirstEventIndex() {
|
|
5208
5224
|
let index = 0;
|
|
@@ -5302,26 +5318,27 @@ var SpessaSynthSequencer = class {
|
|
|
5302
5318
|
}
|
|
5303
5319
|
/**
|
|
5304
5320
|
* Jumps to a MIDI tick without any further processing.
|
|
5305
|
-
* @param
|
|
5321
|
+
* @param targetTicks The MIDI tick to jump to.
|
|
5306
5322
|
* @protected
|
|
5307
5323
|
*/
|
|
5308
|
-
jumpToTick(
|
|
5324
|
+
jumpToTick(targetTicks) {
|
|
5309
5325
|
if (!this._midiData) {
|
|
5310
5326
|
return;
|
|
5311
5327
|
}
|
|
5312
|
-
|
|
5328
|
+
this.sendMIDIAllOff();
|
|
5329
|
+
const seconds = this._midiData.midiTicksToSeconds(targetTicks);
|
|
5313
5330
|
this.callEvent("timeChange", { newTime: seconds });
|
|
5314
5331
|
this.recalculateStartTime(seconds);
|
|
5315
5332
|
this.playedTime = seconds;
|
|
5316
5333
|
this.eventIndexes.length = 0;
|
|
5317
5334
|
for (const track of this._midiData.tracks) {
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
0,
|
|
5321
|
-
track.events.findIndex((e) => e.ticks >= tick)
|
|
5322
|
-
)
|
|
5323
|
-
);
|
|
5335
|
+
const idx = track.events.findIndex((e) => e.ticks >= targetTicks);
|
|
5336
|
+
this.eventIndexes.push(idx < 0 ? track.events.length : idx);
|
|
5324
5337
|
}
|
|
5338
|
+
const targetTempo = this._midiData.tempoChanges.find(
|
|
5339
|
+
(t) => t.ticks <= targetTicks
|
|
5340
|
+
);
|
|
5341
|
+
this.oneTickToSeconds = 60 / (targetTempo.tempo * this._midiData.timeDivision);
|
|
5325
5342
|
}
|
|
5326
5343
|
/*
|
|
5327
5344
|
SEND MIDI METHOD ABSTRACTIONS
|
|
@@ -6901,20 +6918,6 @@ var defaultSoundFont2Modulators = [
|
|
|
6901
6918
|
];
|
|
6902
6919
|
var defaultSpessaSynthModulators = [
|
|
6903
6920
|
// Custom modulators heck yeah
|
|
6904
|
-
// Poly pressure to vibrato
|
|
6905
|
-
new DecodedModulator(
|
|
6906
|
-
getModSourceEnum(
|
|
6907
|
-
modulatorCurveTypes.linear,
|
|
6908
|
-
false,
|
|
6909
|
-
false,
|
|
6910
|
-
false,
|
|
6911
|
-
modulatorSources.polyPressure
|
|
6912
|
-
),
|
|
6913
|
-
0,
|
|
6914
|
-
generatorTypes.vibLfoToPitch,
|
|
6915
|
-
50,
|
|
6916
|
-
0
|
|
6917
|
-
),
|
|
6918
6921
|
// Cc 92 (tremolo) to modLFO volume
|
|
6919
6922
|
new DecodedModulator(
|
|
6920
6923
|
getModSourceEnum(
|
|
@@ -6962,6 +6965,22 @@ var defaultSpessaSynthModulators = [
|
|
|
6962
6965
|
3600,
|
|
6963
6966
|
0
|
|
6964
6967
|
),
|
|
6968
|
+
// Cc 75 (decay time) to vol env decay
|
|
6969
|
+
new DecodedModulator(
|
|
6970
|
+
getModSourceEnum(
|
|
6971
|
+
modulatorCurveTypes.linear,
|
|
6972
|
+
true,
|
|
6973
|
+
false,
|
|
6974
|
+
true,
|
|
6975
|
+
midiControllers.decayTime
|
|
6976
|
+
),
|
|
6977
|
+
// Linear forward bipolar cc 75
|
|
6978
|
+
0,
|
|
6979
|
+
// No controller
|
|
6980
|
+
generatorTypes.decayVolEnv,
|
|
6981
|
+
3600,
|
|
6982
|
+
0
|
|
6983
|
+
),
|
|
6965
6984
|
// Cc 74 (brightness) to filterFc
|
|
6966
6985
|
new DecodedModulator(
|
|
6967
6986
|
getModSourceEnum(
|
|
@@ -6975,7 +6994,7 @@ var defaultSpessaSynthModulators = [
|
|
|
6975
6994
|
0,
|
|
6976
6995
|
// No controller
|
|
6977
6996
|
generatorTypes.initialFilterFc,
|
|
6978
|
-
|
|
6997
|
+
9600,
|
|
6979
6998
|
0
|
|
6980
6999
|
),
|
|
6981
7000
|
// Cc 71 (filter Q) to filter Q (default resonant modulator)
|
|
@@ -6984,7 +7003,55 @@ var defaultSpessaSynthModulators = [
|
|
|
6984
7003
|
0,
|
|
6985
7004
|
// No controller
|
|
6986
7005
|
generatorTypes.initialFilterQ,
|
|
6987
|
-
|
|
7006
|
+
200,
|
|
7007
|
+
0
|
|
7008
|
+
),
|
|
7009
|
+
// Cc 67 (soft pedal) to attenuation
|
|
7010
|
+
new DecodedModulator(
|
|
7011
|
+
getModSourceEnum(
|
|
7012
|
+
modulatorCurveTypes.switch,
|
|
7013
|
+
false,
|
|
7014
|
+
false,
|
|
7015
|
+
true,
|
|
7016
|
+
midiControllers.softPedal
|
|
7017
|
+
),
|
|
7018
|
+
// Switch unipolar positive 67
|
|
7019
|
+
0,
|
|
7020
|
+
// No controller
|
|
7021
|
+
generatorTypes.initialAttenuation,
|
|
7022
|
+
50,
|
|
7023
|
+
0
|
|
7024
|
+
),
|
|
7025
|
+
// Cc 67 (soft pedal) to filter fc
|
|
7026
|
+
new DecodedModulator(
|
|
7027
|
+
getModSourceEnum(
|
|
7028
|
+
modulatorCurveTypes.switch,
|
|
7029
|
+
false,
|
|
7030
|
+
false,
|
|
7031
|
+
true,
|
|
7032
|
+
midiControllers.softPedal
|
|
7033
|
+
),
|
|
7034
|
+
// Switch unipolar positive 67
|
|
7035
|
+
0,
|
|
7036
|
+
// No controller
|
|
7037
|
+
generatorTypes.initialFilterFc,
|
|
7038
|
+
-2400,
|
|
7039
|
+
0
|
|
7040
|
+
),
|
|
7041
|
+
// Cc 8 (balance) to pan
|
|
7042
|
+
new DecodedModulator(
|
|
7043
|
+
getModSourceEnum(
|
|
7044
|
+
modulatorCurveTypes.linear,
|
|
7045
|
+
true,
|
|
7046
|
+
false,
|
|
7047
|
+
true,
|
|
7048
|
+
midiControllers.balance
|
|
7049
|
+
),
|
|
7050
|
+
// Linear bipolar positive 8
|
|
7051
|
+
0,
|
|
7052
|
+
// No controller
|
|
7053
|
+
generatorTypes.pan,
|
|
7054
|
+
500,
|
|
6988
7055
|
0
|
|
6989
7056
|
)
|
|
6990
7057
|
];
|
|
@@ -8273,7 +8340,7 @@ function panAndMixVoice(voice, inputBuffer, outputLeft, outputRight, reverbLeft,
|
|
|
8273
8340
|
}
|
|
8274
8341
|
|
|
8275
8342
|
// src/synthesizer/audio_engine/engine_components/dsp_chain/lowpass_filter.ts
|
|
8276
|
-
var FILTER_SMOOTHING_FACTOR = 0.
|
|
8343
|
+
var FILTER_SMOOTHING_FACTOR = 0.03;
|
|
8277
8344
|
var LowpassFilter = class _LowpassFilter {
|
|
8278
8345
|
/**
|
|
8279
8346
|
* Cached coefficient calculations.
|
|
@@ -8954,7 +9021,29 @@ function getVoicesInternal(channel, midiNote, velocity, realKey) {
|
|
|
8954
9021
|
return this.getVoicesForPreset(preset, midiNote, velocity, realKey);
|
|
8955
9022
|
}
|
|
8956
9023
|
|
|
8957
|
-
// src/synthesizer/audio_engine/engine_methods/system_exclusive.ts
|
|
9024
|
+
// src/synthesizer/audio_engine/engine_methods/system_exclusive/helpers.ts
|
|
9025
|
+
function sysExLogging(syx, channel, value, what, units) {
|
|
9026
|
+
SpessaSynthInfo(
|
|
9027
|
+
`%cChannel %c${channel}%c ${what}. %c${value} ${units}%c, with %c${arrayToHexString(syx)}`,
|
|
9028
|
+
consoleColors.info,
|
|
9029
|
+
consoleColors.recognized,
|
|
9030
|
+
consoleColors.info,
|
|
9031
|
+
consoleColors.value,
|
|
9032
|
+
consoleColors.info,
|
|
9033
|
+
consoleColors.value
|
|
9034
|
+
);
|
|
9035
|
+
}
|
|
9036
|
+
function sysExNotRecognized(syx, what) {
|
|
9037
|
+
SpessaSynthInfo(
|
|
9038
|
+
`%cUnrecognized %c${what} %cSysEx: %c${arrayToHexString(syx)}`,
|
|
9039
|
+
consoleColors.warn,
|
|
9040
|
+
consoleColors.recognized,
|
|
9041
|
+
consoleColors.warn,
|
|
9042
|
+
consoleColors.unrecognized
|
|
9043
|
+
);
|
|
9044
|
+
}
|
|
9045
|
+
|
|
9046
|
+
// src/synthesizer/audio_engine/engine_methods/system_exclusive/handle_gm.ts
|
|
8958
9047
|
function getTuning(byte1, byte2, byte3) {
|
|
8959
9048
|
const midiNote = byte1;
|
|
8960
9049
|
const fraction = byte2 << 7 | byte3;
|
|
@@ -8963,900 +9052,971 @@ function getTuning(byte1, byte2, byte3) {
|
|
|
8963
9052
|
}
|
|
8964
9053
|
return { midiNote, centTuning: fraction * 61e-4 };
|
|
8965
9054
|
}
|
|
8966
|
-
function
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
9055
|
+
function handleGM(syx, channelOffset = 0) {
|
|
9056
|
+
switch (syx[2]) {
|
|
9057
|
+
case 4: {
|
|
9058
|
+
let cents;
|
|
9059
|
+
switch (syx[3]) {
|
|
9060
|
+
case 1: {
|
|
9061
|
+
const vol = syx[5] << 7 | syx[4];
|
|
9062
|
+
this.setMIDIVolume(vol / 16384);
|
|
9063
|
+
SpessaSynthInfo(
|
|
9064
|
+
`%cMaster Volume. Volume: %c${vol}`,
|
|
9065
|
+
consoleColors.info,
|
|
9066
|
+
consoleColors.value
|
|
9067
|
+
);
|
|
9068
|
+
break;
|
|
9069
|
+
}
|
|
9070
|
+
case 2: {
|
|
9071
|
+
const balance = syx[5] << 7 | syx[4];
|
|
9072
|
+
const pan = (balance - 8192) / 8192;
|
|
9073
|
+
this.setMasterParameter("masterPan", pan);
|
|
9074
|
+
SpessaSynthInfo(
|
|
9075
|
+
`%cMaster Pan. Pan: %c${pan}`,
|
|
9076
|
+
consoleColors.info,
|
|
9077
|
+
consoleColors.value
|
|
9078
|
+
);
|
|
9079
|
+
break;
|
|
9080
|
+
}
|
|
9081
|
+
case 3: {
|
|
9082
|
+
const tuningValue = (syx[5] << 7 | syx[6]) - 8192;
|
|
9083
|
+
cents = Math.floor(tuningValue / 81.92);
|
|
9084
|
+
this.setMasterTuning(cents);
|
|
9085
|
+
SpessaSynthInfo(
|
|
9086
|
+
`%cMaster Fine Tuning. Cents: %c${cents}`,
|
|
9087
|
+
consoleColors.info,
|
|
9088
|
+
consoleColors.value
|
|
9089
|
+
);
|
|
9090
|
+
break;
|
|
9091
|
+
}
|
|
9092
|
+
case 4: {
|
|
9093
|
+
const semitones = syx[5] - 64;
|
|
9094
|
+
cents = semitones * 100;
|
|
9095
|
+
this.setMasterTuning(cents);
|
|
9096
|
+
SpessaSynthInfo(
|
|
9097
|
+
`%cMaster Coarse Tuning. Cents: %c${cents}`,
|
|
9098
|
+
consoleColors.info,
|
|
9099
|
+
consoleColors.value
|
|
9100
|
+
);
|
|
9101
|
+
break;
|
|
9102
|
+
}
|
|
9103
|
+
default:
|
|
9104
|
+
SpessaSynthInfo(
|
|
9105
|
+
`%cUnrecognized MIDI Device Control Real-time message: %c${arrayToHexString(syx)}`,
|
|
9106
|
+
consoleColors.warn,
|
|
9107
|
+
consoleColors.unrecognized
|
|
9108
|
+
);
|
|
9109
|
+
}
|
|
9110
|
+
break;
|
|
8971
9111
|
}
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
SpessaSynthInfo(
|
|
8987
|
-
`%cUnrecognized SysEx: %c${arrayToHexString(syx)}`,
|
|
8988
|
-
consoleColors.warn,
|
|
8989
|
-
consoleColors.unrecognized
|
|
8990
|
-
);
|
|
9112
|
+
case 9:
|
|
9113
|
+
if (syx[3] === 1) {
|
|
9114
|
+
SpessaSynthInfo("%cGM1 system on", consoleColors.info);
|
|
9115
|
+
this.resetAllControllers("gm");
|
|
9116
|
+
} else if (syx[3] === 3) {
|
|
9117
|
+
SpessaSynthInfo("%cGM2 system on", consoleColors.info);
|
|
9118
|
+
this.resetAllControllers("gm2");
|
|
9119
|
+
} else {
|
|
9120
|
+
SpessaSynthInfo(
|
|
9121
|
+
"%cGM system off, defaulting to GS",
|
|
9122
|
+
consoleColors.info
|
|
9123
|
+
);
|
|
9124
|
+
this.setMasterParameter("midiSystem", "gs");
|
|
9125
|
+
}
|
|
8991
9126
|
break;
|
|
8992
|
-
//
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
switch (syx[
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
);
|
|
9019
|
-
break;
|
|
9020
|
-
}
|
|
9021
|
-
case 3: {
|
|
9022
|
-
const tuningValue = (syx[5] << 7 | syx[6]) - 8192;
|
|
9023
|
-
cents = Math.floor(tuningValue / 81.92);
|
|
9024
|
-
this.setMasterTuning(cents);
|
|
9025
|
-
SpessaSynthInfo(
|
|
9026
|
-
`%cMaster Fine Tuning. Cents: %c${cents}`,
|
|
9027
|
-
consoleColors.info,
|
|
9028
|
-
consoleColors.value
|
|
9029
|
-
);
|
|
9030
|
-
break;
|
|
9031
|
-
}
|
|
9032
|
-
case 4: {
|
|
9033
|
-
const semitones = syx[5] - 64;
|
|
9034
|
-
cents = semitones * 100;
|
|
9035
|
-
this.setMasterTuning(cents);
|
|
9036
|
-
SpessaSynthInfo(
|
|
9037
|
-
`%cMaster Coarse Tuning. Cents: %c${cents}`,
|
|
9038
|
-
consoleColors.info,
|
|
9039
|
-
consoleColors.value
|
|
9040
|
-
);
|
|
9041
|
-
break;
|
|
9042
|
-
}
|
|
9043
|
-
default:
|
|
9044
|
-
SpessaSynthInfo(
|
|
9045
|
-
`%cUnrecognized MIDI Device Control Real-time message: %c${arrayToHexString(syx)}`,
|
|
9046
|
-
consoleColors.warn,
|
|
9047
|
-
consoleColors.unrecognized
|
|
9048
|
-
);
|
|
9127
|
+
// MIDI Tuning standard
|
|
9128
|
+
// https://midi.org/midi-tuning-updated-specification
|
|
9129
|
+
case 8: {
|
|
9130
|
+
let currentMessageIndex = 4;
|
|
9131
|
+
switch (syx[3]) {
|
|
9132
|
+
// Bulk tuning dump: all 128 notes
|
|
9133
|
+
case 1: {
|
|
9134
|
+
const program = syx[currentMessageIndex++];
|
|
9135
|
+
const tuningName = readBinaryString(
|
|
9136
|
+
syx,
|
|
9137
|
+
16,
|
|
9138
|
+
currentMessageIndex
|
|
9139
|
+
);
|
|
9140
|
+
currentMessageIndex += 16;
|
|
9141
|
+
if (syx.length < 384) {
|
|
9142
|
+
SpessaSynthWarn(
|
|
9143
|
+
`The Bulk Tuning Dump is too short! (${syx.length} bytes, at least 384 are expected)`
|
|
9144
|
+
);
|
|
9145
|
+
return;
|
|
9146
|
+
}
|
|
9147
|
+
for (let i = 0; i < 128; i++) {
|
|
9148
|
+
this.privateProps.tunings[program][i] = getTuning(
|
|
9149
|
+
syx[currentMessageIndex++],
|
|
9150
|
+
syx[currentMessageIndex++],
|
|
9151
|
+
syx[currentMessageIndex++]
|
|
9152
|
+
);
|
|
9049
9153
|
}
|
|
9154
|
+
SpessaSynthInfo(
|
|
9155
|
+
`%cBulk Tuning Dump %c${tuningName}%c Program: %c${program}`,
|
|
9156
|
+
consoleColors.info,
|
|
9157
|
+
consoleColors.value,
|
|
9158
|
+
consoleColors.info,
|
|
9159
|
+
consoleColors.recognized
|
|
9160
|
+
);
|
|
9161
|
+
break;
|
|
9162
|
+
}
|
|
9163
|
+
// Single note change
|
|
9164
|
+
// Single note change bank
|
|
9165
|
+
case 2:
|
|
9166
|
+
case 7: {
|
|
9167
|
+
if (syx[3] === 7) {
|
|
9168
|
+
currentMessageIndex++;
|
|
9169
|
+
}
|
|
9170
|
+
const tuningProgram = syx[currentMessageIndex++];
|
|
9171
|
+
const numberOfChanges = syx[currentMessageIndex++];
|
|
9172
|
+
for (let i = 0; i < numberOfChanges; i++) {
|
|
9173
|
+
this.privateProps.tunings[tuningProgram][syx[currentMessageIndex++]] = getTuning(
|
|
9174
|
+
syx[currentMessageIndex++],
|
|
9175
|
+
syx[currentMessageIndex++],
|
|
9176
|
+
syx[currentMessageIndex++]
|
|
9177
|
+
);
|
|
9178
|
+
}
|
|
9179
|
+
SpessaSynthInfo(
|
|
9180
|
+
`%cSingle Note Tuning. Program: %c${tuningProgram}%c Keys affected: %c${numberOfChanges}`,
|
|
9181
|
+
consoleColors.info,
|
|
9182
|
+
consoleColors.recognized,
|
|
9183
|
+
consoleColors.info,
|
|
9184
|
+
consoleColors.recognized
|
|
9185
|
+
);
|
|
9050
9186
|
break;
|
|
9051
9187
|
}
|
|
9188
|
+
// Octave tuning (1 byte)
|
|
9189
|
+
// And octave tuning (2 bytes)
|
|
9052
9190
|
case 9:
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9191
|
+
case 8: {
|
|
9192
|
+
const newOctaveTuning = new Int8Array(12);
|
|
9193
|
+
if (syx[3] === 8) {
|
|
9194
|
+
for (let i = 0; i < 12; i++) {
|
|
9195
|
+
newOctaveTuning[i] = syx[7 + i] - 64;
|
|
9196
|
+
}
|
|
9059
9197
|
} else {
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9198
|
+
for (let i = 0; i < 24; i += 2) {
|
|
9199
|
+
const tuning = (syx[7 + i] << 7 | syx[8 + i]) - 8192;
|
|
9200
|
+
newOctaveTuning[i / 2] = Math.floor(tuning / 81.92);
|
|
9201
|
+
}
|
|
9202
|
+
}
|
|
9203
|
+
if ((syx[4] & 1) === 1) {
|
|
9204
|
+
this.midiChannels[14 + channelOffset].setOctaveTuning(
|
|
9205
|
+
newOctaveTuning
|
|
9063
9206
|
);
|
|
9064
|
-
this.setMasterParameter("midiSystem", "gs");
|
|
9065
9207
|
}
|
|
9208
|
+
if ((syx[4] >> 1 & 1) === 1) {
|
|
9209
|
+
this.midiChannels[15 + channelOffset].setOctaveTuning(
|
|
9210
|
+
newOctaveTuning
|
|
9211
|
+
);
|
|
9212
|
+
}
|
|
9213
|
+
for (let i = 0; i < 7; i++) {
|
|
9214
|
+
const bit = syx[5] >> i & 1;
|
|
9215
|
+
if (bit === 1) {
|
|
9216
|
+
this.midiChannels[7 + i + channelOffset].setOctaveTuning(newOctaveTuning);
|
|
9217
|
+
}
|
|
9218
|
+
}
|
|
9219
|
+
for (let i = 0; i < 7; i++) {
|
|
9220
|
+
const bit = syx[6] >> i & 1;
|
|
9221
|
+
if (bit === 1) {
|
|
9222
|
+
this.midiChannels[i + channelOffset].setOctaveTuning(newOctaveTuning);
|
|
9223
|
+
}
|
|
9224
|
+
}
|
|
9225
|
+
SpessaSynthInfo(
|
|
9226
|
+
`%cMIDI Octave Scale ${syx[3] === 8 ? "(1 byte)" : "(2 bytes)"} tuning via Tuning: %c${newOctaveTuning.join(" ")}`,
|
|
9227
|
+
consoleColors.info,
|
|
9228
|
+
consoleColors.value
|
|
9229
|
+
);
|
|
9066
9230
|
break;
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9231
|
+
}
|
|
9232
|
+
default:
|
|
9233
|
+
sysExNotRecognized(syx, "MIDI Tuning Standard");
|
|
9234
|
+
break;
|
|
9235
|
+
}
|
|
9236
|
+
break;
|
|
9237
|
+
}
|
|
9238
|
+
default:
|
|
9239
|
+
sysExNotRecognized(syx, "General MIDI");
|
|
9240
|
+
}
|
|
9241
|
+
}
|
|
9242
|
+
|
|
9243
|
+
// src/synthesizer/audio_engine/engine_methods/system_exclusive/handle_gs.ts
|
|
9244
|
+
function handleGS(syx, channelOffset = 0) {
|
|
9245
|
+
if (syx[3] === 18) {
|
|
9246
|
+
switch (syx[2]) {
|
|
9247
|
+
case 66: {
|
|
9248
|
+
const messageValue = syx[7];
|
|
9249
|
+
if (syx[4] === 64 || syx[4] === 0 && syx[6] === 127) {
|
|
9250
|
+
if ((syx[5] & 16) > 0) {
|
|
9251
|
+
const channel = [
|
|
9252
|
+
9,
|
|
9253
|
+
0,
|
|
9254
|
+
1,
|
|
9255
|
+
2,
|
|
9256
|
+
3,
|
|
9257
|
+
4,
|
|
9258
|
+
5,
|
|
9259
|
+
6,
|
|
9260
|
+
7,
|
|
9261
|
+
8,
|
|
9262
|
+
10,
|
|
9263
|
+
11,
|
|
9264
|
+
12,
|
|
9265
|
+
13,
|
|
9266
|
+
14,
|
|
9267
|
+
15
|
|
9268
|
+
][syx[5] & 15] + channelOffset;
|
|
9269
|
+
const channelObject = this.midiChannels[channel];
|
|
9270
|
+
switch (syx[6]) {
|
|
9271
|
+
default:
|
|
9272
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9273
|
+
break;
|
|
9274
|
+
case 21: {
|
|
9275
|
+
const isDrums = messageValue > 0 && syx[5] >> 4 > 0;
|
|
9276
|
+
channelObject.setGSDrums(isDrums);
|
|
9277
|
+
SpessaSynthInfo(
|
|
9278
|
+
`%cChannel %c${channel}%c ${isDrums ? "is now a drum channel" : "now isn't a drum channel"}%c via: %c${arrayToHexString(syx)}`,
|
|
9279
|
+
consoleColors.info,
|
|
9280
|
+
consoleColors.value,
|
|
9281
|
+
consoleColors.recognized,
|
|
9282
|
+
consoleColors.info,
|
|
9283
|
+
consoleColors.value
|
|
9084
9284
|
);
|
|
9085
9285
|
return;
|
|
9086
9286
|
}
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9287
|
+
case 22: {
|
|
9288
|
+
const keyShift = messageValue - 64;
|
|
9289
|
+
channelObject.setCustomController(
|
|
9290
|
+
customControllers.channelKeyShift,
|
|
9291
|
+
keyShift
|
|
9092
9292
|
);
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
consoleColors.recognized
|
|
9100
|
-
);
|
|
9101
|
-
break;
|
|
9102
|
-
}
|
|
9103
|
-
// Single note change
|
|
9104
|
-
// Single note change bank
|
|
9105
|
-
case 2:
|
|
9106
|
-
case 7: {
|
|
9107
|
-
if (syx[3] === 7) {
|
|
9108
|
-
currentMessageIndex++;
|
|
9109
|
-
}
|
|
9110
|
-
const tuningProgram = syx[currentMessageIndex++];
|
|
9111
|
-
const numberOfChanges = syx[currentMessageIndex++];
|
|
9112
|
-
for (let i = 0; i < numberOfChanges; i++) {
|
|
9113
|
-
this.privateProps.tunings[tuningProgram][syx[currentMessageIndex++]] = getTuning(
|
|
9114
|
-
syx[currentMessageIndex++],
|
|
9115
|
-
syx[currentMessageIndex++],
|
|
9116
|
-
syx[currentMessageIndex++]
|
|
9293
|
+
sysExLogging(
|
|
9294
|
+
syx,
|
|
9295
|
+
channel,
|
|
9296
|
+
keyShift,
|
|
9297
|
+
"key shift",
|
|
9298
|
+
"keys"
|
|
9117
9299
|
);
|
|
9300
|
+
return;
|
|
9118
9301
|
}
|
|
9119
|
-
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9126
|
-
|
|
9127
|
-
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
}
|
|
9137
|
-
} else {
|
|
9138
|
-
for (let i = 0; i < 24; i += 2) {
|
|
9139
|
-
const tuning = (syx[7 + i] << 7 | syx[8 + i]) - 8192;
|
|
9140
|
-
newOctaveTuning[i / 2] = Math.floor(
|
|
9141
|
-
tuning / 81.92
|
|
9302
|
+
// Pan position
|
|
9303
|
+
case 28: {
|
|
9304
|
+
const panPosition = messageValue;
|
|
9305
|
+
if (panPosition === 0) {
|
|
9306
|
+
channelObject.randomPan = true;
|
|
9307
|
+
SpessaSynthInfo(
|
|
9308
|
+
`%cRandom pan is set to %cON%c for %c${channel}`,
|
|
9309
|
+
consoleColors.info,
|
|
9310
|
+
consoleColors.recognized,
|
|
9311
|
+
consoleColors.info,
|
|
9312
|
+
consoleColors.value
|
|
9313
|
+
);
|
|
9314
|
+
} else {
|
|
9315
|
+
channelObject.randomPan = false;
|
|
9316
|
+
channelObject.controllerChange(
|
|
9317
|
+
midiControllers.pan,
|
|
9318
|
+
panPosition
|
|
9142
9319
|
);
|
|
9143
9320
|
}
|
|
9321
|
+
break;
|
|
9144
9322
|
}
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9323
|
+
// Chorus send
|
|
9324
|
+
case 33:
|
|
9325
|
+
channelObject.controllerChange(
|
|
9326
|
+
midiControllers.chorusDepth,
|
|
9327
|
+
messageValue
|
|
9328
|
+
);
|
|
9329
|
+
break;
|
|
9330
|
+
// Reverb send
|
|
9331
|
+
case 34:
|
|
9332
|
+
channelObject.controllerChange(
|
|
9333
|
+
midiControllers.reverbDepth,
|
|
9334
|
+
messageValue
|
|
9335
|
+
);
|
|
9336
|
+
break;
|
|
9337
|
+
case 64:
|
|
9338
|
+
case 65:
|
|
9339
|
+
case 66:
|
|
9340
|
+
case 67:
|
|
9341
|
+
case 68:
|
|
9342
|
+
case 69:
|
|
9343
|
+
case 70:
|
|
9344
|
+
case 71:
|
|
9345
|
+
case 72:
|
|
9346
|
+
case 73:
|
|
9347
|
+
case 74:
|
|
9348
|
+
case 75: {
|
|
9349
|
+
const tuningBytes = syx.length - 9;
|
|
9350
|
+
const newTuning = new Int8Array(12);
|
|
9351
|
+
for (let i = 0; i < tuningBytes; i++) {
|
|
9352
|
+
newTuning[i] = syx[i + 7] - 64;
|
|
9161
9353
|
}
|
|
9354
|
+
channelObject.setOctaveTuning(newTuning);
|
|
9355
|
+
const cents = messageValue - 64;
|
|
9356
|
+
sysExLogging(
|
|
9357
|
+
syx,
|
|
9358
|
+
channel,
|
|
9359
|
+
newTuning.join(" "),
|
|
9360
|
+
"octave scale tuning",
|
|
9361
|
+
"cents"
|
|
9362
|
+
);
|
|
9363
|
+
channelObject.setTuning(cents);
|
|
9364
|
+
break;
|
|
9162
9365
|
}
|
|
9163
|
-
SpessaSynthInfo(
|
|
9164
|
-
`%cMIDI Octave Scale ${syx[3] === 8 ? "(1 byte)" : "(2 bytes)"} tuning via Tuning: %c${newOctaveTuning.join(" ")}`,
|
|
9165
|
-
consoleColors.info,
|
|
9166
|
-
consoleColors.value
|
|
9167
|
-
);
|
|
9168
|
-
break;
|
|
9169
9366
|
}
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
consoleColors.warn,
|
|
9199
|
-
consoleColors.unrecognized
|
|
9200
|
-
);
|
|
9201
|
-
};
|
|
9202
|
-
var notRecognized = notRecognized2;
|
|
9203
|
-
switch (syx[2]) {
|
|
9204
|
-
case 66: {
|
|
9205
|
-
const messageValue = syx[7];
|
|
9206
|
-
if (syx[4] === 64 || syx[4] === 0 && syx[6] === 127) {
|
|
9207
|
-
if ((syx[5] & 16) > 0) {
|
|
9208
|
-
const channel = [
|
|
9209
|
-
9,
|
|
9210
|
-
0,
|
|
9211
|
-
1,
|
|
9212
|
-
2,
|
|
9213
|
-
3,
|
|
9214
|
-
4,
|
|
9215
|
-
5,
|
|
9216
|
-
6,
|
|
9217
|
-
7,
|
|
9218
|
-
8,
|
|
9219
|
-
10,
|
|
9220
|
-
11,
|
|
9221
|
-
12,
|
|
9222
|
-
13,
|
|
9223
|
-
14,
|
|
9224
|
-
15
|
|
9225
|
-
][syx[5] & 15] + channelOffset;
|
|
9226
|
-
const channelObject = this.midiChannels[channel];
|
|
9227
|
-
switch (syx[6]) {
|
|
9228
|
-
default:
|
|
9229
|
-
notRecognized2();
|
|
9230
|
-
break;
|
|
9231
|
-
case 21: {
|
|
9232
|
-
const isDrums = messageValue > 0 && syx[5] >> 4 > 0;
|
|
9233
|
-
channelObject.setGSDrums(isDrums);
|
|
9234
|
-
SpessaSynthInfo(
|
|
9235
|
-
`%cChannel %c${channel}%c ${isDrums ? "is now a drum channel" : "now isn't a drum channel"}%c via: %c${arrayToHexString(syx)}`,
|
|
9236
|
-
consoleColors.info,
|
|
9237
|
-
consoleColors.value,
|
|
9238
|
-
consoleColors.recognized,
|
|
9239
|
-
consoleColors.info,
|
|
9240
|
-
consoleColors.value
|
|
9241
|
-
);
|
|
9242
|
-
return;
|
|
9243
|
-
}
|
|
9244
|
-
case 22: {
|
|
9245
|
-
const keyShift = messageValue - 64;
|
|
9246
|
-
channelObject.setCustomController(
|
|
9247
|
-
customControllers.channelKeyShift,
|
|
9248
|
-
keyShift
|
|
9249
|
-
);
|
|
9250
|
-
niceLogging(
|
|
9251
|
-
channel,
|
|
9252
|
-
keyShift,
|
|
9253
|
-
"key shift",
|
|
9254
|
-
"keys"
|
|
9255
|
-
);
|
|
9256
|
-
return;
|
|
9257
|
-
}
|
|
9258
|
-
// Pan position
|
|
9259
|
-
case 28: {
|
|
9260
|
-
const panPosition = messageValue;
|
|
9261
|
-
if (panPosition === 0) {
|
|
9262
|
-
channelObject.randomPan = true;
|
|
9263
|
-
SpessaSynthInfo(
|
|
9264
|
-
`%cRandom pan is set to %cON%c for %c${channel}`,
|
|
9265
|
-
consoleColors.info,
|
|
9266
|
-
consoleColors.recognized,
|
|
9267
|
-
consoleColors.info,
|
|
9268
|
-
consoleColors.value
|
|
9269
|
-
);
|
|
9270
|
-
} else {
|
|
9271
|
-
channelObject.randomPan = false;
|
|
9272
|
-
channelObject.controllerChange(
|
|
9273
|
-
midiControllers.pan,
|
|
9274
|
-
panPosition
|
|
9275
|
-
);
|
|
9276
|
-
}
|
|
9277
|
-
break;
|
|
9278
|
-
}
|
|
9279
|
-
// Chorus send
|
|
9280
|
-
case 33:
|
|
9367
|
+
return;
|
|
9368
|
+
} else if ((syx[5] & 32) > 0) {
|
|
9369
|
+
const channel = [
|
|
9370
|
+
9,
|
|
9371
|
+
0,
|
|
9372
|
+
1,
|
|
9373
|
+
2,
|
|
9374
|
+
3,
|
|
9375
|
+
4,
|
|
9376
|
+
5,
|
|
9377
|
+
6,
|
|
9378
|
+
7,
|
|
9379
|
+
8,
|
|
9380
|
+
10,
|
|
9381
|
+
11,
|
|
9382
|
+
12,
|
|
9383
|
+
13,
|
|
9384
|
+
14,
|
|
9385
|
+
15
|
|
9386
|
+
][syx[5] & 15] + channelOffset;
|
|
9387
|
+
const channelObject = this.midiChannels[channel];
|
|
9388
|
+
const centeredValue = messageValue - 64;
|
|
9389
|
+
const normalizedValue = centeredValue / 64;
|
|
9390
|
+
const normalizedNotCentered = messageValue / 128;
|
|
9391
|
+
const setupReceivers = (source, sourceName, bipolar = false) => {
|
|
9392
|
+
switch (syx[6] & 15) {
|
|
9393
|
+
case 0:
|
|
9394
|
+
if (source === NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel) {
|
|
9281
9395
|
channelObject.controllerChange(
|
|
9282
|
-
midiControllers.
|
|
9283
|
-
|
|
9396
|
+
midiControllers.registeredParameterMSB,
|
|
9397
|
+
0
|
|
9284
9398
|
);
|
|
9285
|
-
break;
|
|
9286
|
-
// Reverb send
|
|
9287
|
-
case 34:
|
|
9288
9399
|
channelObject.controllerChange(
|
|
9289
|
-
midiControllers.
|
|
9290
|
-
|
|
9291
|
-
);
|
|
9292
|
-
break;
|
|
9293
|
-
case 64:
|
|
9294
|
-
case 65:
|
|
9295
|
-
case 66:
|
|
9296
|
-
case 67:
|
|
9297
|
-
case 68:
|
|
9298
|
-
case 69:
|
|
9299
|
-
case 70:
|
|
9300
|
-
case 71:
|
|
9301
|
-
case 72:
|
|
9302
|
-
case 73:
|
|
9303
|
-
case 74:
|
|
9304
|
-
case 75: {
|
|
9305
|
-
const tuningBytes = syx.length - 9;
|
|
9306
|
-
const newTuning = new Int8Array(12);
|
|
9307
|
-
for (let i = 0; i < tuningBytes; i++) {
|
|
9308
|
-
newTuning[i] = syx[i + 7] - 64;
|
|
9309
|
-
}
|
|
9310
|
-
channelObject.setOctaveTuning(
|
|
9311
|
-
newTuning
|
|
9312
|
-
);
|
|
9313
|
-
const cents = messageValue - 64;
|
|
9314
|
-
niceLogging(
|
|
9315
|
-
channel,
|
|
9316
|
-
newTuning.join(" "),
|
|
9317
|
-
"octave scale tuning",
|
|
9318
|
-
"cents"
|
|
9319
|
-
);
|
|
9320
|
-
channelObject.setTuning(cents);
|
|
9321
|
-
break;
|
|
9322
|
-
}
|
|
9323
|
-
}
|
|
9324
|
-
return;
|
|
9325
|
-
} else if ((syx[5] & 32) > 0) {
|
|
9326
|
-
const channel = [
|
|
9327
|
-
9,
|
|
9328
|
-
0,
|
|
9329
|
-
1,
|
|
9330
|
-
2,
|
|
9331
|
-
3,
|
|
9332
|
-
4,
|
|
9333
|
-
5,
|
|
9334
|
-
6,
|
|
9335
|
-
7,
|
|
9336
|
-
8,
|
|
9337
|
-
10,
|
|
9338
|
-
11,
|
|
9339
|
-
12,
|
|
9340
|
-
13,
|
|
9341
|
-
14,
|
|
9342
|
-
15
|
|
9343
|
-
][syx[5] & 15] + channelOffset;
|
|
9344
|
-
const channelObject = this.midiChannels[channel];
|
|
9345
|
-
const centeredValue = messageValue - 64;
|
|
9346
|
-
const normalizedValue = centeredValue / 64;
|
|
9347
|
-
const normalizedNotCentered = messageValue / 128;
|
|
9348
|
-
const setupReceivers = (source, sourceName, bipolar = false) => {
|
|
9349
|
-
switch (syx[6] & 15) {
|
|
9350
|
-
case 0:
|
|
9351
|
-
if (source === NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel) {
|
|
9352
|
-
channelObject.controllerChange(
|
|
9353
|
-
midiControllers.registeredParameterMSB,
|
|
9354
|
-
0
|
|
9355
|
-
);
|
|
9356
|
-
channelObject.controllerChange(
|
|
9357
|
-
midiControllers.registeredParameterLSB,
|
|
9358
|
-
0
|
|
9359
|
-
);
|
|
9360
|
-
channelObject.controllerChange(
|
|
9361
|
-
midiControllers.dataEntryMSB,
|
|
9362
|
-
Math.floor(centeredValue)
|
|
9363
|
-
);
|
|
9364
|
-
} else {
|
|
9365
|
-
channelObject.sysExModulators.setModulator(
|
|
9366
|
-
source,
|
|
9367
|
-
generatorTypes.fineTune,
|
|
9368
|
-
centeredValue * 100,
|
|
9369
|
-
bipolar
|
|
9370
|
-
);
|
|
9371
|
-
niceLogging(
|
|
9372
|
-
channel,
|
|
9373
|
-
centeredValue,
|
|
9374
|
-
`${sourceName} pitch control`,
|
|
9375
|
-
"semitones"
|
|
9376
|
-
);
|
|
9377
|
-
}
|
|
9378
|
-
break;
|
|
9379
|
-
case 1:
|
|
9380
|
-
channelObject.sysExModulators.setModulator(
|
|
9381
|
-
source,
|
|
9382
|
-
generatorTypes.initialFilterFc,
|
|
9383
|
-
normalizedValue * 9600,
|
|
9384
|
-
bipolar
|
|
9385
|
-
);
|
|
9386
|
-
niceLogging(
|
|
9387
|
-
channel,
|
|
9388
|
-
normalizedValue * 9600,
|
|
9389
|
-
`${sourceName} pitch control`,
|
|
9390
|
-
"cents"
|
|
9391
|
-
);
|
|
9392
|
-
break;
|
|
9393
|
-
case 2:
|
|
9394
|
-
channelObject.sysExModulators.setModulator(
|
|
9395
|
-
source,
|
|
9396
|
-
generatorTypes.initialAttenuation,
|
|
9397
|
-
normalizedValue * 960,
|
|
9398
|
-
// Spec says "100%" so 960cB in sf2
|
|
9399
|
-
bipolar
|
|
9400
|
-
);
|
|
9401
|
-
niceLogging(
|
|
9402
|
-
channel,
|
|
9403
|
-
normalizedValue * 960,
|
|
9404
|
-
`${sourceName} amplitude`,
|
|
9405
|
-
"cB"
|
|
9406
|
-
);
|
|
9407
|
-
break;
|
|
9408
|
-
// Rate control is ignored as it is in hertz
|
|
9409
|
-
case 4:
|
|
9410
|
-
channelObject.sysExModulators.setModulator(
|
|
9411
|
-
source,
|
|
9412
|
-
generatorTypes.vibLfoToPitch,
|
|
9413
|
-
normalizedNotCentered * 600,
|
|
9414
|
-
bipolar
|
|
9415
|
-
);
|
|
9416
|
-
niceLogging(
|
|
9417
|
-
channel,
|
|
9418
|
-
normalizedNotCentered * 600,
|
|
9419
|
-
`${sourceName} LFO1 pitch depth`,
|
|
9420
|
-
"cents"
|
|
9421
|
-
);
|
|
9422
|
-
break;
|
|
9423
|
-
case 5:
|
|
9424
|
-
channelObject.sysExModulators.setModulator(
|
|
9425
|
-
source,
|
|
9426
|
-
generatorTypes.vibLfoToFilterFc,
|
|
9427
|
-
normalizedNotCentered * 2400,
|
|
9428
|
-
bipolar
|
|
9429
|
-
);
|
|
9430
|
-
niceLogging(
|
|
9431
|
-
channel,
|
|
9432
|
-
normalizedNotCentered * 2400,
|
|
9433
|
-
`${sourceName} LFO1 filter depth`,
|
|
9434
|
-
"cents"
|
|
9435
|
-
);
|
|
9436
|
-
break;
|
|
9437
|
-
case 6:
|
|
9438
|
-
channelObject.sysExModulators.setModulator(
|
|
9439
|
-
source,
|
|
9440
|
-
generatorTypes.vibLfoToVolume,
|
|
9441
|
-
normalizedValue * 960,
|
|
9442
|
-
bipolar
|
|
9443
|
-
);
|
|
9444
|
-
niceLogging(
|
|
9445
|
-
channel,
|
|
9446
|
-
normalizedValue * 960,
|
|
9447
|
-
`${sourceName} LFO1 amplitude depth`,
|
|
9448
|
-
"cB"
|
|
9449
|
-
);
|
|
9450
|
-
break;
|
|
9451
|
-
// Rate control is ignored as it is in hertz
|
|
9452
|
-
case 8:
|
|
9453
|
-
channelObject.sysExModulators.setModulator(
|
|
9454
|
-
source,
|
|
9455
|
-
generatorTypes.modLfoToPitch,
|
|
9456
|
-
normalizedNotCentered * 600,
|
|
9457
|
-
bipolar
|
|
9458
|
-
);
|
|
9459
|
-
niceLogging(
|
|
9460
|
-
channel,
|
|
9461
|
-
normalizedNotCentered * 600,
|
|
9462
|
-
`${sourceName} LFO2 pitch depth`,
|
|
9463
|
-
"cents"
|
|
9464
|
-
);
|
|
9465
|
-
break;
|
|
9466
|
-
case 9:
|
|
9467
|
-
channelObject.sysExModulators.setModulator(
|
|
9468
|
-
source,
|
|
9469
|
-
generatorTypes.modLfoToFilterFc,
|
|
9470
|
-
normalizedNotCentered * 2400,
|
|
9471
|
-
bipolar
|
|
9472
|
-
);
|
|
9473
|
-
niceLogging(
|
|
9474
|
-
channel,
|
|
9475
|
-
normalizedNotCentered * 2400,
|
|
9476
|
-
`${sourceName} LFO2 filter depth`,
|
|
9477
|
-
"cents"
|
|
9478
|
-
);
|
|
9479
|
-
break;
|
|
9480
|
-
case 10:
|
|
9481
|
-
channelObject.sysExModulators.setModulator(
|
|
9482
|
-
source,
|
|
9483
|
-
generatorTypes.modLfoToVolume,
|
|
9484
|
-
normalizedValue * 960,
|
|
9485
|
-
bipolar
|
|
9486
|
-
);
|
|
9487
|
-
niceLogging(
|
|
9488
|
-
channel,
|
|
9489
|
-
normalizedValue * 960,
|
|
9490
|
-
`${sourceName} LFO2 amplitude depth`,
|
|
9491
|
-
"cB"
|
|
9492
|
-
);
|
|
9493
|
-
break;
|
|
9494
|
-
}
|
|
9495
|
-
};
|
|
9496
|
-
switch (syx[6] & 240) {
|
|
9497
|
-
default:
|
|
9498
|
-
notRecognized2();
|
|
9499
|
-
break;
|
|
9500
|
-
case 0:
|
|
9501
|
-
setupReceivers(
|
|
9502
|
-
midiControllers.modulationWheel,
|
|
9503
|
-
"mod wheel"
|
|
9504
|
-
);
|
|
9505
|
-
break;
|
|
9506
|
-
case 16:
|
|
9507
|
-
setupReceivers(
|
|
9508
|
-
NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel,
|
|
9509
|
-
"pitch wheel",
|
|
9510
|
-
true
|
|
9511
|
-
);
|
|
9512
|
-
break;
|
|
9513
|
-
case 32:
|
|
9514
|
-
setupReceivers(
|
|
9515
|
-
NON_CC_INDEX_OFFSET + modulatorSources.channelPressure,
|
|
9516
|
-
"channel pressure"
|
|
9400
|
+
midiControllers.registeredParameterLSB,
|
|
9401
|
+
0
|
|
9517
9402
|
);
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
9521
|
-
NON_CC_INDEX_OFFSET + modulatorSources.polyPressure,
|
|
9522
|
-
"poly pressure"
|
|
9523
|
-
);
|
|
9524
|
-
break;
|
|
9525
|
-
}
|
|
9526
|
-
return;
|
|
9527
|
-
} else if (syx[5] === 0) {
|
|
9528
|
-
switch (syx[6]) {
|
|
9529
|
-
default:
|
|
9530
|
-
notRecognized2();
|
|
9531
|
-
break;
|
|
9532
|
-
case 127:
|
|
9533
|
-
if (messageValue === 0) {
|
|
9534
|
-
SpessaSynthInfo(
|
|
9535
|
-
"%cGS Reset received!",
|
|
9536
|
-
consoleColors.info
|
|
9537
|
-
);
|
|
9538
|
-
this.resetAllControllers(false);
|
|
9539
|
-
this.setMasterParameter(
|
|
9540
|
-
"midiSystem",
|
|
9541
|
-
"gs"
|
|
9542
|
-
);
|
|
9543
|
-
} else if (messageValue === 127) {
|
|
9544
|
-
SpessaSynthInfo(
|
|
9545
|
-
"%cGS system off, switching to GM",
|
|
9546
|
-
consoleColors.info
|
|
9547
|
-
);
|
|
9548
|
-
this.resetAllControllers(false);
|
|
9549
|
-
this.setMasterParameter(
|
|
9550
|
-
"midiSystem",
|
|
9551
|
-
"gm"
|
|
9552
|
-
);
|
|
9553
|
-
}
|
|
9554
|
-
break;
|
|
9555
|
-
case 6:
|
|
9556
|
-
SpessaSynthInfo(
|
|
9557
|
-
`%cRoland GS Master Pan set to: %c${messageValue}%c with: %c${arrayToHexString(
|
|
9558
|
-
syx
|
|
9559
|
-
)}`,
|
|
9560
|
-
consoleColors.info,
|
|
9561
|
-
consoleColors.value,
|
|
9562
|
-
consoleColors.info,
|
|
9563
|
-
consoleColors.value
|
|
9564
|
-
);
|
|
9565
|
-
this.setMasterParameter(
|
|
9566
|
-
"masterPan",
|
|
9567
|
-
(messageValue - 64) / 64
|
|
9568
|
-
);
|
|
9569
|
-
break;
|
|
9570
|
-
case 4:
|
|
9571
|
-
SpessaSynthInfo(
|
|
9572
|
-
`%cRoland GS Master Volume set to: %c${messageValue}%c with: %c${arrayToHexString(
|
|
9573
|
-
syx
|
|
9574
|
-
)}`,
|
|
9575
|
-
consoleColors.info,
|
|
9576
|
-
consoleColors.value,
|
|
9577
|
-
consoleColors.info,
|
|
9578
|
-
consoleColors.value
|
|
9403
|
+
channelObject.controllerChange(
|
|
9404
|
+
midiControllers.dataEntryMSB,
|
|
9405
|
+
Math.floor(centeredValue)
|
|
9579
9406
|
);
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
syx
|
|
9587
|
-
)}`,
|
|
9588
|
-
consoleColors.info,
|
|
9589
|
-
consoleColors.value,
|
|
9590
|
-
consoleColors.info,
|
|
9591
|
-
consoleColors.value
|
|
9407
|
+
} else {
|
|
9408
|
+
channelObject.sysExModulators.setModulator(
|
|
9409
|
+
source,
|
|
9410
|
+
generatorTypes.fineTune,
|
|
9411
|
+
centeredValue * 100,
|
|
9412
|
+
bipolar
|
|
9592
9413
|
);
|
|
9593
|
-
|
|
9594
|
-
break;
|
|
9595
|
-
}
|
|
9596
|
-
}
|
|
9597
|
-
return;
|
|
9598
|
-
} else if (syx[5] === 1) {
|
|
9599
|
-
switch (syx[6]) {
|
|
9600
|
-
default:
|
|
9601
|
-
notRecognized2();
|
|
9602
|
-
break;
|
|
9603
|
-
case 0: {
|
|
9604
|
-
const patchName = readBinaryString(
|
|
9414
|
+
sysExLogging(
|
|
9605
9415
|
syx,
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
`%cGS Patch name: %c${patchName}`,
|
|
9611
|
-
consoleColors.info,
|
|
9612
|
-
consoleColors.value
|
|
9416
|
+
channel,
|
|
9417
|
+
centeredValue,
|
|
9418
|
+
`${sourceName} pitch control`,
|
|
9419
|
+
"semitones"
|
|
9613
9420
|
);
|
|
9614
|
-
break;
|
|
9615
9421
|
}
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
|
|
9627
|
-
|
|
9628
|
-
|
|
9629
|
-
|
|
9630
|
-
|
|
9631
|
-
|
|
9632
|
-
|
|
9633
|
-
|
|
9634
|
-
|
|
9635
|
-
|
|
9636
|
-
|
|
9637
|
-
|
|
9638
|
-
|
|
9639
|
-
|
|
9640
|
-
|
|
9641
|
-
|
|
9642
|
-
|
|
9643
|
-
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
|
|
9649
|
-
|
|
9650
|
-
|
|
9651
|
-
|
|
9652
|
-
|
|
9653
|
-
|
|
9654
|
-
|
|
9655
|
-
|
|
9656
|
-
|
|
9657
|
-
|
|
9658
|
-
|
|
9659
|
-
|
|
9660
|
-
|
|
9422
|
+
break;
|
|
9423
|
+
case 1:
|
|
9424
|
+
channelObject.sysExModulators.setModulator(
|
|
9425
|
+
source,
|
|
9426
|
+
generatorTypes.initialFilterFc,
|
|
9427
|
+
normalizedValue * 9600,
|
|
9428
|
+
bipolar
|
|
9429
|
+
);
|
|
9430
|
+
sysExLogging(
|
|
9431
|
+
syx,
|
|
9432
|
+
channel,
|
|
9433
|
+
normalizedValue * 9600,
|
|
9434
|
+
`${sourceName} pitch control`,
|
|
9435
|
+
"cents"
|
|
9436
|
+
);
|
|
9437
|
+
break;
|
|
9438
|
+
case 2:
|
|
9439
|
+
channelObject.sysExModulators.setModulator(
|
|
9440
|
+
source,
|
|
9441
|
+
generatorTypes.initialAttenuation,
|
|
9442
|
+
normalizedValue * 960,
|
|
9443
|
+
// Spec says "100%" so 960cB in sf2
|
|
9444
|
+
bipolar
|
|
9445
|
+
);
|
|
9446
|
+
sysExLogging(
|
|
9447
|
+
syx,
|
|
9448
|
+
channel,
|
|
9449
|
+
normalizedValue * 960,
|
|
9450
|
+
`${sourceName} amplitude`,
|
|
9451
|
+
"cB"
|
|
9452
|
+
);
|
|
9453
|
+
break;
|
|
9454
|
+
// Rate control is ignored as it is in hertz
|
|
9455
|
+
case 4:
|
|
9456
|
+
channelObject.sysExModulators.setModulator(
|
|
9457
|
+
source,
|
|
9458
|
+
generatorTypes.vibLfoToPitch,
|
|
9459
|
+
normalizedNotCentered * 600,
|
|
9460
|
+
bipolar
|
|
9461
|
+
);
|
|
9462
|
+
sysExLogging(
|
|
9463
|
+
syx,
|
|
9464
|
+
channel,
|
|
9465
|
+
normalizedNotCentered * 600,
|
|
9466
|
+
`${sourceName} LFO1 pitch depth`,
|
|
9467
|
+
"cents"
|
|
9468
|
+
);
|
|
9469
|
+
break;
|
|
9470
|
+
case 5:
|
|
9471
|
+
channelObject.sysExModulators.setModulator(
|
|
9472
|
+
source,
|
|
9473
|
+
generatorTypes.vibLfoToFilterFc,
|
|
9474
|
+
normalizedNotCentered * 2400,
|
|
9475
|
+
bipolar
|
|
9476
|
+
);
|
|
9477
|
+
sysExLogging(
|
|
9478
|
+
syx,
|
|
9479
|
+
channel,
|
|
9480
|
+
normalizedNotCentered * 2400,
|
|
9481
|
+
`${sourceName} LFO1 filter depth`,
|
|
9482
|
+
"cents"
|
|
9483
|
+
);
|
|
9484
|
+
break;
|
|
9485
|
+
case 6:
|
|
9486
|
+
channelObject.sysExModulators.setModulator(
|
|
9487
|
+
source,
|
|
9488
|
+
generatorTypes.vibLfoToVolume,
|
|
9489
|
+
normalizedValue * 960,
|
|
9490
|
+
bipolar
|
|
9491
|
+
);
|
|
9492
|
+
sysExLogging(
|
|
9493
|
+
syx,
|
|
9494
|
+
channel,
|
|
9495
|
+
normalizedValue * 960,
|
|
9496
|
+
`${sourceName} LFO1 amplitude depth`,
|
|
9497
|
+
"cB"
|
|
9498
|
+
);
|
|
9499
|
+
break;
|
|
9500
|
+
// Rate control is ignored as it is in hertz
|
|
9501
|
+
case 8:
|
|
9502
|
+
channelObject.sysExModulators.setModulator(
|
|
9503
|
+
source,
|
|
9504
|
+
generatorTypes.modLfoToPitch,
|
|
9505
|
+
normalizedNotCentered * 600,
|
|
9506
|
+
bipolar
|
|
9507
|
+
);
|
|
9508
|
+
sysExLogging(
|
|
9509
|
+
syx,
|
|
9510
|
+
channel,
|
|
9511
|
+
normalizedNotCentered * 600,
|
|
9512
|
+
`${sourceName} LFO2 pitch depth`,
|
|
9513
|
+
"cents"
|
|
9514
|
+
);
|
|
9515
|
+
break;
|
|
9516
|
+
case 9:
|
|
9517
|
+
channelObject.sysExModulators.setModulator(
|
|
9518
|
+
source,
|
|
9519
|
+
generatorTypes.modLfoToFilterFc,
|
|
9520
|
+
normalizedNotCentered * 2400,
|
|
9521
|
+
bipolar
|
|
9522
|
+
);
|
|
9523
|
+
sysExLogging(
|
|
9524
|
+
syx,
|
|
9525
|
+
channel,
|
|
9526
|
+
normalizedNotCentered * 2400,
|
|
9527
|
+
`${sourceName} LFO2 filter depth`,
|
|
9528
|
+
"cents"
|
|
9529
|
+
);
|
|
9530
|
+
break;
|
|
9531
|
+
case 10:
|
|
9532
|
+
channelObject.sysExModulators.setModulator(
|
|
9533
|
+
source,
|
|
9534
|
+
generatorTypes.modLfoToVolume,
|
|
9535
|
+
normalizedValue * 960,
|
|
9536
|
+
bipolar
|
|
9537
|
+
);
|
|
9538
|
+
sysExLogging(
|
|
9539
|
+
syx,
|
|
9540
|
+
channel,
|
|
9541
|
+
normalizedValue * 960,
|
|
9542
|
+
`${sourceName} LFO2 amplitude depth`,
|
|
9543
|
+
"cB"
|
|
9544
|
+
);
|
|
9545
|
+
break;
|
|
9661
9546
|
}
|
|
9662
|
-
}
|
|
9663
|
-
|
|
9547
|
+
};
|
|
9548
|
+
switch (syx[6] & 240) {
|
|
9549
|
+
default:
|
|
9550
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9551
|
+
break;
|
|
9552
|
+
case 0:
|
|
9553
|
+
setupReceivers(
|
|
9554
|
+
midiControllers.modulationWheel,
|
|
9555
|
+
"mod wheel"
|
|
9556
|
+
);
|
|
9557
|
+
break;
|
|
9558
|
+
case 16:
|
|
9559
|
+
setupReceivers(
|
|
9560
|
+
NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel,
|
|
9561
|
+
"pitch wheel",
|
|
9562
|
+
true
|
|
9563
|
+
);
|
|
9564
|
+
break;
|
|
9565
|
+
case 32:
|
|
9566
|
+
setupReceivers(
|
|
9567
|
+
NON_CC_INDEX_OFFSET + modulatorSources.channelPressure,
|
|
9568
|
+
"channel pressure"
|
|
9569
|
+
);
|
|
9570
|
+
break;
|
|
9571
|
+
case 48:
|
|
9572
|
+
setupReceivers(
|
|
9573
|
+
NON_CC_INDEX_OFFSET + modulatorSources.polyPressure,
|
|
9574
|
+
"poly pressure"
|
|
9575
|
+
);
|
|
9576
|
+
break;
|
|
9664
9577
|
}
|
|
9665
9578
|
return;
|
|
9666
|
-
}
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9579
|
+
} else if (syx[5] === 0) {
|
|
9580
|
+
switch (syx[6]) {
|
|
9581
|
+
default:
|
|
9582
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9583
|
+
break;
|
|
9584
|
+
case 127:
|
|
9585
|
+
if (messageValue === 0) {
|
|
9586
|
+
SpessaSynthInfo(
|
|
9587
|
+
"%cGS Reset received!",
|
|
9588
|
+
consoleColors.info
|
|
9589
|
+
);
|
|
9590
|
+
this.resetAllControllers("gs");
|
|
9591
|
+
} else if (messageValue === 127) {
|
|
9592
|
+
SpessaSynthInfo(
|
|
9593
|
+
"%cGS system off, switching to GM",
|
|
9594
|
+
consoleColors.info
|
|
9595
|
+
);
|
|
9596
|
+
this.resetAllControllers("gm");
|
|
9597
|
+
}
|
|
9598
|
+
break;
|
|
9599
|
+
case 6:
|
|
9600
|
+
SpessaSynthInfo(
|
|
9601
|
+
`%cRoland GS Master Pan set to: %c${messageValue}%c with: %c${arrayToHexString(
|
|
9602
|
+
syx
|
|
9603
|
+
)}`,
|
|
9604
|
+
consoleColors.info,
|
|
9605
|
+
consoleColors.value,
|
|
9606
|
+
consoleColors.info,
|
|
9607
|
+
consoleColors.value
|
|
9608
|
+
);
|
|
9609
|
+
this.setMasterParameter(
|
|
9610
|
+
"masterPan",
|
|
9611
|
+
(messageValue - 64) / 64
|
|
9612
|
+
);
|
|
9613
|
+
break;
|
|
9614
|
+
case 4:
|
|
9615
|
+
SpessaSynthInfo(
|
|
9616
|
+
`%cRoland GS Master Volume set to: %c${messageValue}%c with: %c${arrayToHexString(
|
|
9617
|
+
syx
|
|
9618
|
+
)}`,
|
|
9619
|
+
consoleColors.info,
|
|
9620
|
+
consoleColors.value,
|
|
9621
|
+
consoleColors.info,
|
|
9622
|
+
consoleColors.value
|
|
9673
9623
|
);
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9624
|
+
this.setMIDIVolume(messageValue / 127);
|
|
9625
|
+
break;
|
|
9626
|
+
case 5: {
|
|
9627
|
+
const transpose = messageValue - 64;
|
|
9628
|
+
SpessaSynthInfo(
|
|
9629
|
+
`%cRoland GS Master Key-Shift set to: %c${transpose}%c with: %c${arrayToHexString(
|
|
9630
|
+
syx
|
|
9631
|
+
)}`,
|
|
9632
|
+
consoleColors.info,
|
|
9633
|
+
consoleColors.value,
|
|
9634
|
+
consoleColors.info,
|
|
9635
|
+
consoleColors.value
|
|
9678
9636
|
);
|
|
9679
|
-
|
|
9680
|
-
|
|
9637
|
+
this.setMasterTuning(transpose * 100);
|
|
9638
|
+
break;
|
|
9681
9639
|
}
|
|
9682
9640
|
}
|
|
9683
9641
|
return;
|
|
9684
|
-
}
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
return;
|
|
9698
|
-
}
|
|
9699
|
-
}
|
|
9700
|
-
} else {
|
|
9701
|
-
SpessaSynthInfo(
|
|
9702
|
-
`%cUnrecognized Roland SysEx: %c${arrayToHexString(syx)}`,
|
|
9703
|
-
consoleColors.warn,
|
|
9704
|
-
consoleColors.unrecognized
|
|
9705
|
-
);
|
|
9706
|
-
return;
|
|
9707
|
-
}
|
|
9708
|
-
break;
|
|
9709
|
-
// Yamaha
|
|
9710
|
-
// http://www.studio4all.de/htmle/main91.html
|
|
9711
|
-
case 67:
|
|
9712
|
-
if (syx[2] === 76) {
|
|
9713
|
-
if (syx[3] === 0 && syx[4] === 0) {
|
|
9714
|
-
switch (syx[5]) {
|
|
9715
|
-
// Master volume
|
|
9716
|
-
case 4: {
|
|
9717
|
-
const vol = syx[6];
|
|
9718
|
-
this.setMIDIVolume(vol / 127);
|
|
9719
|
-
SpessaSynthInfo(
|
|
9720
|
-
`%cXG master volume. Volume: %c${vol}`,
|
|
9721
|
-
consoleColors.info,
|
|
9722
|
-
consoleColors.recognized
|
|
9723
|
-
);
|
|
9724
|
-
break;
|
|
9725
|
-
}
|
|
9726
|
-
// Master transpose
|
|
9727
|
-
case 6: {
|
|
9728
|
-
const transpose = syx[6] - 64;
|
|
9729
|
-
this.setMasterParameter("transposition", transpose);
|
|
9730
|
-
SpessaSynthInfo(
|
|
9731
|
-
`%cXG master transpose. Volume: %c${transpose}`,
|
|
9732
|
-
consoleColors.info,
|
|
9733
|
-
consoleColors.recognized
|
|
9734
|
-
);
|
|
9735
|
-
break;
|
|
9736
|
-
}
|
|
9737
|
-
// XG on
|
|
9738
|
-
case 126:
|
|
9739
|
-
SpessaSynthInfo(
|
|
9740
|
-
"%cXG system on",
|
|
9741
|
-
consoleColors.info
|
|
9742
|
-
);
|
|
9743
|
-
this.resetAllControllers(false);
|
|
9744
|
-
this.setMasterParameter("midiSystem", "xg");
|
|
9745
|
-
break;
|
|
9746
|
-
}
|
|
9747
|
-
} else if (syx[3] === 8) {
|
|
9748
|
-
if (!BankSelectHacks.isSystemXG(
|
|
9749
|
-
this.privateProps.masterParameters.midiSystem
|
|
9750
|
-
)) {
|
|
9751
|
-
return;
|
|
9752
|
-
}
|
|
9753
|
-
const channel = syx[4] + channelOffset;
|
|
9754
|
-
if (channel >= this.midiChannels.length) {
|
|
9755
|
-
return;
|
|
9756
|
-
}
|
|
9757
|
-
const channelObject = this.midiChannels[channel];
|
|
9758
|
-
const value = syx[6];
|
|
9759
|
-
switch (syx[5]) {
|
|
9760
|
-
// Bank-select MSB
|
|
9761
|
-
case 1:
|
|
9762
|
-
channelObject.controllerChange(
|
|
9763
|
-
midiControllers.bankSelect,
|
|
9764
|
-
value
|
|
9765
|
-
);
|
|
9766
|
-
break;
|
|
9767
|
-
// Bank-select LSB
|
|
9768
|
-
case 2:
|
|
9769
|
-
channelObject.controllerChange(
|
|
9770
|
-
midiControllers.bankSelectLSB,
|
|
9771
|
-
value
|
|
9772
|
-
);
|
|
9773
|
-
break;
|
|
9774
|
-
// Program change
|
|
9775
|
-
case 3:
|
|
9776
|
-
channelObject.programChange(value);
|
|
9777
|
-
break;
|
|
9778
|
-
// Note shift
|
|
9779
|
-
case 8: {
|
|
9780
|
-
if (channelObject.drumChannel) {
|
|
9781
|
-
return;
|
|
9642
|
+
} else if (syx[5] === 1) {
|
|
9643
|
+
switch (syx[6]) {
|
|
9644
|
+
default:
|
|
9645
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9646
|
+
break;
|
|
9647
|
+
case 0: {
|
|
9648
|
+
const patchName = readBinaryString(syx, 16, 7);
|
|
9649
|
+
SpessaSynthInfo(
|
|
9650
|
+
`%cGS Patch name: %c${patchName}`,
|
|
9651
|
+
consoleColors.info,
|
|
9652
|
+
consoleColors.value
|
|
9653
|
+
);
|
|
9654
|
+
break;
|
|
9782
9655
|
}
|
|
9783
|
-
|
|
9784
|
-
break;
|
|
9785
|
-
}
|
|
9786
|
-
// Volume
|
|
9787
|
-
case 11:
|
|
9788
|
-
channelObject.controllerChange(
|
|
9789
|
-
midiControllers.mainVolume,
|
|
9790
|
-
value
|
|
9791
|
-
);
|
|
9792
|
-
break;
|
|
9793
|
-
// Pan position
|
|
9794
|
-
case 14: {
|
|
9795
|
-
const pan = value;
|
|
9796
|
-
if (pan === 0) {
|
|
9797
|
-
channelObject.randomPan = true;
|
|
9656
|
+
case 51:
|
|
9798
9657
|
SpessaSynthInfo(
|
|
9799
|
-
`%
|
|
9658
|
+
`%cGS Reverb level: %c${messageValue}`,
|
|
9800
9659
|
consoleColors.info,
|
|
9801
|
-
consoleColors.
|
|
9660
|
+
consoleColors.value
|
|
9661
|
+
);
|
|
9662
|
+
this.privateProps.reverbSend = messageValue / 64;
|
|
9663
|
+
break;
|
|
9664
|
+
// Unsupported reverb params
|
|
9665
|
+
case 48:
|
|
9666
|
+
case 49:
|
|
9667
|
+
case 50:
|
|
9668
|
+
case 52:
|
|
9669
|
+
case 53:
|
|
9670
|
+
case 55:
|
|
9671
|
+
SpessaSynthInfo(
|
|
9672
|
+
`%cUnsupported GS Reverb Parameter: %c${syx[6].toString(16)}`,
|
|
9673
|
+
consoleColors.warn,
|
|
9674
|
+
consoleColors.unrecognized
|
|
9675
|
+
);
|
|
9676
|
+
break;
|
|
9677
|
+
case 58:
|
|
9678
|
+
SpessaSynthInfo(
|
|
9679
|
+
`%cGS Chorus level: %c${messageValue}`,
|
|
9802
9680
|
consoleColors.info,
|
|
9803
9681
|
consoleColors.value
|
|
9804
9682
|
);
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9683
|
+
this.privateProps.chorusSend = messageValue / 64;
|
|
9684
|
+
break;
|
|
9685
|
+
// Unsupported chorus params
|
|
9686
|
+
case 56:
|
|
9687
|
+
case 57:
|
|
9688
|
+
case 59:
|
|
9689
|
+
case 60:
|
|
9690
|
+
case 61:
|
|
9691
|
+
case 62:
|
|
9692
|
+
case 63:
|
|
9693
|
+
case 64:
|
|
9694
|
+
SpessaSynthInfo(
|
|
9695
|
+
`%cUnsupported GS Chorus Parameter: %c${syx[6].toString(16)}`,
|
|
9696
|
+
consoleColors.warn,
|
|
9697
|
+
consoleColors.unrecognized
|
|
9809
9698
|
);
|
|
9810
|
-
|
|
9811
|
-
break;
|
|
9699
|
+
break;
|
|
9812
9700
|
}
|
|
9813
|
-
// Reverb
|
|
9814
|
-
case 19:
|
|
9815
|
-
channelObject.controllerChange(
|
|
9816
|
-
midiControllers.reverbDepth,
|
|
9817
|
-
value
|
|
9818
|
-
);
|
|
9819
|
-
break;
|
|
9820
|
-
// Chorus
|
|
9821
|
-
case 18:
|
|
9822
|
-
channelObject.controllerChange(
|
|
9823
|
-
midiControllers.chorusDepth,
|
|
9824
|
-
value
|
|
9825
|
-
);
|
|
9826
|
-
break;
|
|
9827
|
-
default:
|
|
9828
|
-
SpessaSynthInfo(
|
|
9829
|
-
`%cUnrecognized Yamaha XG Part Setup: %c${syx[5].toString(16).toUpperCase()}`,
|
|
9830
|
-
consoleColors.warn,
|
|
9831
|
-
consoleColors.unrecognized
|
|
9832
|
-
);
|
|
9833
9701
|
}
|
|
9834
|
-
} else
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9702
|
+
} else {
|
|
9703
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9704
|
+
}
|
|
9705
|
+
return;
|
|
9706
|
+
}
|
|
9707
|
+
case 69: {
|
|
9708
|
+
if (syx[4] === 16) {
|
|
9709
|
+
if (syx[5] === 0) {
|
|
9710
|
+
this.privateProps.callEvent(
|
|
9711
|
+
"synthDisplay",
|
|
9712
|
+
Array.from(syx)
|
|
9713
|
+
);
|
|
9714
|
+
} else if (syx[5] === 1) {
|
|
9715
|
+
this.privateProps.callEvent(
|
|
9716
|
+
"synthDisplay",
|
|
9717
|
+
Array.from(syx)
|
|
9718
|
+
);
|
|
9719
|
+
} else {
|
|
9720
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9721
|
+
}
|
|
9722
|
+
}
|
|
9723
|
+
return;
|
|
9724
|
+
}
|
|
9725
|
+
case 22:
|
|
9726
|
+
if (syx[4] === 16) {
|
|
9727
|
+
this.setMIDIVolume(syx[7] / 100);
|
|
9728
|
+
SpessaSynthInfo(
|
|
9729
|
+
`%cRoland Master Volume control set to: %c${syx[7]}%c via: %c${arrayToHexString(
|
|
9730
|
+
syx
|
|
9731
|
+
)}`,
|
|
9732
|
+
consoleColors.info,
|
|
9733
|
+
consoleColors.value,
|
|
9734
|
+
consoleColors.info,
|
|
9735
|
+
consoleColors.value
|
|
9839
9736
|
);
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9737
|
+
return;
|
|
9738
|
+
}
|
|
9739
|
+
}
|
|
9740
|
+
} else {
|
|
9741
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9742
|
+
return;
|
|
9743
|
+
}
|
|
9744
|
+
}
|
|
9745
|
+
|
|
9746
|
+
// src/synthesizer/audio_engine/engine_methods/system_exclusive/handle_xg.ts
|
|
9747
|
+
function handleXG(syx, channelOffset = 0) {
|
|
9748
|
+
if (syx[2] === 76) {
|
|
9749
|
+
const a1 = syx[3];
|
|
9750
|
+
const a2 = syx[4];
|
|
9751
|
+
if (a1 === 0 && a2 === 0) {
|
|
9752
|
+
switch (syx[5]) {
|
|
9753
|
+
// Master tune
|
|
9754
|
+
case 0:
|
|
9755
|
+
{
|
|
9756
|
+
const tune = (syx[6] & 15) << 12 | (syx[7] & 15) << 8 | (syx[8] & 15) << 4 | syx[9] & 15;
|
|
9757
|
+
const cents = (tune - 1024) / 10;
|
|
9758
|
+
this.setMasterTuning(cents);
|
|
9759
|
+
SpessaSynthInfo(
|
|
9760
|
+
`%cXG master tune. Cents: %c${cents}`,
|
|
9761
|
+
consoleColors.info,
|
|
9762
|
+
consoleColors.recognized
|
|
9763
|
+
);
|
|
9764
|
+
}
|
|
9765
|
+
break;
|
|
9766
|
+
// Master volume
|
|
9767
|
+
case 4: {
|
|
9768
|
+
const vol = syx[6];
|
|
9769
|
+
this.setMIDIVolume(vol / 127);
|
|
9843
9770
|
SpessaSynthInfo(
|
|
9844
|
-
`%
|
|
9845
|
-
consoleColors.
|
|
9846
|
-
consoleColors.
|
|
9771
|
+
`%cXG master volume. Volume: %c${vol}`,
|
|
9772
|
+
consoleColors.info,
|
|
9773
|
+
consoleColors.recognized
|
|
9847
9774
|
);
|
|
9775
|
+
break;
|
|
9848
9776
|
}
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9777
|
+
// Master attenuation
|
|
9778
|
+
case 5: {
|
|
9779
|
+
const vol = 127 - syx[6];
|
|
9780
|
+
this.setMIDIVolume(vol / 127);
|
|
9853
9781
|
SpessaSynthInfo(
|
|
9854
|
-
`%
|
|
9855
|
-
consoleColors.
|
|
9856
|
-
consoleColors.
|
|
9782
|
+
`%cXG master attenuation. Volume: %c${vol}`,
|
|
9783
|
+
consoleColors.info,
|
|
9784
|
+
consoleColors.recognized
|
|
9785
|
+
);
|
|
9786
|
+
break;
|
|
9787
|
+
}
|
|
9788
|
+
// Master transpose
|
|
9789
|
+
case 6: {
|
|
9790
|
+
const transpose = syx[6] - 64;
|
|
9791
|
+
this.setMasterParameter("transposition", transpose);
|
|
9792
|
+
SpessaSynthInfo(
|
|
9793
|
+
`%cXG master transpose. Volume: %c${transpose}`,
|
|
9794
|
+
consoleColors.info,
|
|
9795
|
+
consoleColors.recognized
|
|
9796
|
+
);
|
|
9797
|
+
break;
|
|
9798
|
+
}
|
|
9799
|
+
//
|
|
9800
|
+
// XG on
|
|
9801
|
+
case 126:
|
|
9802
|
+
SpessaSynthInfo("%cXG system on", consoleColors.info);
|
|
9803
|
+
this.resetAllControllers("xg");
|
|
9804
|
+
break;
|
|
9805
|
+
}
|
|
9806
|
+
} else if (a1 === 2 && a2 === 1) {
|
|
9807
|
+
let effectType;
|
|
9808
|
+
const effect = syx[5];
|
|
9809
|
+
if (effect <= 21) effectType = "Reverb";
|
|
9810
|
+
else if (effect <= 35) effectType = "Chorus";
|
|
9811
|
+
else effectType = "Variation";
|
|
9812
|
+
SpessaSynthInfo(
|
|
9813
|
+
`%cUnsupported XG ${effectType} Parameter: %c${effect.toString(16)}`,
|
|
9814
|
+
consoleColors.warn,
|
|
9815
|
+
consoleColors.unrecognized
|
|
9816
|
+
);
|
|
9817
|
+
} else if (a1 === 8) {
|
|
9818
|
+
if (!BankSelectHacks.isSystemXG(
|
|
9819
|
+
this.privateProps.masterParameters.midiSystem
|
|
9820
|
+
)) {
|
|
9821
|
+
return;
|
|
9822
|
+
}
|
|
9823
|
+
const channel = a2 + channelOffset;
|
|
9824
|
+
if (channel >= this.midiChannels.length) {
|
|
9825
|
+
return;
|
|
9826
|
+
}
|
|
9827
|
+
const channelObject = this.midiChannels[channel];
|
|
9828
|
+
const value = syx[6];
|
|
9829
|
+
switch (syx[5]) {
|
|
9830
|
+
// Bank-select MSB
|
|
9831
|
+
case 1:
|
|
9832
|
+
channelObject.controllerChange(
|
|
9833
|
+
midiControllers.bankSelect,
|
|
9834
|
+
value
|
|
9835
|
+
);
|
|
9836
|
+
break;
|
|
9837
|
+
// Bank-select LSB
|
|
9838
|
+
case 2:
|
|
9839
|
+
channelObject.controllerChange(
|
|
9840
|
+
midiControllers.bankSelectLSB,
|
|
9841
|
+
value
|
|
9842
|
+
);
|
|
9843
|
+
break;
|
|
9844
|
+
// Program change
|
|
9845
|
+
case 3:
|
|
9846
|
+
channelObject.programChange(value);
|
|
9847
|
+
break;
|
|
9848
|
+
// Part mode
|
|
9849
|
+
case 7:
|
|
9850
|
+
channelObject.setDrums(value != 0);
|
|
9851
|
+
break;
|
|
9852
|
+
// Note shift
|
|
9853
|
+
case 8: {
|
|
9854
|
+
if (channelObject.drumChannel) {
|
|
9855
|
+
break;
|
|
9856
|
+
}
|
|
9857
|
+
channelObject.setCustomController(
|
|
9858
|
+
customControllers.channelKeyShift,
|
|
9859
|
+
value - 64
|
|
9860
|
+
);
|
|
9861
|
+
break;
|
|
9862
|
+
}
|
|
9863
|
+
// Volume
|
|
9864
|
+
case 11:
|
|
9865
|
+
channelObject.controllerChange(
|
|
9866
|
+
midiControllers.mainVolume,
|
|
9867
|
+
value
|
|
9857
9868
|
);
|
|
9869
|
+
break;
|
|
9870
|
+
// Pan position
|
|
9871
|
+
case 14: {
|
|
9872
|
+
const pan = value;
|
|
9873
|
+
if (pan === 0) {
|
|
9874
|
+
channelObject.randomPan = true;
|
|
9875
|
+
SpessaSynthInfo(
|
|
9876
|
+
`%cRandom pan is set to %cON%c for %c${channel}`,
|
|
9877
|
+
consoleColors.info,
|
|
9878
|
+
consoleColors.recognized,
|
|
9879
|
+
consoleColors.info,
|
|
9880
|
+
consoleColors.value
|
|
9881
|
+
);
|
|
9882
|
+
} else {
|
|
9883
|
+
channelObject.controllerChange(
|
|
9884
|
+
midiControllers.pan,
|
|
9885
|
+
pan
|
|
9886
|
+
);
|
|
9887
|
+
}
|
|
9888
|
+
break;
|
|
9858
9889
|
}
|
|
9890
|
+
// Dry
|
|
9891
|
+
case 17:
|
|
9892
|
+
channelObject.controllerChange(
|
|
9893
|
+
midiControllers.mainVolume,
|
|
9894
|
+
value
|
|
9895
|
+
);
|
|
9896
|
+
break;
|
|
9897
|
+
// Chorus
|
|
9898
|
+
case 18:
|
|
9899
|
+
channelObject.controllerChange(
|
|
9900
|
+
midiControllers.chorusDepth,
|
|
9901
|
+
value
|
|
9902
|
+
);
|
|
9903
|
+
break;
|
|
9904
|
+
// Reverb
|
|
9905
|
+
case 19:
|
|
9906
|
+
channelObject.controllerChange(
|
|
9907
|
+
midiControllers.reverbDepth,
|
|
9908
|
+
value
|
|
9909
|
+
);
|
|
9910
|
+
break;
|
|
9911
|
+
// Vibrato rate
|
|
9912
|
+
case 21:
|
|
9913
|
+
channelObject.controllerChange(
|
|
9914
|
+
midiControllers.vibratoRate,
|
|
9915
|
+
value
|
|
9916
|
+
);
|
|
9917
|
+
break;
|
|
9918
|
+
// Vibrato depth
|
|
9919
|
+
case 22:
|
|
9920
|
+
channelObject.controllerChange(
|
|
9921
|
+
midiControllers.vibratoDepth,
|
|
9922
|
+
value
|
|
9923
|
+
);
|
|
9924
|
+
break;
|
|
9925
|
+
// Vibrato delay
|
|
9926
|
+
case 23:
|
|
9927
|
+
channelObject.controllerChange(
|
|
9928
|
+
midiControllers.vibratoDelay,
|
|
9929
|
+
value
|
|
9930
|
+
);
|
|
9931
|
+
break;
|
|
9932
|
+
// Filter cutoff
|
|
9933
|
+
case 24:
|
|
9934
|
+
channelObject.controllerChange(
|
|
9935
|
+
midiControllers.brightness,
|
|
9936
|
+
value
|
|
9937
|
+
);
|
|
9938
|
+
break;
|
|
9939
|
+
// Filter resonance
|
|
9940
|
+
case 25:
|
|
9941
|
+
channelObject.controllerChange(
|
|
9942
|
+
midiControllers.filterResonance,
|
|
9943
|
+
value
|
|
9944
|
+
);
|
|
9945
|
+
break;
|
|
9946
|
+
// Attack time
|
|
9947
|
+
case 26:
|
|
9948
|
+
channelObject.controllerChange(
|
|
9949
|
+
midiControllers.attackTime,
|
|
9950
|
+
value
|
|
9951
|
+
);
|
|
9952
|
+
break;
|
|
9953
|
+
// Decay time
|
|
9954
|
+
case 27:
|
|
9955
|
+
channelObject.controllerChange(
|
|
9956
|
+
midiControllers.decayTime,
|
|
9957
|
+
value
|
|
9958
|
+
);
|
|
9959
|
+
break;
|
|
9960
|
+
// Release time
|
|
9961
|
+
case 28:
|
|
9962
|
+
channelObject.controllerChange(
|
|
9963
|
+
midiControllers.releaseTime,
|
|
9964
|
+
value
|
|
9965
|
+
);
|
|
9966
|
+
break;
|
|
9967
|
+
default:
|
|
9968
|
+
SpessaSynthInfo(
|
|
9969
|
+
`%cUnsupported Yamaha XG Part Setup: %c${syx[5].toString(16).toUpperCase()}%c for channel ${channel}`,
|
|
9970
|
+
consoleColors.warn,
|
|
9971
|
+
consoleColors.unrecognized,
|
|
9972
|
+
consoleColors.warn
|
|
9973
|
+
);
|
|
9859
9974
|
}
|
|
9975
|
+
} else if (a1 === 6 && // XG System parameter
|
|
9976
|
+
a2 === 0) {
|
|
9977
|
+
this.privateProps.callEvent("synthDisplay", Array.from(syx));
|
|
9978
|
+
} else if (BankSelectHacks.isSystemXG(
|
|
9979
|
+
this.privateProps.masterParameters.midiSystem
|
|
9980
|
+
)) {
|
|
9981
|
+
sysExNotRecognized(syx, "Yamaha XG");
|
|
9982
|
+
}
|
|
9983
|
+
} else {
|
|
9984
|
+
sysExNotRecognized(syx, "Yamaha");
|
|
9985
|
+
}
|
|
9986
|
+
}
|
|
9987
|
+
|
|
9988
|
+
// src/synthesizer/audio_engine/engine_methods/system_exclusive.ts
|
|
9989
|
+
function systemExclusiveInternal(syx, channelOffset = 0) {
|
|
9990
|
+
const manufacturer = syx[0];
|
|
9991
|
+
if (
|
|
9992
|
+
// The device ID can be set to "all" which it is by default
|
|
9993
|
+
this.privateProps.masterParameters.deviceID !== ALL_CHANNELS_OR_DIFFERENT_ACTION && syx[1] !== 127
|
|
9994
|
+
) {
|
|
9995
|
+
if (this.privateProps.masterParameters.deviceID !== syx[1]) {
|
|
9996
|
+
return;
|
|
9997
|
+
}
|
|
9998
|
+
}
|
|
9999
|
+
switch (manufacturer) {
|
|
10000
|
+
default:
|
|
10001
|
+
SpessaSynthInfo(
|
|
10002
|
+
`%cUnrecognized SysEx: %c${arrayToHexString(syx)} (unknown manufacturer)`,
|
|
10003
|
+
consoleColors.warn,
|
|
10004
|
+
consoleColors.unrecognized
|
|
10005
|
+
);
|
|
10006
|
+
break;
|
|
10007
|
+
// Non realtime GM
|
|
10008
|
+
case 126:
|
|
10009
|
+
// Realtime GM
|
|
10010
|
+
case 127:
|
|
10011
|
+
handleGM.call(this, syx, channelOffset);
|
|
10012
|
+
break;
|
|
10013
|
+
// Roland
|
|
10014
|
+
case 65:
|
|
10015
|
+
handleGS.call(this, syx, channelOffset);
|
|
10016
|
+
break;
|
|
10017
|
+
// Yamaha
|
|
10018
|
+
case 67:
|
|
10019
|
+
handleXG.call(this, syx, channelOffset);
|
|
9860
10020
|
break;
|
|
9861
10021
|
}
|
|
9862
10022
|
}
|
|
@@ -10250,8 +10410,7 @@ var ProtectedSynthValues = class {
|
|
|
10250
10410
|
voiceKilling;
|
|
10251
10411
|
/**
|
|
10252
10412
|
* Cached voices for all presets for this synthesizer.
|
|
10253
|
-
* Nesting
|
|
10254
|
-
* this.cachedVoices[bankMSB][bankLSB][programNumber][midiNote][velocity] = a list of voices for that.
|
|
10413
|
+
* Nesting is calculated in getCachedVoiceIndex, returns a list of voices for this note.
|
|
10255
10414
|
*/
|
|
10256
10415
|
cachedVoices = [];
|
|
10257
10416
|
constructor(eventCallbackHandler, getVoices, voiceKillingFunction, volumeEnvelopeSmoothingFactor, panSmoothingFactor, filterSmoothingFactor) {
|
|
@@ -10605,13 +10764,14 @@ var nonRegisteredMSB = {
|
|
|
10605
10764
|
awe32: 127,
|
|
10606
10765
|
SF2: 120
|
|
10607
10766
|
};
|
|
10608
|
-
var
|
|
10767
|
+
var nonRegisteredLSB = {
|
|
10609
10768
|
vibratoRate: 8,
|
|
10610
10769
|
vibratoDepth: 9,
|
|
10611
10770
|
vibratoDelay: 10,
|
|
10612
10771
|
TVFFilterCutoff: 32,
|
|
10613
10772
|
TVFFilterResonance: 33,
|
|
10614
10773
|
EGAttackTime: 99,
|
|
10774
|
+
EGDecayTime: 100,
|
|
10615
10775
|
EGReleaseTime: 102
|
|
10616
10776
|
};
|
|
10617
10777
|
function dataEntryCoarse(dataValue) {
|
|
@@ -10640,7 +10800,7 @@ function dataEntryCoarse(dataValue) {
|
|
|
10640
10800
|
default:
|
|
10641
10801
|
case dataEntryStates.Idle:
|
|
10642
10802
|
break;
|
|
10643
|
-
// Process
|
|
10803
|
+
// Process NRPNs
|
|
10644
10804
|
case dataEntryStates.NRPFine: {
|
|
10645
10805
|
if (this.lockGSNRPNParams) {
|
|
10646
10806
|
return;
|
|
@@ -10667,7 +10827,7 @@ function dataEntryCoarse(dataValue) {
|
|
|
10667
10827
|
consoleColors.value
|
|
10668
10828
|
);
|
|
10669
10829
|
break;
|
|
10670
|
-
// Part parameters
|
|
10830
|
+
// Part parameters
|
|
10671
10831
|
case nonRegisteredMSB.partParameter:
|
|
10672
10832
|
switch (NRPNFine) {
|
|
10673
10833
|
default:
|
|
@@ -10686,8 +10846,8 @@ function dataEntryCoarse(dataValue) {
|
|
|
10686
10846
|
consoleColors.value
|
|
10687
10847
|
);
|
|
10688
10848
|
break;
|
|
10689
|
-
// Vibrato rate
|
|
10690
|
-
case
|
|
10849
|
+
// Vibrato rate (custom vibrato)
|
|
10850
|
+
case nonRegisteredLSB.vibratoRate:
|
|
10691
10851
|
if (dataValue === 64) {
|
|
10692
10852
|
return;
|
|
10693
10853
|
}
|
|
@@ -10699,8 +10859,8 @@ function dataEntryCoarse(dataValue) {
|
|
|
10699
10859
|
"Hz"
|
|
10700
10860
|
);
|
|
10701
10861
|
break;
|
|
10702
|
-
// Vibrato depth
|
|
10703
|
-
case
|
|
10862
|
+
// Vibrato depth (custom vibrato)
|
|
10863
|
+
case nonRegisteredLSB.vibratoDepth:
|
|
10704
10864
|
if (dataValue === 64) {
|
|
10705
10865
|
return;
|
|
10706
10866
|
}
|
|
@@ -10712,8 +10872,8 @@ function dataEntryCoarse(dataValue) {
|
|
|
10712
10872
|
"cents of detune"
|
|
10713
10873
|
);
|
|
10714
10874
|
break;
|
|
10715
|
-
// Vibrato delay
|
|
10716
|
-
case
|
|
10875
|
+
// Vibrato delay (custom vibrato)
|
|
10876
|
+
case nonRegisteredLSB.vibratoDelay:
|
|
10717
10877
|
if (dataValue === 64) {
|
|
10718
10878
|
return;
|
|
10719
10879
|
}
|
|
@@ -10726,15 +10886,26 @@ function dataEntryCoarse(dataValue) {
|
|
|
10726
10886
|
);
|
|
10727
10887
|
break;
|
|
10728
10888
|
// Filter cutoff
|
|
10729
|
-
case
|
|
10889
|
+
case nonRegisteredLSB.TVFFilterCutoff:
|
|
10730
10890
|
this.controllerChange(
|
|
10731
10891
|
midiControllers.brightness,
|
|
10732
10892
|
dataValue
|
|
10733
10893
|
);
|
|
10734
10894
|
coolInfo("Filter cutoff", dataValue.toString(), "");
|
|
10735
10895
|
break;
|
|
10896
|
+
case nonRegisteredLSB.TVFFilterResonance:
|
|
10897
|
+
this.controllerChange(
|
|
10898
|
+
midiControllers.filterResonance,
|
|
10899
|
+
dataValue
|
|
10900
|
+
);
|
|
10901
|
+
coolInfo(
|
|
10902
|
+
"Filter resonance",
|
|
10903
|
+
dataValue.toString(),
|
|
10904
|
+
""
|
|
10905
|
+
);
|
|
10906
|
+
break;
|
|
10736
10907
|
// Attack time
|
|
10737
|
-
case
|
|
10908
|
+
case nonRegisteredLSB.EGAttackTime:
|
|
10738
10909
|
this.controllerChange(
|
|
10739
10910
|
midiControllers.attackTime,
|
|
10740
10911
|
dataValue
|
|
@@ -10745,8 +10916,15 @@ function dataEntryCoarse(dataValue) {
|
|
|
10745
10916
|
""
|
|
10746
10917
|
);
|
|
10747
10918
|
break;
|
|
10919
|
+
case nonRegisteredLSB.EGDecayTime:
|
|
10920
|
+
this.controllerChange(
|
|
10921
|
+
midiControllers.decayTime,
|
|
10922
|
+
dataValue
|
|
10923
|
+
);
|
|
10924
|
+
coolInfo("EG decay time", dataValue.toString(), "");
|
|
10925
|
+
break;
|
|
10748
10926
|
// Release time
|
|
10749
|
-
case
|
|
10927
|
+
case nonRegisteredLSB.EGReleaseTime:
|
|
10750
10928
|
this.controllerChange(
|
|
10751
10929
|
midiControllers.releaseTime,
|
|
10752
10930
|
dataValue
|
|
@@ -11163,9 +11341,10 @@ var portamentoLookup = {
|
|
|
11163
11341
|
124: 80,
|
|
11164
11342
|
127: 480
|
|
11165
11343
|
};
|
|
11166
|
-
function
|
|
11344
|
+
function portaTimeToRate(value) {
|
|
11345
|
+
let portaTime = 0;
|
|
11167
11346
|
if (portamentoLookup[value] !== void 0) {
|
|
11168
|
-
|
|
11347
|
+
portaTime = portamentoLookup[value];
|
|
11169
11348
|
}
|
|
11170
11349
|
let lower = null;
|
|
11171
11350
|
let upper = null;
|
|
@@ -11181,12 +11360,12 @@ function getLookup(value) {
|
|
|
11181
11360
|
if (lower !== null && upper !== null) {
|
|
11182
11361
|
const lowerTime = portamentoLookup[lower];
|
|
11183
11362
|
const upperTime = portamentoLookup[upper];
|
|
11184
|
-
|
|
11363
|
+
portaTime = lowerTime + (value - lower) * (upperTime - lowerTime) / (upper - lower);
|
|
11185
11364
|
}
|
|
11186
|
-
return
|
|
11365
|
+
return portaTime / 40;
|
|
11187
11366
|
}
|
|
11188
11367
|
function portamentoTimeToSeconds(time, distance) {
|
|
11189
|
-
return
|
|
11368
|
+
return portaTimeToRate(time) * distance;
|
|
11190
11369
|
}
|
|
11191
11370
|
|
|
11192
11371
|
// src/synthesizer/audio_engine/engine_methods/note_on.ts
|
|
@@ -11230,16 +11409,15 @@ function noteOn(midiNote, velocity) {
|
|
|
11230
11409
|
let portamentoFromKey = -1;
|
|
11231
11410
|
let portamentoDuration = 0;
|
|
11232
11411
|
const portamentoTime = this.midiControllers[midiControllers.portamentoTime] >> 7;
|
|
11233
|
-
const
|
|
11234
|
-
const currentFromKey = control >> 7;
|
|
11412
|
+
const portaControl = this.midiControllers[midiControllers.portamentoControl] >> 7;
|
|
11235
11413
|
if (!this.drumChannel && // No portamento on drum channel
|
|
11236
|
-
|
|
11414
|
+
portaControl !== internalMidiNote && // If the same note, there's no portamento
|
|
11237
11415
|
this.midiControllers[midiControllers.portamentoOnOff] >= 8192 && // (64 << 7)
|
|
11238
11416
|
portamentoTime > 0) {
|
|
11239
|
-
if (
|
|
11240
|
-
const diff = Math.abs(internalMidiNote -
|
|
11417
|
+
if (portaControl > 0) {
|
|
11418
|
+
const diff = Math.abs(internalMidiNote - portaControl);
|
|
11241
11419
|
portamentoDuration = portamentoTimeToSeconds(portamentoTime, diff);
|
|
11242
|
-
portamentoFromKey =
|
|
11420
|
+
portamentoFromKey = portaControl;
|
|
11243
11421
|
}
|
|
11244
11422
|
this.controllerChange(
|
|
11245
11423
|
midiControllers.portamentoControl,
|
|
@@ -17057,16 +17235,12 @@ var SpessaSynthProcessor3 = class {
|
|
|
17057
17235
|
});
|
|
17058
17236
|
}
|
|
17059
17237
|
getCachedVoice(patch, midiNote, velocity) {
|
|
17060
|
-
|
|
17061
|
-
let bankLSB = patch.bankLSB;
|
|
17062
|
-
const { isGMGSDrum, program } = patch;
|
|
17063
|
-
if (isGMGSDrum) {
|
|
17064
|
-
bankMSB = 128;
|
|
17065
|
-
bankLSB = 0;
|
|
17066
|
-
}
|
|
17067
|
-
return this.privateProps.cachedVoices?.[bankMSB]?.[bankLSB]?.[program]?.[midiNote]?.[velocity];
|
|
17238
|
+
return this.privateProps.cachedVoices?.[this.getCachedVoiceIndex(patch, midiNote, velocity)];
|
|
17068
17239
|
}
|
|
17069
17240
|
setCachedVoice(patch, midiNote, velocity, voices) {
|
|
17241
|
+
this.privateProps.cachedVoices[this.getCachedVoiceIndex(patch, midiNote, velocity)] = voices;
|
|
17242
|
+
}
|
|
17243
|
+
getCachedVoiceIndex(patch, midiNote, velocity) {
|
|
17070
17244
|
let bankMSB = patch.bankMSB;
|
|
17071
17245
|
let bankLSB = patch.bankLSB;
|
|
17072
17246
|
const { isGMGSDrum, program } = patch;
|
|
@@ -17074,19 +17248,11 @@ var SpessaSynthProcessor3 = class {
|
|
|
17074
17248
|
bankMSB = 128;
|
|
17075
17249
|
bankLSB = 0;
|
|
17076
17250
|
}
|
|
17077
|
-
|
|
17078
|
-
|
|
17079
|
-
|
|
17080
|
-
|
|
17081
|
-
|
|
17082
|
-
}
|
|
17083
|
-
if (!this.privateProps.cachedVoices[bankMSB][bankLSB][program]) {
|
|
17084
|
-
this.privateProps.cachedVoices[bankMSB][bankLSB][program] = [];
|
|
17085
|
-
}
|
|
17086
|
-
if (!this.privateProps.cachedVoices[bankMSB][bankLSB][program][midiNote]) {
|
|
17087
|
-
this.privateProps.cachedVoices[bankMSB][bankLSB][program][midiNote] = [];
|
|
17088
|
-
}
|
|
17089
|
-
this.privateProps.cachedVoices[bankMSB][bankLSB][program][midiNote][velocity] = voices;
|
|
17251
|
+
return bankMSB + // 128 ^ 0
|
|
17252
|
+
bankLSB * 128 + // 128 ^ 1
|
|
17253
|
+
program * 16384 + // 128 ^ 2
|
|
17254
|
+
2097152 * midiNote + // 128 ^ 3
|
|
17255
|
+
268435456 * velocity;
|
|
17090
17256
|
}
|
|
17091
17257
|
createMIDIChannelInternal(sendEvent) {
|
|
17092
17258
|
const channel = new MIDIChannel(
|
|
@@ -17110,7 +17276,7 @@ var SpessaSynthProcessor3 = class {
|
|
|
17110
17276
|
this.midiChannels.forEach((c) => {
|
|
17111
17277
|
c.setPresetLock(false);
|
|
17112
17278
|
});
|
|
17113
|
-
this.resetAllControllers(
|
|
17279
|
+
this.resetAllControllers();
|
|
17114
17280
|
}
|
|
17115
17281
|
getDefaultPresets() {
|
|
17116
17282
|
this.privateProps.defaultPreset = this.soundBankManager.getPreset(
|
|
@@ -17164,7 +17330,6 @@ export {
|
|
|
17164
17330
|
Modulator,
|
|
17165
17331
|
ModulatorSource,
|
|
17166
17332
|
NON_CC_INDEX_OFFSET,
|
|
17167
|
-
PORTAMENTO_CONTROL_UNSET,
|
|
17168
17333
|
SoundBankLoader,
|
|
17169
17334
|
SpessaSynthCoreUtils,
|
|
17170
17335
|
SpessaSynthLogging,
|