spessasynth_core 4.0.23 → 4.0.25
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 +21 -8
- package/dist/index.js +1229 -986
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2999,6 +2999,41 @@ var BasicMIDI2 = class _BasicMIDI {
|
|
|
2999
2999
|
}
|
|
3000
3000
|
return totalSeconds;
|
|
3001
3001
|
}
|
|
3002
|
+
/**
|
|
3003
|
+
* Converts seconds to time in MIDI ticks.
|
|
3004
|
+
* @param seconds The time in seconds.
|
|
3005
|
+
* @returns The time in MIDI ticks.
|
|
3006
|
+
*/
|
|
3007
|
+
secondsToMIDITicks(seconds) {
|
|
3008
|
+
seconds = Math.max(seconds, 0);
|
|
3009
|
+
if (seconds === 0) return 0;
|
|
3010
|
+
if (this.tempoChanges.length < 1) {
|
|
3011
|
+
throw new Error(
|
|
3012
|
+
"There are no tempo changes in the sequence. At least one is needed."
|
|
3013
|
+
);
|
|
3014
|
+
}
|
|
3015
|
+
if (this.tempoChanges[this.tempoChanges.length - 1].ticks !== 0) {
|
|
3016
|
+
throw new Error(
|
|
3017
|
+
`The last tempo change is not at 0 ticks. Got ${this.tempoChanges[this.tempoChanges.length - 1].ticks} ticks.`
|
|
3018
|
+
);
|
|
3019
|
+
}
|
|
3020
|
+
let remainingSeconds = seconds;
|
|
3021
|
+
let totalTicks = 0;
|
|
3022
|
+
for (let i = this.tempoChanges.length - 1; i >= 0; i--) {
|
|
3023
|
+
const currentTempo = this.tempoChanges[i];
|
|
3024
|
+
const next = this.tempoChanges[i - 1];
|
|
3025
|
+
const ticksToNextTempo = next ? next.ticks - currentTempo.ticks : Infinity;
|
|
3026
|
+
const oneTickToSeconds = 60 / (currentTempo.tempo * this.timeDivision);
|
|
3027
|
+
const secondsToNextTempo = ticksToNextTempo * oneTickToSeconds;
|
|
3028
|
+
if (remainingSeconds <= secondsToNextTempo) {
|
|
3029
|
+
totalTicks += Math.round(remainingSeconds / oneTickToSeconds);
|
|
3030
|
+
return totalTicks;
|
|
3031
|
+
}
|
|
3032
|
+
totalTicks += ticksToNextTempo;
|
|
3033
|
+
remainingSeconds -= secondsToNextTempo;
|
|
3034
|
+
}
|
|
3035
|
+
return totalTicks;
|
|
3036
|
+
}
|
|
3002
3037
|
/**
|
|
3003
3038
|
* Gets the used programs and keys for this MIDI file with a given sound bank.
|
|
3004
3039
|
* @param soundbank the sound bank.
|
|
@@ -3007,6 +3042,32 @@ var BasicMIDI2 = class _BasicMIDI {
|
|
|
3007
3042
|
getUsedProgramsAndKeys(soundbank) {
|
|
3008
3043
|
return getUsedProgramsAndKeys(this, soundbank);
|
|
3009
3044
|
}
|
|
3045
|
+
/**
|
|
3046
|
+
* Preloads all voices for this sequence in a given synth.
|
|
3047
|
+
* This caches all the needed voices for playing back this sequencer, resulting in a smooth playback.
|
|
3048
|
+
* The sequencer calls this function by default when loading the songs.
|
|
3049
|
+
* @param synth
|
|
3050
|
+
*/
|
|
3051
|
+
preloadSynth(synth) {
|
|
3052
|
+
SpessaSynthGroupCollapsed(
|
|
3053
|
+
`%cPreloading samples...`,
|
|
3054
|
+
consoleColors.info
|
|
3055
|
+
);
|
|
3056
|
+
const used = this.getUsedProgramsAndKeys(synth.soundBankManager);
|
|
3057
|
+
used.forEach((combos, preset) => {
|
|
3058
|
+
SpessaSynthInfo(
|
|
3059
|
+
`%cPreloading used samples on %c${preset.name}%c...`,
|
|
3060
|
+
consoleColors.info,
|
|
3061
|
+
consoleColors.recognized,
|
|
3062
|
+
consoleColors.info
|
|
3063
|
+
);
|
|
3064
|
+
for (const combo of combos) {
|
|
3065
|
+
const [midiNote, velocity] = combo.split("-").map(Number);
|
|
3066
|
+
synth.getVoicesForPreset(preset, midiNote, velocity, midiNote);
|
|
3067
|
+
}
|
|
3068
|
+
});
|
|
3069
|
+
SpessaSynthGroupEnd();
|
|
3070
|
+
}
|
|
3010
3071
|
/**
|
|
3011
3072
|
* Updates all internal values of the MIDI.
|
|
3012
3073
|
* @param sortEvents if the events should be sorted by ticks. Recommended to be true.
|
|
@@ -3438,6 +3499,10 @@ var BasicMIDI2 = class _BasicMIDI {
|
|
|
3438
3499
|
loopEnd = this.lastVoiceEventTick;
|
|
3439
3500
|
}
|
|
3440
3501
|
this.loop = { start: loopStart, end: loopEnd, type: loopType };
|
|
3502
|
+
this.lastVoiceEventTick = Math.max(
|
|
3503
|
+
this.lastVoiceEventTick,
|
|
3504
|
+
this.loop.end
|
|
3505
|
+
);
|
|
3441
3506
|
SpessaSynthInfo(
|
|
3442
3507
|
`%cLoop points: start: %c${this.loop.start}%c end: %c${this.loop.end}`,
|
|
3443
3508
|
consoleColors.info,
|
|
@@ -3958,33 +4023,9 @@ function loadNewSequenceInternal(parsedMidi) {
|
|
|
3958
4023
|
this._midiData.embeddedSoundBank,
|
|
3959
4024
|
this._midiData.bankOffset
|
|
3960
4025
|
);
|
|
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();
|
|
4026
|
+
if (this.preload) {
|
|
4027
|
+
this._midiData.preloadSynth(this.synth);
|
|
4028
|
+
}
|
|
3988
4029
|
}
|
|
3989
4030
|
this.currentMIDIPorts = this._midiData.tracks.map((t) => t.port);
|
|
3990
4031
|
this.midiPortChannelOffset = 0;
|
|
@@ -4582,8 +4623,6 @@ setResetValue(midiControllers.registeredParameterLSB, 127);
|
|
|
4582
4623
|
setResetValue(midiControllers.registeredParameterMSB, 127);
|
|
4583
4624
|
setResetValue(midiControllers.nonRegisteredParameterLSB, 127);
|
|
4584
4625
|
setResetValue(midiControllers.nonRegisteredParameterMSB, 127);
|
|
4585
|
-
var PORTAMENTO_CONTROL_UNSET = 1;
|
|
4586
|
-
defaultMIDIControllerValues[midiControllers.portamentoControl] = PORTAMENTO_CONTROL_UNSET;
|
|
4587
4626
|
setResetValue(
|
|
4588
4627
|
NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel,
|
|
4589
4628
|
64
|
|
@@ -4597,12 +4636,9 @@ var customResetArray = new Float32Array(CUSTOM_CONTROLLER_TABLE_SIZE);
|
|
|
4597
4636
|
customResetArray[customControllers.modulationMultiplier] = 1;
|
|
4598
4637
|
|
|
4599
4638
|
// 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
|
-
}
|
|
4639
|
+
function resetAllControllersInternal(system = DEFAULT_SYNTH_MODE) {
|
|
4604
4640
|
this.privateProps.callEvent("allControllerReset", void 0);
|
|
4605
|
-
this.setMasterParameter("midiSystem",
|
|
4641
|
+
this.setMasterParameter("midiSystem", system);
|
|
4606
4642
|
this.privateProps.tunings.length = 0;
|
|
4607
4643
|
for (let i = 0; i < 128; i++) {
|
|
4608
4644
|
this.privateProps.tunings.push([]);
|
|
@@ -4642,27 +4678,34 @@ function resetAllControllersInternal(log = true) {
|
|
|
4642
4678
|
}
|
|
4643
4679
|
}
|
|
4644
4680
|
}
|
|
4681
|
+
function resetPortamento(sendCC) {
|
|
4682
|
+
if (this.lockedControllers[midiControllers.portamentoControl]) return;
|
|
4683
|
+
if (this.channelSystem === "xg") {
|
|
4684
|
+
this.controllerChange(midiControllers.portamentoControl, 60, sendCC);
|
|
4685
|
+
} else {
|
|
4686
|
+
this.controllerChange(midiControllers.portamentoControl, 0, sendCC);
|
|
4687
|
+
}
|
|
4688
|
+
}
|
|
4645
4689
|
function resetControllers(sendCCEvents = true) {
|
|
4646
4690
|
this.channelOctaveTuning.fill(0);
|
|
4647
|
-
for (let
|
|
4648
|
-
if (this.lockedControllers[
|
|
4691
|
+
for (let cc = 0; cc < defaultMIDIControllerValues.length; cc++) {
|
|
4692
|
+
if (this.lockedControllers[cc]) {
|
|
4649
4693
|
continue;
|
|
4650
4694
|
}
|
|
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) {
|
|
4695
|
+
const resetValue = defaultMIDIControllerValues[cc];
|
|
4696
|
+
if (this.midiControllers[cc] !== resetValue && cc < 127) {
|
|
4697
|
+
if (cc !== midiControllers.portamentoControl && cc !== midiControllers.dataEntryMSB && cc !== midiControllers.registeredParameterMSB && cc !== midiControllers.registeredParameterLSB && cc !== midiControllers.nonRegisteredParameterMSB && cc !== midiControllers.nonRegisteredParameterLSB) {
|
|
4656
4698
|
this.controllerChange(
|
|
4657
|
-
|
|
4699
|
+
cc,
|
|
4658
4700
|
resetValue >> 7,
|
|
4659
4701
|
sendCCEvents
|
|
4660
4702
|
);
|
|
4661
4703
|
}
|
|
4662
4704
|
} else {
|
|
4663
|
-
this.midiControllers[
|
|
4705
|
+
this.midiControllers[cc] = resetValue;
|
|
4664
4706
|
}
|
|
4665
4707
|
}
|
|
4708
|
+
resetPortamento.call(this, sendCCEvents);
|
|
4666
4709
|
this.channelVibrato = { rate: 0, depth: 0, delay: 0 };
|
|
4667
4710
|
this.randomPan = false;
|
|
4668
4711
|
this.sysExModulators.resetModulators();
|
|
@@ -4708,13 +4751,12 @@ function resetControllersRP15Compliant() {
|
|
|
4708
4751
|
for (let i = 0; i < 128; i++) {
|
|
4709
4752
|
const resetValue = defaultMIDIControllerValues[i];
|
|
4710
4753
|
if (!nonResettableCCs.has(i) && resetValue !== this.midiControllers[i]) {
|
|
4711
|
-
if (i
|
|
4712
|
-
this.midiControllers[i] = PORTAMENTO_CONTROL_UNSET;
|
|
4713
|
-
} else {
|
|
4754
|
+
if (i !== midiControllers.portamentoControl) {
|
|
4714
4755
|
this.controllerChange(i, resetValue >> 7);
|
|
4715
4756
|
}
|
|
4716
4757
|
}
|
|
4717
4758
|
}
|
|
4759
|
+
resetPortamento.call(this, true);
|
|
4718
4760
|
this.resetGeneratorOverrides();
|
|
4719
4761
|
this.resetGeneratorOffsets();
|
|
4720
4762
|
}
|
|
@@ -5166,6 +5208,15 @@ var SpessaSynthSequencer = class {
|
|
|
5166
5208
|
this._songIndex = 0;
|
|
5167
5209
|
this.shuffleSongIndexes();
|
|
5168
5210
|
this.callEvent("songListChange", { newSongList: [...this.songs] });
|
|
5211
|
+
if (this.preload) {
|
|
5212
|
+
SpessaSynthGroup("%cPreloading all songs...", consoleColors.info);
|
|
5213
|
+
this.songs.forEach((song) => {
|
|
5214
|
+
if (song.embeddedSoundBank === void 0) {
|
|
5215
|
+
song.preloadSynth(this.synth);
|
|
5216
|
+
}
|
|
5217
|
+
});
|
|
5218
|
+
SpessaSynthGroupEnd();
|
|
5219
|
+
}
|
|
5169
5220
|
this.loadCurrentSong();
|
|
5170
5221
|
}
|
|
5171
5222
|
callEvent(type, data) {
|
|
@@ -6902,20 +6953,6 @@ var defaultSoundFont2Modulators = [
|
|
|
6902
6953
|
];
|
|
6903
6954
|
var defaultSpessaSynthModulators = [
|
|
6904
6955
|
// Custom modulators heck yeah
|
|
6905
|
-
// Poly pressure to vibrato
|
|
6906
|
-
new DecodedModulator(
|
|
6907
|
-
getModSourceEnum(
|
|
6908
|
-
modulatorCurveTypes.linear,
|
|
6909
|
-
false,
|
|
6910
|
-
false,
|
|
6911
|
-
false,
|
|
6912
|
-
modulatorSources.polyPressure
|
|
6913
|
-
),
|
|
6914
|
-
0,
|
|
6915
|
-
generatorTypes.vibLfoToPitch,
|
|
6916
|
-
50,
|
|
6917
|
-
0
|
|
6918
|
-
),
|
|
6919
6956
|
// Cc 92 (tremolo) to modLFO volume
|
|
6920
6957
|
new DecodedModulator(
|
|
6921
6958
|
getModSourceEnum(
|
|
@@ -6963,6 +7000,22 @@ var defaultSpessaSynthModulators = [
|
|
|
6963
7000
|
3600,
|
|
6964
7001
|
0
|
|
6965
7002
|
),
|
|
7003
|
+
// Cc 75 (decay time) to vol env decay
|
|
7004
|
+
new DecodedModulator(
|
|
7005
|
+
getModSourceEnum(
|
|
7006
|
+
modulatorCurveTypes.linear,
|
|
7007
|
+
true,
|
|
7008
|
+
false,
|
|
7009
|
+
true,
|
|
7010
|
+
midiControllers.decayTime
|
|
7011
|
+
),
|
|
7012
|
+
// Linear forward bipolar cc 75
|
|
7013
|
+
0,
|
|
7014
|
+
// No controller
|
|
7015
|
+
generatorTypes.decayVolEnv,
|
|
7016
|
+
3600,
|
|
7017
|
+
0
|
|
7018
|
+
),
|
|
6966
7019
|
// Cc 74 (brightness) to filterFc
|
|
6967
7020
|
new DecodedModulator(
|
|
6968
7021
|
getModSourceEnum(
|
|
@@ -6976,7 +7029,7 @@ var defaultSpessaSynthModulators = [
|
|
|
6976
7029
|
0,
|
|
6977
7030
|
// No controller
|
|
6978
7031
|
generatorTypes.initialFilterFc,
|
|
6979
|
-
|
|
7032
|
+
9600,
|
|
6980
7033
|
0
|
|
6981
7034
|
),
|
|
6982
7035
|
// Cc 71 (filter Q) to filter Q (default resonant modulator)
|
|
@@ -6985,7 +7038,55 @@ var defaultSpessaSynthModulators = [
|
|
|
6985
7038
|
0,
|
|
6986
7039
|
// No controller
|
|
6987
7040
|
generatorTypes.initialFilterQ,
|
|
6988
|
-
|
|
7041
|
+
200,
|
|
7042
|
+
0
|
|
7043
|
+
),
|
|
7044
|
+
// Cc 67 (soft pedal) to attenuation
|
|
7045
|
+
new DecodedModulator(
|
|
7046
|
+
getModSourceEnum(
|
|
7047
|
+
modulatorCurveTypes.switch,
|
|
7048
|
+
false,
|
|
7049
|
+
false,
|
|
7050
|
+
true,
|
|
7051
|
+
midiControllers.softPedal
|
|
7052
|
+
),
|
|
7053
|
+
// Switch unipolar positive 67
|
|
7054
|
+
0,
|
|
7055
|
+
// No controller
|
|
7056
|
+
generatorTypes.initialAttenuation,
|
|
7057
|
+
50,
|
|
7058
|
+
0
|
|
7059
|
+
),
|
|
7060
|
+
// Cc 67 (soft pedal) to filter fc
|
|
7061
|
+
new DecodedModulator(
|
|
7062
|
+
getModSourceEnum(
|
|
7063
|
+
modulatorCurveTypes.switch,
|
|
7064
|
+
false,
|
|
7065
|
+
false,
|
|
7066
|
+
true,
|
|
7067
|
+
midiControllers.softPedal
|
|
7068
|
+
),
|
|
7069
|
+
// Switch unipolar positive 67
|
|
7070
|
+
0,
|
|
7071
|
+
// No controller
|
|
7072
|
+
generatorTypes.initialFilterFc,
|
|
7073
|
+
-2400,
|
|
7074
|
+
0
|
|
7075
|
+
),
|
|
7076
|
+
// Cc 8 (balance) to pan
|
|
7077
|
+
new DecodedModulator(
|
|
7078
|
+
getModSourceEnum(
|
|
7079
|
+
modulatorCurveTypes.linear,
|
|
7080
|
+
true,
|
|
7081
|
+
false,
|
|
7082
|
+
true,
|
|
7083
|
+
midiControllers.balance
|
|
7084
|
+
),
|
|
7085
|
+
// Linear bipolar positive 8
|
|
7086
|
+
0,
|
|
7087
|
+
// No controller
|
|
7088
|
+
generatorTypes.pan,
|
|
7089
|
+
500,
|
|
6989
7090
|
0
|
|
6990
7091
|
)
|
|
6991
7092
|
];
|
|
@@ -8274,7 +8375,7 @@ function panAndMixVoice(voice, inputBuffer, outputLeft, outputRight, reverbLeft,
|
|
|
8274
8375
|
}
|
|
8275
8376
|
|
|
8276
8377
|
// src/synthesizer/audio_engine/engine_components/dsp_chain/lowpass_filter.ts
|
|
8277
|
-
var FILTER_SMOOTHING_FACTOR = 0.
|
|
8378
|
+
var FILTER_SMOOTHING_FACTOR = 0.03;
|
|
8278
8379
|
var LowpassFilter = class _LowpassFilter {
|
|
8279
8380
|
/**
|
|
8280
8381
|
* Cached coefficient calculations.
|
|
@@ -8955,7 +9056,29 @@ function getVoicesInternal(channel, midiNote, velocity, realKey) {
|
|
|
8955
9056
|
return this.getVoicesForPreset(preset, midiNote, velocity, realKey);
|
|
8956
9057
|
}
|
|
8957
9058
|
|
|
8958
|
-
// src/synthesizer/audio_engine/engine_methods/system_exclusive.ts
|
|
9059
|
+
// src/synthesizer/audio_engine/engine_methods/system_exclusive/helpers.ts
|
|
9060
|
+
function sysExLogging(syx, channel, value, what, units) {
|
|
9061
|
+
SpessaSynthInfo(
|
|
9062
|
+
`%cChannel %c${channel}%c ${what}. %c${value} ${units}%c, with %c${arrayToHexString(syx)}`,
|
|
9063
|
+
consoleColors.info,
|
|
9064
|
+
consoleColors.recognized,
|
|
9065
|
+
consoleColors.info,
|
|
9066
|
+
consoleColors.value,
|
|
9067
|
+
consoleColors.info,
|
|
9068
|
+
consoleColors.value
|
|
9069
|
+
);
|
|
9070
|
+
}
|
|
9071
|
+
function sysExNotRecognized(syx, what) {
|
|
9072
|
+
SpessaSynthInfo(
|
|
9073
|
+
`%cUnrecognized %c${what} %cSysEx: %c${arrayToHexString(syx)}`,
|
|
9074
|
+
consoleColors.warn,
|
|
9075
|
+
consoleColors.recognized,
|
|
9076
|
+
consoleColors.warn,
|
|
9077
|
+
consoleColors.unrecognized
|
|
9078
|
+
);
|
|
9079
|
+
}
|
|
9080
|
+
|
|
9081
|
+
// src/synthesizer/audio_engine/engine_methods/system_exclusive/handle_gm.ts
|
|
8959
9082
|
function getTuning(byte1, byte2, byte3) {
|
|
8960
9083
|
const midiNote = byte1;
|
|
8961
9084
|
const fraction = byte2 << 7 | byte3;
|
|
@@ -8964,900 +9087,971 @@ function getTuning(byte1, byte2, byte3) {
|
|
|
8964
9087
|
}
|
|
8965
9088
|
return { midiNote, centTuning: fraction * 61e-4 };
|
|
8966
9089
|
}
|
|
8967
|
-
function
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
9090
|
+
function handleGM(syx, channelOffset = 0) {
|
|
9091
|
+
switch (syx[2]) {
|
|
9092
|
+
case 4: {
|
|
9093
|
+
let cents;
|
|
9094
|
+
switch (syx[3]) {
|
|
9095
|
+
case 1: {
|
|
9096
|
+
const vol = syx[5] << 7 | syx[4];
|
|
9097
|
+
this.setMIDIVolume(vol / 16384);
|
|
9098
|
+
SpessaSynthInfo(
|
|
9099
|
+
`%cMaster Volume. Volume: %c${vol}`,
|
|
9100
|
+
consoleColors.info,
|
|
9101
|
+
consoleColors.value
|
|
9102
|
+
);
|
|
9103
|
+
break;
|
|
9104
|
+
}
|
|
9105
|
+
case 2: {
|
|
9106
|
+
const balance = syx[5] << 7 | syx[4];
|
|
9107
|
+
const pan = (balance - 8192) / 8192;
|
|
9108
|
+
this.setMasterParameter("masterPan", pan);
|
|
9109
|
+
SpessaSynthInfo(
|
|
9110
|
+
`%cMaster Pan. Pan: %c${pan}`,
|
|
9111
|
+
consoleColors.info,
|
|
9112
|
+
consoleColors.value
|
|
9113
|
+
);
|
|
9114
|
+
break;
|
|
9115
|
+
}
|
|
9116
|
+
case 3: {
|
|
9117
|
+
const tuningValue = (syx[5] << 7 | syx[6]) - 8192;
|
|
9118
|
+
cents = Math.floor(tuningValue / 81.92);
|
|
9119
|
+
this.setMasterTuning(cents);
|
|
9120
|
+
SpessaSynthInfo(
|
|
9121
|
+
`%cMaster Fine Tuning. Cents: %c${cents}`,
|
|
9122
|
+
consoleColors.info,
|
|
9123
|
+
consoleColors.value
|
|
9124
|
+
);
|
|
9125
|
+
break;
|
|
9126
|
+
}
|
|
9127
|
+
case 4: {
|
|
9128
|
+
const semitones = syx[5] - 64;
|
|
9129
|
+
cents = semitones * 100;
|
|
9130
|
+
this.setMasterTuning(cents);
|
|
9131
|
+
SpessaSynthInfo(
|
|
9132
|
+
`%cMaster Coarse Tuning. Cents: %c${cents}`,
|
|
9133
|
+
consoleColors.info,
|
|
9134
|
+
consoleColors.value
|
|
9135
|
+
);
|
|
9136
|
+
break;
|
|
9137
|
+
}
|
|
9138
|
+
default:
|
|
9139
|
+
SpessaSynthInfo(
|
|
9140
|
+
`%cUnrecognized MIDI Device Control Real-time message: %c${arrayToHexString(syx)}`,
|
|
9141
|
+
consoleColors.warn,
|
|
9142
|
+
consoleColors.unrecognized
|
|
9143
|
+
);
|
|
9144
|
+
}
|
|
9145
|
+
break;
|
|
8972
9146
|
}
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
SpessaSynthInfo(
|
|
8988
|
-
`%cUnrecognized SysEx: %c${arrayToHexString(syx)}`,
|
|
8989
|
-
consoleColors.warn,
|
|
8990
|
-
consoleColors.unrecognized
|
|
8991
|
-
);
|
|
9147
|
+
case 9:
|
|
9148
|
+
if (syx[3] === 1) {
|
|
9149
|
+
SpessaSynthInfo("%cGM1 system on", consoleColors.info);
|
|
9150
|
+
this.resetAllControllers("gm");
|
|
9151
|
+
} else if (syx[3] === 3) {
|
|
9152
|
+
SpessaSynthInfo("%cGM2 system on", consoleColors.info);
|
|
9153
|
+
this.resetAllControllers("gm2");
|
|
9154
|
+
} else {
|
|
9155
|
+
SpessaSynthInfo(
|
|
9156
|
+
"%cGM system off, defaulting to GS",
|
|
9157
|
+
consoleColors.info
|
|
9158
|
+
);
|
|
9159
|
+
this.setMasterParameter("midiSystem", "gs");
|
|
9160
|
+
}
|
|
8992
9161
|
break;
|
|
8993
|
-
//
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
switch (syx[
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
const balance = syx[5] << 7 | syx[4];
|
|
9013
|
-
const pan = (balance - 8192) / 8192;
|
|
9014
|
-
this.setMasterParameter("masterPan", pan);
|
|
9015
|
-
SpessaSynthInfo(
|
|
9016
|
-
`%cMaster Pan. Pan: %c${pan}`,
|
|
9017
|
-
consoleColors.info,
|
|
9018
|
-
consoleColors.value
|
|
9019
|
-
);
|
|
9020
|
-
break;
|
|
9021
|
-
}
|
|
9022
|
-
case 3: {
|
|
9023
|
-
const tuningValue = (syx[5] << 7 | syx[6]) - 8192;
|
|
9024
|
-
cents = Math.floor(tuningValue / 81.92);
|
|
9025
|
-
this.setMasterTuning(cents);
|
|
9026
|
-
SpessaSynthInfo(
|
|
9027
|
-
`%cMaster Fine Tuning. Cents: %c${cents}`,
|
|
9028
|
-
consoleColors.info,
|
|
9029
|
-
consoleColors.value
|
|
9030
|
-
);
|
|
9031
|
-
break;
|
|
9032
|
-
}
|
|
9033
|
-
case 4: {
|
|
9034
|
-
const semitones = syx[5] - 64;
|
|
9035
|
-
cents = semitones * 100;
|
|
9036
|
-
this.setMasterTuning(cents);
|
|
9037
|
-
SpessaSynthInfo(
|
|
9038
|
-
`%cMaster Coarse Tuning. Cents: %c${cents}`,
|
|
9039
|
-
consoleColors.info,
|
|
9040
|
-
consoleColors.value
|
|
9041
|
-
);
|
|
9042
|
-
break;
|
|
9043
|
-
}
|
|
9044
|
-
default:
|
|
9045
|
-
SpessaSynthInfo(
|
|
9046
|
-
`%cUnrecognized MIDI Device Control Real-time message: %c${arrayToHexString(syx)}`,
|
|
9047
|
-
consoleColors.warn,
|
|
9048
|
-
consoleColors.unrecognized
|
|
9049
|
-
);
|
|
9162
|
+
// MIDI Tuning standard
|
|
9163
|
+
// https://midi.org/midi-tuning-updated-specification
|
|
9164
|
+
case 8: {
|
|
9165
|
+
let currentMessageIndex = 4;
|
|
9166
|
+
switch (syx[3]) {
|
|
9167
|
+
// Bulk tuning dump: all 128 notes
|
|
9168
|
+
case 1: {
|
|
9169
|
+
const program = syx[currentMessageIndex++];
|
|
9170
|
+
const tuningName = readBinaryString(
|
|
9171
|
+
syx,
|
|
9172
|
+
16,
|
|
9173
|
+
currentMessageIndex
|
|
9174
|
+
);
|
|
9175
|
+
currentMessageIndex += 16;
|
|
9176
|
+
if (syx.length < 384) {
|
|
9177
|
+
SpessaSynthWarn(
|
|
9178
|
+
`The Bulk Tuning Dump is too short! (${syx.length} bytes, at least 384 are expected)`
|
|
9179
|
+
);
|
|
9180
|
+
return;
|
|
9050
9181
|
}
|
|
9182
|
+
for (let i = 0; i < 128; i++) {
|
|
9183
|
+
this.privateProps.tunings[program][i] = getTuning(
|
|
9184
|
+
syx[currentMessageIndex++],
|
|
9185
|
+
syx[currentMessageIndex++],
|
|
9186
|
+
syx[currentMessageIndex++]
|
|
9187
|
+
);
|
|
9188
|
+
}
|
|
9189
|
+
SpessaSynthInfo(
|
|
9190
|
+
`%cBulk Tuning Dump %c${tuningName}%c Program: %c${program}`,
|
|
9191
|
+
consoleColors.info,
|
|
9192
|
+
consoleColors.value,
|
|
9193
|
+
consoleColors.info,
|
|
9194
|
+
consoleColors.recognized
|
|
9195
|
+
);
|
|
9051
9196
|
break;
|
|
9052
9197
|
}
|
|
9198
|
+
// Single note change
|
|
9199
|
+
// Single note change bank
|
|
9200
|
+
case 2:
|
|
9201
|
+
case 7: {
|
|
9202
|
+
if (syx[3] === 7) {
|
|
9203
|
+
currentMessageIndex++;
|
|
9204
|
+
}
|
|
9205
|
+
const tuningProgram = syx[currentMessageIndex++];
|
|
9206
|
+
const numberOfChanges = syx[currentMessageIndex++];
|
|
9207
|
+
for (let i = 0; i < numberOfChanges; i++) {
|
|
9208
|
+
this.privateProps.tunings[tuningProgram][syx[currentMessageIndex++]] = getTuning(
|
|
9209
|
+
syx[currentMessageIndex++],
|
|
9210
|
+
syx[currentMessageIndex++],
|
|
9211
|
+
syx[currentMessageIndex++]
|
|
9212
|
+
);
|
|
9213
|
+
}
|
|
9214
|
+
SpessaSynthInfo(
|
|
9215
|
+
`%cSingle Note Tuning. Program: %c${tuningProgram}%c Keys affected: %c${numberOfChanges}`,
|
|
9216
|
+
consoleColors.info,
|
|
9217
|
+
consoleColors.recognized,
|
|
9218
|
+
consoleColors.info,
|
|
9219
|
+
consoleColors.recognized
|
|
9220
|
+
);
|
|
9221
|
+
break;
|
|
9222
|
+
}
|
|
9223
|
+
// Octave tuning (1 byte)
|
|
9224
|
+
// And octave tuning (2 bytes)
|
|
9053
9225
|
case 9:
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9226
|
+
case 8: {
|
|
9227
|
+
const newOctaveTuning = new Int8Array(12);
|
|
9228
|
+
if (syx[3] === 8) {
|
|
9229
|
+
for (let i = 0; i < 12; i++) {
|
|
9230
|
+
newOctaveTuning[i] = syx[7 + i] - 64;
|
|
9231
|
+
}
|
|
9060
9232
|
} else {
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9233
|
+
for (let i = 0; i < 24; i += 2) {
|
|
9234
|
+
const tuning = (syx[7 + i] << 7 | syx[8 + i]) - 8192;
|
|
9235
|
+
newOctaveTuning[i / 2] = Math.floor(tuning / 81.92);
|
|
9236
|
+
}
|
|
9237
|
+
}
|
|
9238
|
+
if ((syx[4] & 1) === 1) {
|
|
9239
|
+
this.midiChannels[14 + channelOffset].setOctaveTuning(
|
|
9240
|
+
newOctaveTuning
|
|
9064
9241
|
);
|
|
9065
|
-
this.setMasterParameter("midiSystem", "gs");
|
|
9066
9242
|
}
|
|
9243
|
+
if ((syx[4] >> 1 & 1) === 1) {
|
|
9244
|
+
this.midiChannels[15 + channelOffset].setOctaveTuning(
|
|
9245
|
+
newOctaveTuning
|
|
9246
|
+
);
|
|
9247
|
+
}
|
|
9248
|
+
for (let i = 0; i < 7; i++) {
|
|
9249
|
+
const bit = syx[5] >> i & 1;
|
|
9250
|
+
if (bit === 1) {
|
|
9251
|
+
this.midiChannels[7 + i + channelOffset].setOctaveTuning(newOctaveTuning);
|
|
9252
|
+
}
|
|
9253
|
+
}
|
|
9254
|
+
for (let i = 0; i < 7; i++) {
|
|
9255
|
+
const bit = syx[6] >> i & 1;
|
|
9256
|
+
if (bit === 1) {
|
|
9257
|
+
this.midiChannels[i + channelOffset].setOctaveTuning(newOctaveTuning);
|
|
9258
|
+
}
|
|
9259
|
+
}
|
|
9260
|
+
SpessaSynthInfo(
|
|
9261
|
+
`%cMIDI Octave Scale ${syx[3] === 8 ? "(1 byte)" : "(2 bytes)"} tuning via Tuning: %c${newOctaveTuning.join(" ")}`,
|
|
9262
|
+
consoleColors.info,
|
|
9263
|
+
consoleColors.value
|
|
9264
|
+
);
|
|
9067
9265
|
break;
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9084
|
-
|
|
9266
|
+
}
|
|
9267
|
+
default:
|
|
9268
|
+
sysExNotRecognized(syx, "MIDI Tuning Standard");
|
|
9269
|
+
break;
|
|
9270
|
+
}
|
|
9271
|
+
break;
|
|
9272
|
+
}
|
|
9273
|
+
default:
|
|
9274
|
+
sysExNotRecognized(syx, "General MIDI");
|
|
9275
|
+
}
|
|
9276
|
+
}
|
|
9277
|
+
|
|
9278
|
+
// src/synthesizer/audio_engine/engine_methods/system_exclusive/handle_gs.ts
|
|
9279
|
+
function handleGS(syx, channelOffset = 0) {
|
|
9280
|
+
if (syx[3] === 18) {
|
|
9281
|
+
switch (syx[2]) {
|
|
9282
|
+
case 66: {
|
|
9283
|
+
const messageValue = syx[7];
|
|
9284
|
+
if (syx[4] === 64 || syx[4] === 0 && syx[6] === 127) {
|
|
9285
|
+
if ((syx[5] & 16) > 0) {
|
|
9286
|
+
const channel = [
|
|
9287
|
+
9,
|
|
9288
|
+
0,
|
|
9289
|
+
1,
|
|
9290
|
+
2,
|
|
9291
|
+
3,
|
|
9292
|
+
4,
|
|
9293
|
+
5,
|
|
9294
|
+
6,
|
|
9295
|
+
7,
|
|
9296
|
+
8,
|
|
9297
|
+
10,
|
|
9298
|
+
11,
|
|
9299
|
+
12,
|
|
9300
|
+
13,
|
|
9301
|
+
14,
|
|
9302
|
+
15
|
|
9303
|
+
][syx[5] & 15] + channelOffset;
|
|
9304
|
+
const channelObject = this.midiChannels[channel];
|
|
9305
|
+
switch (syx[6]) {
|
|
9306
|
+
default:
|
|
9307
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9308
|
+
break;
|
|
9309
|
+
case 21: {
|
|
9310
|
+
const isDrums = messageValue > 0 && syx[5] >> 4 > 0;
|
|
9311
|
+
channelObject.setGSDrums(isDrums);
|
|
9312
|
+
SpessaSynthInfo(
|
|
9313
|
+
`%cChannel %c${channel}%c ${isDrums ? "is now a drum channel" : "now isn't a drum channel"}%c via: %c${arrayToHexString(syx)}`,
|
|
9314
|
+
consoleColors.info,
|
|
9315
|
+
consoleColors.value,
|
|
9316
|
+
consoleColors.recognized,
|
|
9317
|
+
consoleColors.info,
|
|
9318
|
+
consoleColors.value
|
|
9085
9319
|
);
|
|
9086
9320
|
return;
|
|
9087
9321
|
}
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9322
|
+
case 22: {
|
|
9323
|
+
const keyShift = messageValue - 64;
|
|
9324
|
+
channelObject.setCustomController(
|
|
9325
|
+
customControllers.channelKeyShift,
|
|
9326
|
+
keyShift
|
|
9093
9327
|
);
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
consoleColors.recognized
|
|
9101
|
-
);
|
|
9102
|
-
break;
|
|
9103
|
-
}
|
|
9104
|
-
// Single note change
|
|
9105
|
-
// Single note change bank
|
|
9106
|
-
case 2:
|
|
9107
|
-
case 7: {
|
|
9108
|
-
if (syx[3] === 7) {
|
|
9109
|
-
currentMessageIndex++;
|
|
9110
|
-
}
|
|
9111
|
-
const tuningProgram = syx[currentMessageIndex++];
|
|
9112
|
-
const numberOfChanges = syx[currentMessageIndex++];
|
|
9113
|
-
for (let i = 0; i < numberOfChanges; i++) {
|
|
9114
|
-
this.privateProps.tunings[tuningProgram][syx[currentMessageIndex++]] = getTuning(
|
|
9115
|
-
syx[currentMessageIndex++],
|
|
9116
|
-
syx[currentMessageIndex++],
|
|
9117
|
-
syx[currentMessageIndex++]
|
|
9328
|
+
sysExLogging(
|
|
9329
|
+
syx,
|
|
9330
|
+
channel,
|
|
9331
|
+
keyShift,
|
|
9332
|
+
"key shift",
|
|
9333
|
+
"keys"
|
|
9118
9334
|
);
|
|
9335
|
+
return;
|
|
9119
9336
|
}
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9126
|
-
|
|
9127
|
-
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
}
|
|
9138
|
-
} else {
|
|
9139
|
-
for (let i = 0; i < 24; i += 2) {
|
|
9140
|
-
const tuning = (syx[7 + i] << 7 | syx[8 + i]) - 8192;
|
|
9141
|
-
newOctaveTuning[i / 2] = Math.floor(
|
|
9142
|
-
tuning / 81.92
|
|
9337
|
+
// Pan position
|
|
9338
|
+
case 28: {
|
|
9339
|
+
const panPosition = messageValue;
|
|
9340
|
+
if (panPosition === 0) {
|
|
9341
|
+
channelObject.randomPan = true;
|
|
9342
|
+
SpessaSynthInfo(
|
|
9343
|
+
`%cRandom pan is set to %cON%c for %c${channel}`,
|
|
9344
|
+
consoleColors.info,
|
|
9345
|
+
consoleColors.recognized,
|
|
9346
|
+
consoleColors.info,
|
|
9347
|
+
consoleColors.value
|
|
9348
|
+
);
|
|
9349
|
+
} else {
|
|
9350
|
+
channelObject.randomPan = false;
|
|
9351
|
+
channelObject.controllerChange(
|
|
9352
|
+
midiControllers.pan,
|
|
9353
|
+
panPosition
|
|
9143
9354
|
);
|
|
9144
9355
|
}
|
|
9356
|
+
break;
|
|
9145
9357
|
}
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9358
|
+
// Chorus send
|
|
9359
|
+
case 33:
|
|
9360
|
+
channelObject.controllerChange(
|
|
9361
|
+
midiControllers.chorusDepth,
|
|
9362
|
+
messageValue
|
|
9363
|
+
);
|
|
9364
|
+
break;
|
|
9365
|
+
// Reverb send
|
|
9366
|
+
case 34:
|
|
9367
|
+
channelObject.controllerChange(
|
|
9368
|
+
midiControllers.reverbDepth,
|
|
9369
|
+
messageValue
|
|
9370
|
+
);
|
|
9371
|
+
break;
|
|
9372
|
+
case 64:
|
|
9373
|
+
case 65:
|
|
9374
|
+
case 66:
|
|
9375
|
+
case 67:
|
|
9376
|
+
case 68:
|
|
9377
|
+
case 69:
|
|
9378
|
+
case 70:
|
|
9379
|
+
case 71:
|
|
9380
|
+
case 72:
|
|
9381
|
+
case 73:
|
|
9382
|
+
case 74:
|
|
9383
|
+
case 75: {
|
|
9384
|
+
const tuningBytes = syx.length - 9;
|
|
9385
|
+
const newTuning = new Int8Array(12);
|
|
9386
|
+
for (let i = 0; i < tuningBytes; i++) {
|
|
9387
|
+
newTuning[i] = syx[i + 7] - 64;
|
|
9162
9388
|
}
|
|
9389
|
+
channelObject.setOctaveTuning(newTuning);
|
|
9390
|
+
const cents = messageValue - 64;
|
|
9391
|
+
sysExLogging(
|
|
9392
|
+
syx,
|
|
9393
|
+
channel,
|
|
9394
|
+
newTuning.join(" "),
|
|
9395
|
+
"octave scale tuning",
|
|
9396
|
+
"cents"
|
|
9397
|
+
);
|
|
9398
|
+
channelObject.setTuning(cents);
|
|
9399
|
+
break;
|
|
9163
9400
|
}
|
|
9164
|
-
SpessaSynthInfo(
|
|
9165
|
-
`%cMIDI Octave Scale ${syx[3] === 8 ? "(1 byte)" : "(2 bytes)"} tuning via Tuning: %c${newOctaveTuning.join(" ")}`,
|
|
9166
|
-
consoleColors.info,
|
|
9167
|
-
consoleColors.value
|
|
9168
|
-
);
|
|
9169
|
-
break;
|
|
9170
9401
|
}
|
|
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
|
-
|
|
9199
|
-
consoleColors.warn,
|
|
9200
|
-
consoleColors.unrecognized
|
|
9201
|
-
);
|
|
9202
|
-
};
|
|
9203
|
-
var notRecognized = notRecognized2;
|
|
9204
|
-
switch (syx[2]) {
|
|
9205
|
-
case 66: {
|
|
9206
|
-
const messageValue = syx[7];
|
|
9207
|
-
if (syx[4] === 64 || syx[4] === 0 && syx[6] === 127) {
|
|
9208
|
-
if ((syx[5] & 16) > 0) {
|
|
9209
|
-
const channel = [
|
|
9210
|
-
9,
|
|
9211
|
-
0,
|
|
9212
|
-
1,
|
|
9213
|
-
2,
|
|
9214
|
-
3,
|
|
9215
|
-
4,
|
|
9216
|
-
5,
|
|
9217
|
-
6,
|
|
9218
|
-
7,
|
|
9219
|
-
8,
|
|
9220
|
-
10,
|
|
9221
|
-
11,
|
|
9222
|
-
12,
|
|
9223
|
-
13,
|
|
9224
|
-
14,
|
|
9225
|
-
15
|
|
9226
|
-
][syx[5] & 15] + channelOffset;
|
|
9227
|
-
const channelObject = this.midiChannels[channel];
|
|
9228
|
-
switch (syx[6]) {
|
|
9229
|
-
default:
|
|
9230
|
-
notRecognized2();
|
|
9231
|
-
break;
|
|
9232
|
-
case 21: {
|
|
9233
|
-
const isDrums = messageValue > 0 && syx[5] >> 4 > 0;
|
|
9234
|
-
channelObject.setGSDrums(isDrums);
|
|
9235
|
-
SpessaSynthInfo(
|
|
9236
|
-
`%cChannel %c${channel}%c ${isDrums ? "is now a drum channel" : "now isn't a drum channel"}%c via: %c${arrayToHexString(syx)}`,
|
|
9237
|
-
consoleColors.info,
|
|
9238
|
-
consoleColors.value,
|
|
9239
|
-
consoleColors.recognized,
|
|
9240
|
-
consoleColors.info,
|
|
9241
|
-
consoleColors.value
|
|
9242
|
-
);
|
|
9243
|
-
return;
|
|
9244
|
-
}
|
|
9245
|
-
case 22: {
|
|
9246
|
-
const keyShift = messageValue - 64;
|
|
9247
|
-
channelObject.setCustomController(
|
|
9248
|
-
customControllers.channelKeyShift,
|
|
9249
|
-
keyShift
|
|
9250
|
-
);
|
|
9251
|
-
niceLogging(
|
|
9252
|
-
channel,
|
|
9253
|
-
keyShift,
|
|
9254
|
-
"key shift",
|
|
9255
|
-
"keys"
|
|
9256
|
-
);
|
|
9257
|
-
return;
|
|
9258
|
-
}
|
|
9259
|
-
// Pan position
|
|
9260
|
-
case 28: {
|
|
9261
|
-
const panPosition = messageValue;
|
|
9262
|
-
if (panPosition === 0) {
|
|
9263
|
-
channelObject.randomPan = true;
|
|
9264
|
-
SpessaSynthInfo(
|
|
9265
|
-
`%cRandom pan is set to %cON%c for %c${channel}`,
|
|
9266
|
-
consoleColors.info,
|
|
9267
|
-
consoleColors.recognized,
|
|
9268
|
-
consoleColors.info,
|
|
9269
|
-
consoleColors.value
|
|
9270
|
-
);
|
|
9271
|
-
} else {
|
|
9272
|
-
channelObject.randomPan = false;
|
|
9273
|
-
channelObject.controllerChange(
|
|
9274
|
-
midiControllers.pan,
|
|
9275
|
-
panPosition
|
|
9276
|
-
);
|
|
9277
|
-
}
|
|
9278
|
-
break;
|
|
9279
|
-
}
|
|
9280
|
-
// Chorus send
|
|
9281
|
-
case 33:
|
|
9402
|
+
return;
|
|
9403
|
+
} else if ((syx[5] & 32) > 0) {
|
|
9404
|
+
const channel = [
|
|
9405
|
+
9,
|
|
9406
|
+
0,
|
|
9407
|
+
1,
|
|
9408
|
+
2,
|
|
9409
|
+
3,
|
|
9410
|
+
4,
|
|
9411
|
+
5,
|
|
9412
|
+
6,
|
|
9413
|
+
7,
|
|
9414
|
+
8,
|
|
9415
|
+
10,
|
|
9416
|
+
11,
|
|
9417
|
+
12,
|
|
9418
|
+
13,
|
|
9419
|
+
14,
|
|
9420
|
+
15
|
|
9421
|
+
][syx[5] & 15] + channelOffset;
|
|
9422
|
+
const channelObject = this.midiChannels[channel];
|
|
9423
|
+
const centeredValue = messageValue - 64;
|
|
9424
|
+
const normalizedValue = centeredValue / 64;
|
|
9425
|
+
const normalizedNotCentered = messageValue / 128;
|
|
9426
|
+
const setupReceivers = (source, sourceName, bipolar = false) => {
|
|
9427
|
+
switch (syx[6] & 15) {
|
|
9428
|
+
case 0:
|
|
9429
|
+
if (source === NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel) {
|
|
9282
9430
|
channelObject.controllerChange(
|
|
9283
|
-
midiControllers.
|
|
9284
|
-
|
|
9431
|
+
midiControllers.registeredParameterMSB,
|
|
9432
|
+
0
|
|
9285
9433
|
);
|
|
9286
|
-
break;
|
|
9287
|
-
// Reverb send
|
|
9288
|
-
case 34:
|
|
9289
9434
|
channelObject.controllerChange(
|
|
9290
|
-
midiControllers.
|
|
9291
|
-
|
|
9292
|
-
);
|
|
9293
|
-
break;
|
|
9294
|
-
case 64:
|
|
9295
|
-
case 65:
|
|
9296
|
-
case 66:
|
|
9297
|
-
case 67:
|
|
9298
|
-
case 68:
|
|
9299
|
-
case 69:
|
|
9300
|
-
case 70:
|
|
9301
|
-
case 71:
|
|
9302
|
-
case 72:
|
|
9303
|
-
case 73:
|
|
9304
|
-
case 74:
|
|
9305
|
-
case 75: {
|
|
9306
|
-
const tuningBytes = syx.length - 9;
|
|
9307
|
-
const newTuning = new Int8Array(12);
|
|
9308
|
-
for (let i = 0; i < tuningBytes; i++) {
|
|
9309
|
-
newTuning[i] = syx[i + 7] - 64;
|
|
9310
|
-
}
|
|
9311
|
-
channelObject.setOctaveTuning(
|
|
9312
|
-
newTuning
|
|
9313
|
-
);
|
|
9314
|
-
const cents = messageValue - 64;
|
|
9315
|
-
niceLogging(
|
|
9316
|
-
channel,
|
|
9317
|
-
newTuning.join(" "),
|
|
9318
|
-
"octave scale tuning",
|
|
9319
|
-
"cents"
|
|
9320
|
-
);
|
|
9321
|
-
channelObject.setTuning(cents);
|
|
9322
|
-
break;
|
|
9323
|
-
}
|
|
9324
|
-
}
|
|
9325
|
-
return;
|
|
9326
|
-
} else if ((syx[5] & 32) > 0) {
|
|
9327
|
-
const channel = [
|
|
9328
|
-
9,
|
|
9329
|
-
0,
|
|
9330
|
-
1,
|
|
9331
|
-
2,
|
|
9332
|
-
3,
|
|
9333
|
-
4,
|
|
9334
|
-
5,
|
|
9335
|
-
6,
|
|
9336
|
-
7,
|
|
9337
|
-
8,
|
|
9338
|
-
10,
|
|
9339
|
-
11,
|
|
9340
|
-
12,
|
|
9341
|
-
13,
|
|
9342
|
-
14,
|
|
9343
|
-
15
|
|
9344
|
-
][syx[5] & 15] + channelOffset;
|
|
9345
|
-
const channelObject = this.midiChannels[channel];
|
|
9346
|
-
const centeredValue = messageValue - 64;
|
|
9347
|
-
const normalizedValue = centeredValue / 64;
|
|
9348
|
-
const normalizedNotCentered = messageValue / 128;
|
|
9349
|
-
const setupReceivers = (source, sourceName, bipolar = false) => {
|
|
9350
|
-
switch (syx[6] & 15) {
|
|
9351
|
-
case 0:
|
|
9352
|
-
if (source === NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel) {
|
|
9353
|
-
channelObject.controllerChange(
|
|
9354
|
-
midiControllers.registeredParameterMSB,
|
|
9355
|
-
0
|
|
9356
|
-
);
|
|
9357
|
-
channelObject.controllerChange(
|
|
9358
|
-
midiControllers.registeredParameterLSB,
|
|
9359
|
-
0
|
|
9360
|
-
);
|
|
9361
|
-
channelObject.controllerChange(
|
|
9362
|
-
midiControllers.dataEntryMSB,
|
|
9363
|
-
Math.floor(centeredValue)
|
|
9364
|
-
);
|
|
9365
|
-
} else {
|
|
9366
|
-
channelObject.sysExModulators.setModulator(
|
|
9367
|
-
source,
|
|
9368
|
-
generatorTypes.fineTune,
|
|
9369
|
-
centeredValue * 100,
|
|
9370
|
-
bipolar
|
|
9371
|
-
);
|
|
9372
|
-
niceLogging(
|
|
9373
|
-
channel,
|
|
9374
|
-
centeredValue,
|
|
9375
|
-
`${sourceName} pitch control`,
|
|
9376
|
-
"semitones"
|
|
9377
|
-
);
|
|
9378
|
-
}
|
|
9379
|
-
break;
|
|
9380
|
-
case 1:
|
|
9381
|
-
channelObject.sysExModulators.setModulator(
|
|
9382
|
-
source,
|
|
9383
|
-
generatorTypes.initialFilterFc,
|
|
9384
|
-
normalizedValue * 9600,
|
|
9385
|
-
bipolar
|
|
9386
|
-
);
|
|
9387
|
-
niceLogging(
|
|
9388
|
-
channel,
|
|
9389
|
-
normalizedValue * 9600,
|
|
9390
|
-
`${sourceName} pitch control`,
|
|
9391
|
-
"cents"
|
|
9392
|
-
);
|
|
9393
|
-
break;
|
|
9394
|
-
case 2:
|
|
9395
|
-
channelObject.sysExModulators.setModulator(
|
|
9396
|
-
source,
|
|
9397
|
-
generatorTypes.initialAttenuation,
|
|
9398
|
-
normalizedValue * 960,
|
|
9399
|
-
// Spec says "100%" so 960cB in sf2
|
|
9400
|
-
bipolar
|
|
9401
|
-
);
|
|
9402
|
-
niceLogging(
|
|
9403
|
-
channel,
|
|
9404
|
-
normalizedValue * 960,
|
|
9405
|
-
`${sourceName} amplitude`,
|
|
9406
|
-
"cB"
|
|
9407
|
-
);
|
|
9408
|
-
break;
|
|
9409
|
-
// Rate control is ignored as it is in hertz
|
|
9410
|
-
case 4:
|
|
9411
|
-
channelObject.sysExModulators.setModulator(
|
|
9412
|
-
source,
|
|
9413
|
-
generatorTypes.vibLfoToPitch,
|
|
9414
|
-
normalizedNotCentered * 600,
|
|
9415
|
-
bipolar
|
|
9416
|
-
);
|
|
9417
|
-
niceLogging(
|
|
9418
|
-
channel,
|
|
9419
|
-
normalizedNotCentered * 600,
|
|
9420
|
-
`${sourceName} LFO1 pitch depth`,
|
|
9421
|
-
"cents"
|
|
9422
|
-
);
|
|
9423
|
-
break;
|
|
9424
|
-
case 5:
|
|
9425
|
-
channelObject.sysExModulators.setModulator(
|
|
9426
|
-
source,
|
|
9427
|
-
generatorTypes.vibLfoToFilterFc,
|
|
9428
|
-
normalizedNotCentered * 2400,
|
|
9429
|
-
bipolar
|
|
9430
|
-
);
|
|
9431
|
-
niceLogging(
|
|
9432
|
-
channel,
|
|
9433
|
-
normalizedNotCentered * 2400,
|
|
9434
|
-
`${sourceName} LFO1 filter depth`,
|
|
9435
|
-
"cents"
|
|
9436
|
-
);
|
|
9437
|
-
break;
|
|
9438
|
-
case 6:
|
|
9439
|
-
channelObject.sysExModulators.setModulator(
|
|
9440
|
-
source,
|
|
9441
|
-
generatorTypes.vibLfoToVolume,
|
|
9442
|
-
normalizedValue * 960,
|
|
9443
|
-
bipolar
|
|
9444
|
-
);
|
|
9445
|
-
niceLogging(
|
|
9446
|
-
channel,
|
|
9447
|
-
normalizedValue * 960,
|
|
9448
|
-
`${sourceName} LFO1 amplitude depth`,
|
|
9449
|
-
"cB"
|
|
9450
|
-
);
|
|
9451
|
-
break;
|
|
9452
|
-
// Rate control is ignored as it is in hertz
|
|
9453
|
-
case 8:
|
|
9454
|
-
channelObject.sysExModulators.setModulator(
|
|
9455
|
-
source,
|
|
9456
|
-
generatorTypes.modLfoToPitch,
|
|
9457
|
-
normalizedNotCentered * 600,
|
|
9458
|
-
bipolar
|
|
9459
|
-
);
|
|
9460
|
-
niceLogging(
|
|
9461
|
-
channel,
|
|
9462
|
-
normalizedNotCentered * 600,
|
|
9463
|
-
`${sourceName} LFO2 pitch depth`,
|
|
9464
|
-
"cents"
|
|
9465
|
-
);
|
|
9466
|
-
break;
|
|
9467
|
-
case 9:
|
|
9468
|
-
channelObject.sysExModulators.setModulator(
|
|
9469
|
-
source,
|
|
9470
|
-
generatorTypes.modLfoToFilterFc,
|
|
9471
|
-
normalizedNotCentered * 2400,
|
|
9472
|
-
bipolar
|
|
9473
|
-
);
|
|
9474
|
-
niceLogging(
|
|
9475
|
-
channel,
|
|
9476
|
-
normalizedNotCentered * 2400,
|
|
9477
|
-
`${sourceName} LFO2 filter depth`,
|
|
9478
|
-
"cents"
|
|
9479
|
-
);
|
|
9480
|
-
break;
|
|
9481
|
-
case 10:
|
|
9482
|
-
channelObject.sysExModulators.setModulator(
|
|
9483
|
-
source,
|
|
9484
|
-
generatorTypes.modLfoToVolume,
|
|
9485
|
-
normalizedValue * 960,
|
|
9486
|
-
bipolar
|
|
9487
|
-
);
|
|
9488
|
-
niceLogging(
|
|
9489
|
-
channel,
|
|
9490
|
-
normalizedValue * 960,
|
|
9491
|
-
`${sourceName} LFO2 amplitude depth`,
|
|
9492
|
-
"cB"
|
|
9493
|
-
);
|
|
9494
|
-
break;
|
|
9495
|
-
}
|
|
9496
|
-
};
|
|
9497
|
-
switch (syx[6] & 240) {
|
|
9498
|
-
default:
|
|
9499
|
-
notRecognized2();
|
|
9500
|
-
break;
|
|
9501
|
-
case 0:
|
|
9502
|
-
setupReceivers(
|
|
9503
|
-
midiControllers.modulationWheel,
|
|
9504
|
-
"mod wheel"
|
|
9505
|
-
);
|
|
9506
|
-
break;
|
|
9507
|
-
case 16:
|
|
9508
|
-
setupReceivers(
|
|
9509
|
-
NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel,
|
|
9510
|
-
"pitch wheel",
|
|
9511
|
-
true
|
|
9435
|
+
midiControllers.registeredParameterLSB,
|
|
9436
|
+
0
|
|
9512
9437
|
);
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
NON_CC_INDEX_OFFSET + modulatorSources.channelPressure,
|
|
9517
|
-
"channel pressure"
|
|
9518
|
-
);
|
|
9519
|
-
break;
|
|
9520
|
-
case 48:
|
|
9521
|
-
setupReceivers(
|
|
9522
|
-
NON_CC_INDEX_OFFSET + modulatorSources.polyPressure,
|
|
9523
|
-
"poly pressure"
|
|
9524
|
-
);
|
|
9525
|
-
break;
|
|
9526
|
-
}
|
|
9527
|
-
return;
|
|
9528
|
-
} else if (syx[5] === 0) {
|
|
9529
|
-
switch (syx[6]) {
|
|
9530
|
-
default:
|
|
9531
|
-
notRecognized2();
|
|
9532
|
-
break;
|
|
9533
|
-
case 127:
|
|
9534
|
-
if (messageValue === 0) {
|
|
9535
|
-
SpessaSynthInfo(
|
|
9536
|
-
"%cGS Reset received!",
|
|
9537
|
-
consoleColors.info
|
|
9538
|
-
);
|
|
9539
|
-
this.resetAllControllers(false);
|
|
9540
|
-
this.setMasterParameter(
|
|
9541
|
-
"midiSystem",
|
|
9542
|
-
"gs"
|
|
9543
|
-
);
|
|
9544
|
-
} else if (messageValue === 127) {
|
|
9545
|
-
SpessaSynthInfo(
|
|
9546
|
-
"%cGS system off, switching to GM",
|
|
9547
|
-
consoleColors.info
|
|
9548
|
-
);
|
|
9549
|
-
this.resetAllControllers(false);
|
|
9550
|
-
this.setMasterParameter(
|
|
9551
|
-
"midiSystem",
|
|
9552
|
-
"gm"
|
|
9553
|
-
);
|
|
9554
|
-
}
|
|
9555
|
-
break;
|
|
9556
|
-
case 6:
|
|
9557
|
-
SpessaSynthInfo(
|
|
9558
|
-
`%cRoland GS Master Pan set to: %c${messageValue}%c with: %c${arrayToHexString(
|
|
9559
|
-
syx
|
|
9560
|
-
)}`,
|
|
9561
|
-
consoleColors.info,
|
|
9562
|
-
consoleColors.value,
|
|
9563
|
-
consoleColors.info,
|
|
9564
|
-
consoleColors.value
|
|
9565
|
-
);
|
|
9566
|
-
this.setMasterParameter(
|
|
9567
|
-
"masterPan",
|
|
9568
|
-
(messageValue - 64) / 64
|
|
9569
|
-
);
|
|
9570
|
-
break;
|
|
9571
|
-
case 4:
|
|
9572
|
-
SpessaSynthInfo(
|
|
9573
|
-
`%cRoland GS Master Volume set to: %c${messageValue}%c with: %c${arrayToHexString(
|
|
9574
|
-
syx
|
|
9575
|
-
)}`,
|
|
9576
|
-
consoleColors.info,
|
|
9577
|
-
consoleColors.value,
|
|
9578
|
-
consoleColors.info,
|
|
9579
|
-
consoleColors.value
|
|
9438
|
+
channelObject.controllerChange(
|
|
9439
|
+
midiControllers.dataEntryMSB,
|
|
9440
|
+
Math.floor(centeredValue)
|
|
9580
9441
|
);
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
syx
|
|
9588
|
-
)}`,
|
|
9589
|
-
consoleColors.info,
|
|
9590
|
-
consoleColors.value,
|
|
9591
|
-
consoleColors.info,
|
|
9592
|
-
consoleColors.value
|
|
9442
|
+
} else {
|
|
9443
|
+
channelObject.sysExModulators.setModulator(
|
|
9444
|
+
source,
|
|
9445
|
+
generatorTypes.fineTune,
|
|
9446
|
+
centeredValue * 100,
|
|
9447
|
+
bipolar
|
|
9593
9448
|
);
|
|
9594
|
-
|
|
9595
|
-
break;
|
|
9596
|
-
}
|
|
9597
|
-
}
|
|
9598
|
-
return;
|
|
9599
|
-
} else if (syx[5] === 1) {
|
|
9600
|
-
switch (syx[6]) {
|
|
9601
|
-
default:
|
|
9602
|
-
notRecognized2();
|
|
9603
|
-
break;
|
|
9604
|
-
case 0: {
|
|
9605
|
-
const patchName = readBinaryString(
|
|
9449
|
+
sysExLogging(
|
|
9606
9450
|
syx,
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
`%cGS Patch name: %c${patchName}`,
|
|
9612
|
-
consoleColors.info,
|
|
9613
|
-
consoleColors.value
|
|
9451
|
+
channel,
|
|
9452
|
+
centeredValue,
|
|
9453
|
+
`${sourceName} pitch control`,
|
|
9454
|
+
"semitones"
|
|
9614
9455
|
);
|
|
9615
|
-
break;
|
|
9616
9456
|
}
|
|
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
|
-
|
|
9661
|
-
|
|
9457
|
+
break;
|
|
9458
|
+
case 1:
|
|
9459
|
+
channelObject.sysExModulators.setModulator(
|
|
9460
|
+
source,
|
|
9461
|
+
generatorTypes.initialFilterFc,
|
|
9462
|
+
normalizedValue * 9600,
|
|
9463
|
+
bipolar
|
|
9464
|
+
);
|
|
9465
|
+
sysExLogging(
|
|
9466
|
+
syx,
|
|
9467
|
+
channel,
|
|
9468
|
+
normalizedValue * 9600,
|
|
9469
|
+
`${sourceName} pitch control`,
|
|
9470
|
+
"cents"
|
|
9471
|
+
);
|
|
9472
|
+
break;
|
|
9473
|
+
case 2:
|
|
9474
|
+
channelObject.sysExModulators.setModulator(
|
|
9475
|
+
source,
|
|
9476
|
+
generatorTypes.initialAttenuation,
|
|
9477
|
+
normalizedValue * 960,
|
|
9478
|
+
// Spec says "100%" so 960cB in sf2
|
|
9479
|
+
bipolar
|
|
9480
|
+
);
|
|
9481
|
+
sysExLogging(
|
|
9482
|
+
syx,
|
|
9483
|
+
channel,
|
|
9484
|
+
normalizedValue * 960,
|
|
9485
|
+
`${sourceName} amplitude`,
|
|
9486
|
+
"cB"
|
|
9487
|
+
);
|
|
9488
|
+
break;
|
|
9489
|
+
// Rate control is ignored as it is in hertz
|
|
9490
|
+
case 4:
|
|
9491
|
+
channelObject.sysExModulators.setModulator(
|
|
9492
|
+
source,
|
|
9493
|
+
generatorTypes.vibLfoToPitch,
|
|
9494
|
+
normalizedNotCentered * 600,
|
|
9495
|
+
bipolar
|
|
9496
|
+
);
|
|
9497
|
+
sysExLogging(
|
|
9498
|
+
syx,
|
|
9499
|
+
channel,
|
|
9500
|
+
normalizedNotCentered * 600,
|
|
9501
|
+
`${sourceName} LFO1 pitch depth`,
|
|
9502
|
+
"cents"
|
|
9503
|
+
);
|
|
9504
|
+
break;
|
|
9505
|
+
case 5:
|
|
9506
|
+
channelObject.sysExModulators.setModulator(
|
|
9507
|
+
source,
|
|
9508
|
+
generatorTypes.vibLfoToFilterFc,
|
|
9509
|
+
normalizedNotCentered * 2400,
|
|
9510
|
+
bipolar
|
|
9511
|
+
);
|
|
9512
|
+
sysExLogging(
|
|
9513
|
+
syx,
|
|
9514
|
+
channel,
|
|
9515
|
+
normalizedNotCentered * 2400,
|
|
9516
|
+
`${sourceName} LFO1 filter depth`,
|
|
9517
|
+
"cents"
|
|
9518
|
+
);
|
|
9519
|
+
break;
|
|
9520
|
+
case 6:
|
|
9521
|
+
channelObject.sysExModulators.setModulator(
|
|
9522
|
+
source,
|
|
9523
|
+
generatorTypes.vibLfoToVolume,
|
|
9524
|
+
normalizedValue * 960,
|
|
9525
|
+
bipolar
|
|
9526
|
+
);
|
|
9527
|
+
sysExLogging(
|
|
9528
|
+
syx,
|
|
9529
|
+
channel,
|
|
9530
|
+
normalizedValue * 960,
|
|
9531
|
+
`${sourceName} LFO1 amplitude depth`,
|
|
9532
|
+
"cB"
|
|
9533
|
+
);
|
|
9534
|
+
break;
|
|
9535
|
+
// Rate control is ignored as it is in hertz
|
|
9536
|
+
case 8:
|
|
9537
|
+
channelObject.sysExModulators.setModulator(
|
|
9538
|
+
source,
|
|
9539
|
+
generatorTypes.modLfoToPitch,
|
|
9540
|
+
normalizedNotCentered * 600,
|
|
9541
|
+
bipolar
|
|
9542
|
+
);
|
|
9543
|
+
sysExLogging(
|
|
9544
|
+
syx,
|
|
9545
|
+
channel,
|
|
9546
|
+
normalizedNotCentered * 600,
|
|
9547
|
+
`${sourceName} LFO2 pitch depth`,
|
|
9548
|
+
"cents"
|
|
9549
|
+
);
|
|
9550
|
+
break;
|
|
9551
|
+
case 9:
|
|
9552
|
+
channelObject.sysExModulators.setModulator(
|
|
9553
|
+
source,
|
|
9554
|
+
generatorTypes.modLfoToFilterFc,
|
|
9555
|
+
normalizedNotCentered * 2400,
|
|
9556
|
+
bipolar
|
|
9557
|
+
);
|
|
9558
|
+
sysExLogging(
|
|
9559
|
+
syx,
|
|
9560
|
+
channel,
|
|
9561
|
+
normalizedNotCentered * 2400,
|
|
9562
|
+
`${sourceName} LFO2 filter depth`,
|
|
9563
|
+
"cents"
|
|
9564
|
+
);
|
|
9565
|
+
break;
|
|
9566
|
+
case 10:
|
|
9567
|
+
channelObject.sysExModulators.setModulator(
|
|
9568
|
+
source,
|
|
9569
|
+
generatorTypes.modLfoToVolume,
|
|
9570
|
+
normalizedValue * 960,
|
|
9571
|
+
bipolar
|
|
9572
|
+
);
|
|
9573
|
+
sysExLogging(
|
|
9574
|
+
syx,
|
|
9575
|
+
channel,
|
|
9576
|
+
normalizedValue * 960,
|
|
9577
|
+
`${sourceName} LFO2 amplitude depth`,
|
|
9578
|
+
"cB"
|
|
9579
|
+
);
|
|
9580
|
+
break;
|
|
9662
9581
|
}
|
|
9663
|
-
}
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
"synthDisplay",
|
|
9673
|
-
Array.from(syx)
|
|
9582
|
+
};
|
|
9583
|
+
switch (syx[6] & 240) {
|
|
9584
|
+
default:
|
|
9585
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9586
|
+
break;
|
|
9587
|
+
case 0:
|
|
9588
|
+
setupReceivers(
|
|
9589
|
+
midiControllers.modulationWheel,
|
|
9590
|
+
"mod wheel"
|
|
9674
9591
|
);
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9592
|
+
break;
|
|
9593
|
+
case 16:
|
|
9594
|
+
setupReceivers(
|
|
9595
|
+
NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel,
|
|
9596
|
+
"pitch wheel",
|
|
9597
|
+
true
|
|
9679
9598
|
);
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
consoleColors.value,
|
|
9695
|
-
consoleColors.info,
|
|
9696
|
-
consoleColors.value
|
|
9697
|
-
);
|
|
9698
|
-
return;
|
|
9699
|
-
}
|
|
9700
|
-
}
|
|
9701
|
-
} else {
|
|
9702
|
-
SpessaSynthInfo(
|
|
9703
|
-
`%cUnrecognized Roland SysEx: %c${arrayToHexString(syx)}`,
|
|
9704
|
-
consoleColors.warn,
|
|
9705
|
-
consoleColors.unrecognized
|
|
9706
|
-
);
|
|
9707
|
-
return;
|
|
9708
|
-
}
|
|
9709
|
-
break;
|
|
9710
|
-
// Yamaha
|
|
9711
|
-
// http://www.studio4all.de/htmle/main91.html
|
|
9712
|
-
case 67:
|
|
9713
|
-
if (syx[2] === 76) {
|
|
9714
|
-
if (syx[3] === 0 && syx[4] === 0) {
|
|
9715
|
-
switch (syx[5]) {
|
|
9716
|
-
// Master volume
|
|
9717
|
-
case 4: {
|
|
9718
|
-
const vol = syx[6];
|
|
9719
|
-
this.setMIDIVolume(vol / 127);
|
|
9720
|
-
SpessaSynthInfo(
|
|
9721
|
-
`%cXG master volume. Volume: %c${vol}`,
|
|
9722
|
-
consoleColors.info,
|
|
9723
|
-
consoleColors.recognized
|
|
9724
|
-
);
|
|
9725
|
-
break;
|
|
9726
|
-
}
|
|
9727
|
-
// Master transpose
|
|
9728
|
-
case 6: {
|
|
9729
|
-
const transpose = syx[6] - 64;
|
|
9730
|
-
this.setMasterParameter("transposition", transpose);
|
|
9731
|
-
SpessaSynthInfo(
|
|
9732
|
-
`%cXG master transpose. Volume: %c${transpose}`,
|
|
9733
|
-
consoleColors.info,
|
|
9734
|
-
consoleColors.recognized
|
|
9735
|
-
);
|
|
9736
|
-
break;
|
|
9737
|
-
}
|
|
9738
|
-
// XG on
|
|
9739
|
-
case 126:
|
|
9740
|
-
SpessaSynthInfo(
|
|
9741
|
-
"%cXG system on",
|
|
9742
|
-
consoleColors.info
|
|
9743
|
-
);
|
|
9744
|
-
this.resetAllControllers(false);
|
|
9745
|
-
this.setMasterParameter("midiSystem", "xg");
|
|
9746
|
-
break;
|
|
9747
|
-
}
|
|
9748
|
-
} else if (syx[3] === 8) {
|
|
9749
|
-
if (!BankSelectHacks.isSystemXG(
|
|
9750
|
-
this.privateProps.masterParameters.midiSystem
|
|
9751
|
-
)) {
|
|
9752
|
-
return;
|
|
9753
|
-
}
|
|
9754
|
-
const channel = syx[4] + channelOffset;
|
|
9755
|
-
if (channel >= this.midiChannels.length) {
|
|
9599
|
+
break;
|
|
9600
|
+
case 32:
|
|
9601
|
+
setupReceivers(
|
|
9602
|
+
NON_CC_INDEX_OFFSET + modulatorSources.channelPressure,
|
|
9603
|
+
"channel pressure"
|
|
9604
|
+
);
|
|
9605
|
+
break;
|
|
9606
|
+
case 48:
|
|
9607
|
+
setupReceivers(
|
|
9608
|
+
NON_CC_INDEX_OFFSET + modulatorSources.polyPressure,
|
|
9609
|
+
"poly pressure"
|
|
9610
|
+
);
|
|
9611
|
+
break;
|
|
9612
|
+
}
|
|
9756
9613
|
return;
|
|
9757
|
-
}
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
|
|
9775
|
-
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
|
|
9780
|
-
|
|
9781
|
-
|
|
9782
|
-
|
|
9614
|
+
} else if (syx[5] === 0) {
|
|
9615
|
+
switch (syx[6]) {
|
|
9616
|
+
default:
|
|
9617
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9618
|
+
break;
|
|
9619
|
+
case 127:
|
|
9620
|
+
if (messageValue === 0) {
|
|
9621
|
+
SpessaSynthInfo(
|
|
9622
|
+
"%cGS Reset received!",
|
|
9623
|
+
consoleColors.info
|
|
9624
|
+
);
|
|
9625
|
+
this.resetAllControllers("gs");
|
|
9626
|
+
} else if (messageValue === 127) {
|
|
9627
|
+
SpessaSynthInfo(
|
|
9628
|
+
"%cGS system off, switching to GM",
|
|
9629
|
+
consoleColors.info
|
|
9630
|
+
);
|
|
9631
|
+
this.resetAllControllers("gm");
|
|
9632
|
+
}
|
|
9633
|
+
break;
|
|
9634
|
+
case 6:
|
|
9635
|
+
SpessaSynthInfo(
|
|
9636
|
+
`%cRoland GS Master Pan set to: %c${messageValue}%c with: %c${arrayToHexString(
|
|
9637
|
+
syx
|
|
9638
|
+
)}`,
|
|
9639
|
+
consoleColors.info,
|
|
9640
|
+
consoleColors.value,
|
|
9641
|
+
consoleColors.info,
|
|
9642
|
+
consoleColors.value
|
|
9643
|
+
);
|
|
9644
|
+
this.setMasterParameter(
|
|
9645
|
+
"masterPan",
|
|
9646
|
+
(messageValue - 64) / 64
|
|
9647
|
+
);
|
|
9648
|
+
break;
|
|
9649
|
+
case 4:
|
|
9650
|
+
SpessaSynthInfo(
|
|
9651
|
+
`%cRoland GS Master Volume set to: %c${messageValue}%c with: %c${arrayToHexString(
|
|
9652
|
+
syx
|
|
9653
|
+
)}`,
|
|
9654
|
+
consoleColors.info,
|
|
9655
|
+
consoleColors.value,
|
|
9656
|
+
consoleColors.info,
|
|
9657
|
+
consoleColors.value
|
|
9658
|
+
);
|
|
9659
|
+
this.setMIDIVolume(messageValue / 127);
|
|
9660
|
+
break;
|
|
9661
|
+
case 5: {
|
|
9662
|
+
const transpose = messageValue - 64;
|
|
9663
|
+
SpessaSynthInfo(
|
|
9664
|
+
`%cRoland GS Master Key-Shift set to: %c${transpose}%c with: %c${arrayToHexString(
|
|
9665
|
+
syx
|
|
9666
|
+
)}`,
|
|
9667
|
+
consoleColors.info,
|
|
9668
|
+
consoleColors.value,
|
|
9669
|
+
consoleColors.info,
|
|
9670
|
+
consoleColors.value
|
|
9671
|
+
);
|
|
9672
|
+
this.setMasterTuning(transpose * 100);
|
|
9673
|
+
break;
|
|
9783
9674
|
}
|
|
9784
|
-
channelObject.channelTransposeKeyShift = value - 64;
|
|
9785
|
-
break;
|
|
9786
9675
|
}
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
case 14: {
|
|
9796
|
-
const pan = value;
|
|
9797
|
-
if (pan === 0) {
|
|
9798
|
-
channelObject.randomPan = true;
|
|
9676
|
+
return;
|
|
9677
|
+
} else if (syx[5] === 1) {
|
|
9678
|
+
switch (syx[6]) {
|
|
9679
|
+
default:
|
|
9680
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9681
|
+
break;
|
|
9682
|
+
case 0: {
|
|
9683
|
+
const patchName = readBinaryString(syx, 16, 7);
|
|
9799
9684
|
SpessaSynthInfo(
|
|
9800
|
-
`%
|
|
9685
|
+
`%cGS Patch name: %c${patchName}`,
|
|
9801
9686
|
consoleColors.info,
|
|
9802
|
-
consoleColors.
|
|
9687
|
+
consoleColors.value
|
|
9688
|
+
);
|
|
9689
|
+
break;
|
|
9690
|
+
}
|
|
9691
|
+
case 51:
|
|
9692
|
+
SpessaSynthInfo(
|
|
9693
|
+
`%cGS Reverb level: %c${messageValue}`,
|
|
9803
9694
|
consoleColors.info,
|
|
9804
9695
|
consoleColors.value
|
|
9805
9696
|
);
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9697
|
+
this.privateProps.reverbSend = messageValue / 64;
|
|
9698
|
+
break;
|
|
9699
|
+
// Unsupported reverb params
|
|
9700
|
+
case 48:
|
|
9701
|
+
case 49:
|
|
9702
|
+
case 50:
|
|
9703
|
+
case 52:
|
|
9704
|
+
case 53:
|
|
9705
|
+
case 55:
|
|
9706
|
+
SpessaSynthInfo(
|
|
9707
|
+
`%cUnsupported GS Reverb Parameter: %c${syx[6].toString(16)}`,
|
|
9708
|
+
consoleColors.warn,
|
|
9709
|
+
consoleColors.unrecognized
|
|
9810
9710
|
);
|
|
9811
|
-
|
|
9812
|
-
|
|
9711
|
+
break;
|
|
9712
|
+
case 58:
|
|
9713
|
+
SpessaSynthInfo(
|
|
9714
|
+
`%cGS Chorus level: %c${messageValue}`,
|
|
9715
|
+
consoleColors.info,
|
|
9716
|
+
consoleColors.value
|
|
9717
|
+
);
|
|
9718
|
+
this.privateProps.chorusSend = messageValue / 64;
|
|
9719
|
+
break;
|
|
9720
|
+
// Unsupported chorus params
|
|
9721
|
+
case 56:
|
|
9722
|
+
case 57:
|
|
9723
|
+
case 59:
|
|
9724
|
+
case 60:
|
|
9725
|
+
case 61:
|
|
9726
|
+
case 62:
|
|
9727
|
+
case 63:
|
|
9728
|
+
case 64:
|
|
9729
|
+
SpessaSynthInfo(
|
|
9730
|
+
`%cUnsupported GS Chorus Parameter: %c${syx[6].toString(16)}`,
|
|
9731
|
+
consoleColors.warn,
|
|
9732
|
+
consoleColors.unrecognized
|
|
9733
|
+
);
|
|
9734
|
+
break;
|
|
9813
9735
|
}
|
|
9814
|
-
// Reverb
|
|
9815
|
-
case 19:
|
|
9816
|
-
channelObject.controllerChange(
|
|
9817
|
-
midiControllers.reverbDepth,
|
|
9818
|
-
value
|
|
9819
|
-
);
|
|
9820
|
-
break;
|
|
9821
|
-
// Chorus
|
|
9822
|
-
case 18:
|
|
9823
|
-
channelObject.controllerChange(
|
|
9824
|
-
midiControllers.chorusDepth,
|
|
9825
|
-
value
|
|
9826
|
-
);
|
|
9827
|
-
break;
|
|
9828
|
-
default:
|
|
9829
|
-
SpessaSynthInfo(
|
|
9830
|
-
`%cUnrecognized Yamaha XG Part Setup: %c${syx[5].toString(16).toUpperCase()}`,
|
|
9831
|
-
consoleColors.warn,
|
|
9832
|
-
consoleColors.unrecognized
|
|
9833
|
-
);
|
|
9834
9736
|
}
|
|
9835
|
-
} else
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9737
|
+
} else {
|
|
9738
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9739
|
+
}
|
|
9740
|
+
return;
|
|
9741
|
+
}
|
|
9742
|
+
case 69: {
|
|
9743
|
+
if (syx[4] === 16) {
|
|
9744
|
+
if (syx[5] === 0) {
|
|
9745
|
+
this.privateProps.callEvent(
|
|
9746
|
+
"synthDisplay",
|
|
9747
|
+
Array.from(syx)
|
|
9748
|
+
);
|
|
9749
|
+
} else if (syx[5] === 1) {
|
|
9750
|
+
this.privateProps.callEvent(
|
|
9751
|
+
"synthDisplay",
|
|
9752
|
+
Array.from(syx)
|
|
9753
|
+
);
|
|
9754
|
+
} else {
|
|
9755
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9756
|
+
}
|
|
9757
|
+
}
|
|
9758
|
+
return;
|
|
9759
|
+
}
|
|
9760
|
+
case 22:
|
|
9761
|
+
if (syx[4] === 16) {
|
|
9762
|
+
this.setMIDIVolume(syx[7] / 100);
|
|
9763
|
+
SpessaSynthInfo(
|
|
9764
|
+
`%cRoland Master Volume control set to: %c${syx[7]}%c via: %c${arrayToHexString(
|
|
9765
|
+
syx
|
|
9766
|
+
)}`,
|
|
9767
|
+
consoleColors.info,
|
|
9768
|
+
consoleColors.value,
|
|
9769
|
+
consoleColors.info,
|
|
9770
|
+
consoleColors.value
|
|
9771
|
+
);
|
|
9772
|
+
return;
|
|
9773
|
+
}
|
|
9774
|
+
}
|
|
9775
|
+
} else {
|
|
9776
|
+
sysExNotRecognized(syx, "Roland GS");
|
|
9777
|
+
return;
|
|
9778
|
+
}
|
|
9779
|
+
}
|
|
9780
|
+
|
|
9781
|
+
// src/synthesizer/audio_engine/engine_methods/system_exclusive/handle_xg.ts
|
|
9782
|
+
function handleXG(syx, channelOffset = 0) {
|
|
9783
|
+
if (syx[2] === 76) {
|
|
9784
|
+
const a1 = syx[3];
|
|
9785
|
+
const a2 = syx[4];
|
|
9786
|
+
if (a1 === 0 && a2 === 0) {
|
|
9787
|
+
switch (syx[5]) {
|
|
9788
|
+
// Master tune
|
|
9789
|
+
case 0:
|
|
9790
|
+
{
|
|
9791
|
+
const tune = (syx[6] & 15) << 12 | (syx[7] & 15) << 8 | (syx[8] & 15) << 4 | syx[9] & 15;
|
|
9792
|
+
const cents = (tune - 1024) / 10;
|
|
9793
|
+
this.setMasterTuning(cents);
|
|
9794
|
+
SpessaSynthInfo(
|
|
9795
|
+
`%cXG master tune. Cents: %c${cents}`,
|
|
9796
|
+
consoleColors.info,
|
|
9797
|
+
consoleColors.recognized
|
|
9798
|
+
);
|
|
9799
|
+
}
|
|
9800
|
+
break;
|
|
9801
|
+
// Master volume
|
|
9802
|
+
case 4: {
|
|
9803
|
+
const vol = syx[6];
|
|
9804
|
+
this.setMIDIVolume(vol / 127);
|
|
9805
|
+
SpessaSynthInfo(
|
|
9806
|
+
`%cXG master volume. Volume: %c${vol}`,
|
|
9807
|
+
consoleColors.info,
|
|
9808
|
+
consoleColors.recognized
|
|
9840
9809
|
);
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9810
|
+
break;
|
|
9811
|
+
}
|
|
9812
|
+
// Master attenuation
|
|
9813
|
+
case 5: {
|
|
9814
|
+
const vol = 127 - syx[6];
|
|
9815
|
+
this.setMIDIVolume(vol / 127);
|
|
9844
9816
|
SpessaSynthInfo(
|
|
9845
|
-
`%
|
|
9846
|
-
consoleColors.
|
|
9847
|
-
consoleColors.
|
|
9817
|
+
`%cXG master attenuation. Volume: %c${vol}`,
|
|
9818
|
+
consoleColors.info,
|
|
9819
|
+
consoleColors.recognized
|
|
9848
9820
|
);
|
|
9821
|
+
break;
|
|
9849
9822
|
}
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9823
|
+
// Master transpose
|
|
9824
|
+
case 6: {
|
|
9825
|
+
const transpose = syx[6] - 64;
|
|
9826
|
+
this.setMasterParameter("transposition", transpose);
|
|
9854
9827
|
SpessaSynthInfo(
|
|
9855
|
-
`%
|
|
9856
|
-
consoleColors.
|
|
9857
|
-
consoleColors.
|
|
9828
|
+
`%cXG master transpose. Volume: %c${transpose}`,
|
|
9829
|
+
consoleColors.info,
|
|
9830
|
+
consoleColors.recognized
|
|
9831
|
+
);
|
|
9832
|
+
break;
|
|
9833
|
+
}
|
|
9834
|
+
//
|
|
9835
|
+
// XG on
|
|
9836
|
+
case 126:
|
|
9837
|
+
SpessaSynthInfo("%cXG system on", consoleColors.info);
|
|
9838
|
+
this.resetAllControllers("xg");
|
|
9839
|
+
break;
|
|
9840
|
+
}
|
|
9841
|
+
} else if (a1 === 2 && a2 === 1) {
|
|
9842
|
+
let effectType;
|
|
9843
|
+
const effect = syx[5];
|
|
9844
|
+
if (effect <= 21) effectType = "Reverb";
|
|
9845
|
+
else if (effect <= 35) effectType = "Chorus";
|
|
9846
|
+
else effectType = "Variation";
|
|
9847
|
+
SpessaSynthInfo(
|
|
9848
|
+
`%cUnsupported XG ${effectType} Parameter: %c${effect.toString(16)}`,
|
|
9849
|
+
consoleColors.warn,
|
|
9850
|
+
consoleColors.unrecognized
|
|
9851
|
+
);
|
|
9852
|
+
} else if (a1 === 8) {
|
|
9853
|
+
if (!BankSelectHacks.isSystemXG(
|
|
9854
|
+
this.privateProps.masterParameters.midiSystem
|
|
9855
|
+
)) {
|
|
9856
|
+
return;
|
|
9857
|
+
}
|
|
9858
|
+
const channel = a2 + channelOffset;
|
|
9859
|
+
if (channel >= this.midiChannels.length) {
|
|
9860
|
+
return;
|
|
9861
|
+
}
|
|
9862
|
+
const channelObject = this.midiChannels[channel];
|
|
9863
|
+
const value = syx[6];
|
|
9864
|
+
switch (syx[5]) {
|
|
9865
|
+
// Bank-select MSB
|
|
9866
|
+
case 1:
|
|
9867
|
+
channelObject.controllerChange(
|
|
9868
|
+
midiControllers.bankSelect,
|
|
9869
|
+
value
|
|
9870
|
+
);
|
|
9871
|
+
break;
|
|
9872
|
+
// Bank-select LSB
|
|
9873
|
+
case 2:
|
|
9874
|
+
channelObject.controllerChange(
|
|
9875
|
+
midiControllers.bankSelectLSB,
|
|
9876
|
+
value
|
|
9877
|
+
);
|
|
9878
|
+
break;
|
|
9879
|
+
// Program change
|
|
9880
|
+
case 3:
|
|
9881
|
+
channelObject.programChange(value);
|
|
9882
|
+
break;
|
|
9883
|
+
// Part mode
|
|
9884
|
+
case 7:
|
|
9885
|
+
channelObject.setDrums(value != 0);
|
|
9886
|
+
break;
|
|
9887
|
+
// Note shift
|
|
9888
|
+
case 8: {
|
|
9889
|
+
if (channelObject.drumChannel) {
|
|
9890
|
+
break;
|
|
9891
|
+
}
|
|
9892
|
+
channelObject.setCustomController(
|
|
9893
|
+
customControllers.channelKeyShift,
|
|
9894
|
+
value - 64
|
|
9858
9895
|
);
|
|
9896
|
+
break;
|
|
9897
|
+
}
|
|
9898
|
+
// Volume
|
|
9899
|
+
case 11:
|
|
9900
|
+
channelObject.controllerChange(
|
|
9901
|
+
midiControllers.mainVolume,
|
|
9902
|
+
value
|
|
9903
|
+
);
|
|
9904
|
+
break;
|
|
9905
|
+
// Pan position
|
|
9906
|
+
case 14: {
|
|
9907
|
+
const pan = value;
|
|
9908
|
+
if (pan === 0) {
|
|
9909
|
+
channelObject.randomPan = true;
|
|
9910
|
+
SpessaSynthInfo(
|
|
9911
|
+
`%cRandom pan is set to %cON%c for %c${channel}`,
|
|
9912
|
+
consoleColors.info,
|
|
9913
|
+
consoleColors.recognized,
|
|
9914
|
+
consoleColors.info,
|
|
9915
|
+
consoleColors.value
|
|
9916
|
+
);
|
|
9917
|
+
} else {
|
|
9918
|
+
channelObject.controllerChange(
|
|
9919
|
+
midiControllers.pan,
|
|
9920
|
+
pan
|
|
9921
|
+
);
|
|
9922
|
+
}
|
|
9923
|
+
break;
|
|
9859
9924
|
}
|
|
9925
|
+
// Dry
|
|
9926
|
+
case 17:
|
|
9927
|
+
channelObject.controllerChange(
|
|
9928
|
+
midiControllers.mainVolume,
|
|
9929
|
+
value
|
|
9930
|
+
);
|
|
9931
|
+
break;
|
|
9932
|
+
// Chorus
|
|
9933
|
+
case 18:
|
|
9934
|
+
channelObject.controllerChange(
|
|
9935
|
+
midiControllers.chorusDepth,
|
|
9936
|
+
value
|
|
9937
|
+
);
|
|
9938
|
+
break;
|
|
9939
|
+
// Reverb
|
|
9940
|
+
case 19:
|
|
9941
|
+
channelObject.controllerChange(
|
|
9942
|
+
midiControllers.reverbDepth,
|
|
9943
|
+
value
|
|
9944
|
+
);
|
|
9945
|
+
break;
|
|
9946
|
+
// Vibrato rate
|
|
9947
|
+
case 21:
|
|
9948
|
+
channelObject.controllerChange(
|
|
9949
|
+
midiControllers.vibratoRate,
|
|
9950
|
+
value
|
|
9951
|
+
);
|
|
9952
|
+
break;
|
|
9953
|
+
// Vibrato depth
|
|
9954
|
+
case 22:
|
|
9955
|
+
channelObject.controllerChange(
|
|
9956
|
+
midiControllers.vibratoDepth,
|
|
9957
|
+
value
|
|
9958
|
+
);
|
|
9959
|
+
break;
|
|
9960
|
+
// Vibrato delay
|
|
9961
|
+
case 23:
|
|
9962
|
+
channelObject.controllerChange(
|
|
9963
|
+
midiControllers.vibratoDelay,
|
|
9964
|
+
value
|
|
9965
|
+
);
|
|
9966
|
+
break;
|
|
9967
|
+
// Filter cutoff
|
|
9968
|
+
case 24:
|
|
9969
|
+
channelObject.controllerChange(
|
|
9970
|
+
midiControllers.brightness,
|
|
9971
|
+
value
|
|
9972
|
+
);
|
|
9973
|
+
break;
|
|
9974
|
+
// Filter resonance
|
|
9975
|
+
case 25:
|
|
9976
|
+
channelObject.controllerChange(
|
|
9977
|
+
midiControllers.filterResonance,
|
|
9978
|
+
value
|
|
9979
|
+
);
|
|
9980
|
+
break;
|
|
9981
|
+
// Attack time
|
|
9982
|
+
case 26:
|
|
9983
|
+
channelObject.controllerChange(
|
|
9984
|
+
midiControllers.attackTime,
|
|
9985
|
+
value
|
|
9986
|
+
);
|
|
9987
|
+
break;
|
|
9988
|
+
// Decay time
|
|
9989
|
+
case 27:
|
|
9990
|
+
channelObject.controllerChange(
|
|
9991
|
+
midiControllers.decayTime,
|
|
9992
|
+
value
|
|
9993
|
+
);
|
|
9994
|
+
break;
|
|
9995
|
+
// Release time
|
|
9996
|
+
case 28:
|
|
9997
|
+
channelObject.controllerChange(
|
|
9998
|
+
midiControllers.releaseTime,
|
|
9999
|
+
value
|
|
10000
|
+
);
|
|
10001
|
+
break;
|
|
10002
|
+
default:
|
|
10003
|
+
SpessaSynthInfo(
|
|
10004
|
+
`%cUnsupported Yamaha XG Part Setup: %c${syx[5].toString(16).toUpperCase()}%c for channel ${channel}`,
|
|
10005
|
+
consoleColors.warn,
|
|
10006
|
+
consoleColors.unrecognized,
|
|
10007
|
+
consoleColors.warn
|
|
10008
|
+
);
|
|
9860
10009
|
}
|
|
10010
|
+
} else if (a1 === 6 && // XG System parameter
|
|
10011
|
+
a2 === 0) {
|
|
10012
|
+
this.privateProps.callEvent("synthDisplay", Array.from(syx));
|
|
10013
|
+
} else if (BankSelectHacks.isSystemXG(
|
|
10014
|
+
this.privateProps.masterParameters.midiSystem
|
|
10015
|
+
)) {
|
|
10016
|
+
sysExNotRecognized(syx, "Yamaha XG");
|
|
10017
|
+
}
|
|
10018
|
+
} else {
|
|
10019
|
+
sysExNotRecognized(syx, "Yamaha");
|
|
10020
|
+
}
|
|
10021
|
+
}
|
|
10022
|
+
|
|
10023
|
+
// src/synthesizer/audio_engine/engine_methods/system_exclusive.ts
|
|
10024
|
+
function systemExclusiveInternal(syx, channelOffset = 0) {
|
|
10025
|
+
const manufacturer = syx[0];
|
|
10026
|
+
if (
|
|
10027
|
+
// The device ID can be set to "all" which it is by default
|
|
10028
|
+
this.privateProps.masterParameters.deviceID !== ALL_CHANNELS_OR_DIFFERENT_ACTION && syx[1] !== 127
|
|
10029
|
+
) {
|
|
10030
|
+
if (this.privateProps.masterParameters.deviceID !== syx[1]) {
|
|
10031
|
+
return;
|
|
10032
|
+
}
|
|
10033
|
+
}
|
|
10034
|
+
switch (manufacturer) {
|
|
10035
|
+
default:
|
|
10036
|
+
SpessaSynthInfo(
|
|
10037
|
+
`%cUnrecognized SysEx: %c${arrayToHexString(syx)} (unknown manufacturer)`,
|
|
10038
|
+
consoleColors.warn,
|
|
10039
|
+
consoleColors.unrecognized
|
|
10040
|
+
);
|
|
10041
|
+
break;
|
|
10042
|
+
// Non realtime GM
|
|
10043
|
+
case 126:
|
|
10044
|
+
// Realtime GM
|
|
10045
|
+
case 127:
|
|
10046
|
+
handleGM.call(this, syx, channelOffset);
|
|
10047
|
+
break;
|
|
10048
|
+
// Roland
|
|
10049
|
+
case 65:
|
|
10050
|
+
handleGS.call(this, syx, channelOffset);
|
|
10051
|
+
break;
|
|
10052
|
+
// Yamaha
|
|
10053
|
+
case 67:
|
|
10054
|
+
handleXG.call(this, syx, channelOffset);
|
|
9861
10055
|
break;
|
|
9862
10056
|
}
|
|
9863
10057
|
}
|
|
@@ -10251,8 +10445,7 @@ var ProtectedSynthValues = class {
|
|
|
10251
10445
|
voiceKilling;
|
|
10252
10446
|
/**
|
|
10253
10447
|
* Cached voices for all presets for this synthesizer.
|
|
10254
|
-
* Nesting
|
|
10255
|
-
* this.cachedVoices[bankMSB][bankLSB][programNumber][midiNote][velocity] = a list of voices for that.
|
|
10448
|
+
* Nesting is calculated in getCachedVoiceIndex, returns a list of voices for this note.
|
|
10256
10449
|
*/
|
|
10257
10450
|
cachedVoices = [];
|
|
10258
10451
|
constructor(eventCallbackHandler, getVoices, voiceKillingFunction, volumeEnvelopeSmoothingFactor, panSmoothingFactor, filterSmoothingFactor) {
|
|
@@ -10606,13 +10799,14 @@ var nonRegisteredMSB = {
|
|
|
10606
10799
|
awe32: 127,
|
|
10607
10800
|
SF2: 120
|
|
10608
10801
|
};
|
|
10609
|
-
var
|
|
10802
|
+
var nonRegisteredLSB = {
|
|
10610
10803
|
vibratoRate: 8,
|
|
10611
10804
|
vibratoDepth: 9,
|
|
10612
10805
|
vibratoDelay: 10,
|
|
10613
10806
|
TVFFilterCutoff: 32,
|
|
10614
10807
|
TVFFilterResonance: 33,
|
|
10615
10808
|
EGAttackTime: 99,
|
|
10809
|
+
EGDecayTime: 100,
|
|
10616
10810
|
EGReleaseTime: 102
|
|
10617
10811
|
};
|
|
10618
10812
|
function dataEntryCoarse(dataValue) {
|
|
@@ -10641,7 +10835,7 @@ function dataEntryCoarse(dataValue) {
|
|
|
10641
10835
|
default:
|
|
10642
10836
|
case dataEntryStates.Idle:
|
|
10643
10837
|
break;
|
|
10644
|
-
// Process
|
|
10838
|
+
// Process NRPNs
|
|
10645
10839
|
case dataEntryStates.NRPFine: {
|
|
10646
10840
|
if (this.lockGSNRPNParams) {
|
|
10647
10841
|
return;
|
|
@@ -10668,7 +10862,7 @@ function dataEntryCoarse(dataValue) {
|
|
|
10668
10862
|
consoleColors.value
|
|
10669
10863
|
);
|
|
10670
10864
|
break;
|
|
10671
|
-
// Part parameters
|
|
10865
|
+
// Part parameters
|
|
10672
10866
|
case nonRegisteredMSB.partParameter:
|
|
10673
10867
|
switch (NRPNFine) {
|
|
10674
10868
|
default:
|
|
@@ -10687,8 +10881,8 @@ function dataEntryCoarse(dataValue) {
|
|
|
10687
10881
|
consoleColors.value
|
|
10688
10882
|
);
|
|
10689
10883
|
break;
|
|
10690
|
-
// Vibrato rate
|
|
10691
|
-
case
|
|
10884
|
+
// Vibrato rate (custom vibrato)
|
|
10885
|
+
case nonRegisteredLSB.vibratoRate:
|
|
10692
10886
|
if (dataValue === 64) {
|
|
10693
10887
|
return;
|
|
10694
10888
|
}
|
|
@@ -10700,8 +10894,8 @@ function dataEntryCoarse(dataValue) {
|
|
|
10700
10894
|
"Hz"
|
|
10701
10895
|
);
|
|
10702
10896
|
break;
|
|
10703
|
-
// Vibrato depth
|
|
10704
|
-
case
|
|
10897
|
+
// Vibrato depth (custom vibrato)
|
|
10898
|
+
case nonRegisteredLSB.vibratoDepth:
|
|
10705
10899
|
if (dataValue === 64) {
|
|
10706
10900
|
return;
|
|
10707
10901
|
}
|
|
@@ -10713,8 +10907,8 @@ function dataEntryCoarse(dataValue) {
|
|
|
10713
10907
|
"cents of detune"
|
|
10714
10908
|
);
|
|
10715
10909
|
break;
|
|
10716
|
-
// Vibrato delay
|
|
10717
|
-
case
|
|
10910
|
+
// Vibrato delay (custom vibrato)
|
|
10911
|
+
case nonRegisteredLSB.vibratoDelay:
|
|
10718
10912
|
if (dataValue === 64) {
|
|
10719
10913
|
return;
|
|
10720
10914
|
}
|
|
@@ -10727,15 +10921,26 @@ function dataEntryCoarse(dataValue) {
|
|
|
10727
10921
|
);
|
|
10728
10922
|
break;
|
|
10729
10923
|
// Filter cutoff
|
|
10730
|
-
case
|
|
10924
|
+
case nonRegisteredLSB.TVFFilterCutoff:
|
|
10731
10925
|
this.controllerChange(
|
|
10732
10926
|
midiControllers.brightness,
|
|
10733
10927
|
dataValue
|
|
10734
10928
|
);
|
|
10735
10929
|
coolInfo("Filter cutoff", dataValue.toString(), "");
|
|
10736
10930
|
break;
|
|
10931
|
+
case nonRegisteredLSB.TVFFilterResonance:
|
|
10932
|
+
this.controllerChange(
|
|
10933
|
+
midiControllers.filterResonance,
|
|
10934
|
+
dataValue
|
|
10935
|
+
);
|
|
10936
|
+
coolInfo(
|
|
10937
|
+
"Filter resonance",
|
|
10938
|
+
dataValue.toString(),
|
|
10939
|
+
""
|
|
10940
|
+
);
|
|
10941
|
+
break;
|
|
10737
10942
|
// Attack time
|
|
10738
|
-
case
|
|
10943
|
+
case nonRegisteredLSB.EGAttackTime:
|
|
10739
10944
|
this.controllerChange(
|
|
10740
10945
|
midiControllers.attackTime,
|
|
10741
10946
|
dataValue
|
|
@@ -10746,8 +10951,15 @@ function dataEntryCoarse(dataValue) {
|
|
|
10746
10951
|
""
|
|
10747
10952
|
);
|
|
10748
10953
|
break;
|
|
10954
|
+
case nonRegisteredLSB.EGDecayTime:
|
|
10955
|
+
this.controllerChange(
|
|
10956
|
+
midiControllers.decayTime,
|
|
10957
|
+
dataValue
|
|
10958
|
+
);
|
|
10959
|
+
coolInfo("EG decay time", dataValue.toString(), "");
|
|
10960
|
+
break;
|
|
10749
10961
|
// Release time
|
|
10750
|
-
case
|
|
10962
|
+
case nonRegisteredLSB.EGReleaseTime:
|
|
10751
10963
|
this.controllerChange(
|
|
10752
10964
|
midiControllers.releaseTime,
|
|
10753
10965
|
dataValue
|
|
@@ -11147,47 +11359,92 @@ function controllerChange(controllerNumber, controllerValue, sendEvent = true) {
|
|
|
11147
11359
|
}
|
|
11148
11360
|
|
|
11149
11361
|
// src/synthesizer/audio_engine/engine_methods/portamento_time.ts
|
|
11150
|
-
var
|
|
11151
|
-
|
|
11152
|
-
1
|
|
11153
|
-
|
|
11154
|
-
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
|
|
11170
|
-
|
|
11171
|
-
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11181
|
-
|
|
11182
|
-
|
|
11183
|
-
|
|
11184
|
-
const
|
|
11185
|
-
|
|
11362
|
+
var PORTA_DIVISION_CONSTANT = 40;
|
|
11363
|
+
function portaTimeToRate(cc) {
|
|
11364
|
+
if (cc < 1) {
|
|
11365
|
+
return 0;
|
|
11366
|
+
} else {
|
|
11367
|
+
const x0 = [1, 2, 4, 8, 16, 32, 64, 80, 96, 112, 120, 124];
|
|
11368
|
+
const ih = [
|
|
11369
|
+
1,
|
|
11370
|
+
0.5,
|
|
11371
|
+
0.25,
|
|
11372
|
+
0.125,
|
|
11373
|
+
0.0625,
|
|
11374
|
+
0.03125,
|
|
11375
|
+
0.0625,
|
|
11376
|
+
0.0625,
|
|
11377
|
+
0.0625,
|
|
11378
|
+
0.125,
|
|
11379
|
+
0.25,
|
|
11380
|
+
1 / 3
|
|
11381
|
+
];
|
|
11382
|
+
const a = [
|
|
11383
|
+
-0.16653127382501215,
|
|
11384
|
+
0.11863875218299408,
|
|
11385
|
+
0.029479047361245264,
|
|
11386
|
+
-0.005442312089231738,
|
|
11387
|
+
0.1451520875973037,
|
|
11388
|
+
-0.005056281449558275,
|
|
11389
|
+
-0.005095486882876532,
|
|
11390
|
+
0.03334009551111544,
|
|
11391
|
+
-0.09361368678020432,
|
|
11392
|
+
0.14132569702451822,
|
|
11393
|
+
-0.15805565301011382,
|
|
11394
|
+
-0.09918856955881927
|
|
11395
|
+
];
|
|
11396
|
+
const b = [
|
|
11397
|
+
0.028212773333433472,
|
|
11398
|
+
-0.3388502064992847,
|
|
11399
|
+
-0.15839529890929713,
|
|
11400
|
+
-0.12398131766775483,
|
|
11401
|
+
-0.2874848552685111,
|
|
11402
|
+
0.012254866302537692,
|
|
11403
|
+
0.005957797193345771,
|
|
11404
|
+
-0.03745899330347374,
|
|
11405
|
+
0.12911781869810196,
|
|
11406
|
+
-0.15867193224162568,
|
|
11407
|
+
0.504406322732748,
|
|
11408
|
+
0.3786845131875458
|
|
11409
|
+
];
|
|
11410
|
+
const c = [
|
|
11411
|
+
0.7218950861255283,
|
|
11412
|
+
0.5574536226347168,
|
|
11413
|
+
0.47133893237025826,
|
|
11414
|
+
0.48597095327079914,
|
|
11415
|
+
0.44336276333518854,
|
|
11416
|
+
0.6076986311801551,
|
|
11417
|
+
0.30851975971827794,
|
|
11418
|
+
0.30514889345633955,
|
|
11419
|
+
0.3302511933827384,
|
|
11420
|
+
0.153822885219165,
|
|
11421
|
+
0.1302280559047337,
|
|
11422
|
+
0.49865530675491687
|
|
11423
|
+
];
|
|
11424
|
+
const d = [
|
|
11425
|
+
-2.2218487496163566,
|
|
11426
|
+
-1.6382721639824072,
|
|
11427
|
+
-1.3010299956639813,
|
|
11428
|
+
-0.958607314841775,
|
|
11429
|
+
-0.6020599913279624,
|
|
11430
|
+
-0.3010299956639812,
|
|
11431
|
+
0.31386722036915343,
|
|
11432
|
+
0.6232492903979004,
|
|
11433
|
+
0.9242792860618817,
|
|
11434
|
+
1.290034611362518,
|
|
11435
|
+
1.4265112613645752,
|
|
11436
|
+
1.9030899869919435
|
|
11437
|
+
];
|
|
11438
|
+
const thresholds = [2, 4, 8, 16, 32, 64, 80, 96, 112, 120, 124];
|
|
11439
|
+
const s = thresholds.findLastIndex((t2) => t2 < cc) + 1;
|
|
11440
|
+
const t = (cc - x0[s]) * ih[s];
|
|
11441
|
+
return Math.exp(
|
|
11442
|
+
2.302585092994046 * (((a[s] * t + b[s]) * t + c[s]) * t + d[s])
|
|
11443
|
+
) / PORTA_DIVISION_CONSTANT;
|
|
11186
11444
|
}
|
|
11187
|
-
return 0;
|
|
11188
11445
|
}
|
|
11189
11446
|
function portamentoTimeToSeconds(time, distance) {
|
|
11190
|
-
return
|
|
11447
|
+
return portaTimeToRate(time) * distance;
|
|
11191
11448
|
}
|
|
11192
11449
|
|
|
11193
11450
|
// src/synthesizer/audio_engine/engine_methods/note_on.ts
|
|
@@ -11231,16 +11488,15 @@ function noteOn(midiNote, velocity) {
|
|
|
11231
11488
|
let portamentoFromKey = -1;
|
|
11232
11489
|
let portamentoDuration = 0;
|
|
11233
11490
|
const portamentoTime = this.midiControllers[midiControllers.portamentoTime] >> 7;
|
|
11234
|
-
const
|
|
11235
|
-
const currentFromKey = control >> 7;
|
|
11491
|
+
const portaControl = this.midiControllers[midiControllers.portamentoControl] >> 7;
|
|
11236
11492
|
if (!this.drumChannel && // No portamento on drum channel
|
|
11237
|
-
|
|
11493
|
+
portaControl !== internalMidiNote && // If the same note, there's no portamento
|
|
11238
11494
|
this.midiControllers[midiControllers.portamentoOnOff] >= 8192 && // (64 << 7)
|
|
11239
11495
|
portamentoTime > 0) {
|
|
11240
|
-
if (
|
|
11241
|
-
const diff = Math.abs(internalMidiNote -
|
|
11496
|
+
if (portaControl > 0) {
|
|
11497
|
+
const diff = Math.abs(internalMidiNote - portaControl);
|
|
11242
11498
|
portamentoDuration = portamentoTimeToSeconds(portamentoTime, diff);
|
|
11243
|
-
portamentoFromKey =
|
|
11499
|
+
portamentoFromKey = portaControl;
|
|
11244
11500
|
}
|
|
11245
11501
|
this.controllerChange(
|
|
11246
11502
|
midiControllers.portamentoControl,
|
|
@@ -17058,16 +17314,12 @@ var SpessaSynthProcessor3 = class {
|
|
|
17058
17314
|
});
|
|
17059
17315
|
}
|
|
17060
17316
|
getCachedVoice(patch, midiNote, velocity) {
|
|
17061
|
-
|
|
17062
|
-
let bankLSB = patch.bankLSB;
|
|
17063
|
-
const { isGMGSDrum, program } = patch;
|
|
17064
|
-
if (isGMGSDrum) {
|
|
17065
|
-
bankMSB = 128;
|
|
17066
|
-
bankLSB = 0;
|
|
17067
|
-
}
|
|
17068
|
-
return this.privateProps.cachedVoices?.[bankMSB]?.[bankLSB]?.[program]?.[midiNote]?.[velocity];
|
|
17317
|
+
return this.privateProps.cachedVoices?.[this.getCachedVoiceIndex(patch, midiNote, velocity)];
|
|
17069
17318
|
}
|
|
17070
17319
|
setCachedVoice(patch, midiNote, velocity, voices) {
|
|
17320
|
+
this.privateProps.cachedVoices[this.getCachedVoiceIndex(patch, midiNote, velocity)] = voices;
|
|
17321
|
+
}
|
|
17322
|
+
getCachedVoiceIndex(patch, midiNote, velocity) {
|
|
17071
17323
|
let bankMSB = patch.bankMSB;
|
|
17072
17324
|
let bankLSB = patch.bankLSB;
|
|
17073
17325
|
const { isGMGSDrum, program } = patch;
|
|
@@ -17075,19 +17327,11 @@ var SpessaSynthProcessor3 = class {
|
|
|
17075
17327
|
bankMSB = 128;
|
|
17076
17328
|
bankLSB = 0;
|
|
17077
17329
|
}
|
|
17078
|
-
|
|
17079
|
-
|
|
17080
|
-
|
|
17081
|
-
|
|
17082
|
-
|
|
17083
|
-
}
|
|
17084
|
-
if (!this.privateProps.cachedVoices[bankMSB][bankLSB][program]) {
|
|
17085
|
-
this.privateProps.cachedVoices[bankMSB][bankLSB][program] = [];
|
|
17086
|
-
}
|
|
17087
|
-
if (!this.privateProps.cachedVoices[bankMSB][bankLSB][program][midiNote]) {
|
|
17088
|
-
this.privateProps.cachedVoices[bankMSB][bankLSB][program][midiNote] = [];
|
|
17089
|
-
}
|
|
17090
|
-
this.privateProps.cachedVoices[bankMSB][bankLSB][program][midiNote][velocity] = voices;
|
|
17330
|
+
return bankMSB + // 128 ^ 0
|
|
17331
|
+
bankLSB * 128 + // 128 ^ 1
|
|
17332
|
+
program * 16384 + // 128 ^ 2
|
|
17333
|
+
2097152 * midiNote + // 128 ^ 3
|
|
17334
|
+
268435456 * velocity;
|
|
17091
17335
|
}
|
|
17092
17336
|
createMIDIChannelInternal(sendEvent) {
|
|
17093
17337
|
const channel = new MIDIChannel(
|
|
@@ -17111,7 +17355,7 @@ var SpessaSynthProcessor3 = class {
|
|
|
17111
17355
|
this.midiChannels.forEach((c) => {
|
|
17112
17356
|
c.setPresetLock(false);
|
|
17113
17357
|
});
|
|
17114
|
-
this.resetAllControllers(
|
|
17358
|
+
this.resetAllControllers();
|
|
17115
17359
|
}
|
|
17116
17360
|
getDefaultPresets() {
|
|
17117
17361
|
this.privateProps.defaultPreset = this.soundBankManager.getPreset(
|
|
@@ -17165,7 +17409,6 @@ export {
|
|
|
17165
17409
|
Modulator,
|
|
17166
17410
|
ModulatorSource,
|
|
17167
17411
|
NON_CC_INDEX_OFFSET,
|
|
17168
|
-
PORTAMENTO_CONTROL_UNSET,
|
|
17169
17412
|
SoundBankLoader,
|
|
17170
17413
|
SpessaSynthCoreUtils,
|
|
17171
17414
|
SpessaSynthLogging,
|