spessasynth_core 1.1.2 → 1.1.4
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/LICENSE +3 -26
- package/README.md +156 -474
- package/index.js +73 -8
- package/package.json +21 -8
- package/src/externals/fflate/LICENSE +21 -0
- package/src/externals/fflate/fflate.min.js +1 -0
- package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +12 -0
- package/src/externals/stbvorbis_sync/LICENSE +202 -0
- package/src/externals/stbvorbis_sync/NOTICE +6 -0
- package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +1 -0
- package/src/midi/README.md +32 -0
- package/src/midi/basic_midi.js +567 -0
- package/src/midi/midi_builder.js +202 -0
- package/src/midi/midi_loader.js +324 -0
- package/{spessasynth_core/midi_parser → src/midi}/midi_message.js +58 -35
- package/src/midi/midi_sequence.js +224 -0
- package/src/midi/midi_tools/get_note_times.js +154 -0
- package/src/midi/midi_tools/midi_editor.js +611 -0
- package/src/midi/midi_tools/midi_writer.js +99 -0
- package/src/midi/midi_tools/rmidi_writer.js +567 -0
- package/src/midi/midi_tools/used_keys_loaded.js +238 -0
- package/src/midi/xmf_loader.js +454 -0
- package/src/sequencer/README.md +5 -0
- package/src/sequencer/events.js +81 -0
- package/src/sequencer/play.js +349 -0
- package/src/sequencer/process_event.js +165 -0
- package/{spessasynth_core/sequencer/worklet_sequencer → src/sequencer}/process_tick.js +103 -84
- package/src/sequencer/sequencer_engine.js +367 -0
- package/src/sequencer/song_control.js +201 -0
- package/src/soundfont/README.md +13 -0
- package/src/soundfont/basic_soundfont/basic_instrument.js +77 -0
- package/src/soundfont/basic_soundfont/basic_preset.js +336 -0
- package/src/soundfont/basic_soundfont/basic_sample.js +206 -0
- package/src/soundfont/basic_soundfont/basic_soundfont.js +565 -0
- package/src/soundfont/basic_soundfont/basic_zone.js +64 -0
- package/src/soundfont/basic_soundfont/basic_zones.js +43 -0
- package/src/soundfont/basic_soundfont/generator.js +220 -0
- package/src/soundfont/basic_soundfont/modulator.js +378 -0
- package/src/soundfont/basic_soundfont/riff_chunk.js +149 -0
- package/src/soundfont/basic_soundfont/write_dls/art2.js +173 -0
- package/src/soundfont/basic_soundfont/write_dls/articulator.js +49 -0
- package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +400 -0
- package/src/soundfont/basic_soundfont/write_dls/ins.js +103 -0
- package/src/soundfont/basic_soundfont/write_dls/lins.js +18 -0
- package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +330 -0
- package/src/soundfont/basic_soundfont/write_dls/rgn2.js +121 -0
- package/src/soundfont/basic_soundfont/write_dls/wave.js +94 -0
- package/src/soundfont/basic_soundfont/write_dls/write_dls.js +119 -0
- package/src/soundfont/basic_soundfont/write_dls/wsmp.js +78 -0
- package/src/soundfont/basic_soundfont/write_dls/wvpl.js +32 -0
- package/src/soundfont/basic_soundfont/write_sf2/ibag.js +39 -0
- package/src/soundfont/basic_soundfont/write_sf2/igen.js +80 -0
- package/src/soundfont/basic_soundfont/write_sf2/imod.js +46 -0
- package/src/soundfont/basic_soundfont/write_sf2/inst.js +34 -0
- package/src/soundfont/basic_soundfont/write_sf2/pbag.js +39 -0
- package/src/soundfont/basic_soundfont/write_sf2/pgen.js +82 -0
- package/src/soundfont/basic_soundfont/write_sf2/phdr.js +42 -0
- package/src/soundfont/basic_soundfont/write_sf2/pmod.js +46 -0
- package/src/soundfont/basic_soundfont/write_sf2/sdta.js +80 -0
- package/src/soundfont/basic_soundfont/write_sf2/shdr.js +55 -0
- package/src/soundfont/basic_soundfont/write_sf2/write.js +222 -0
- package/src/soundfont/dls/articulator_converter.js +396 -0
- package/src/soundfont/dls/dls_destinations.js +38 -0
- package/src/soundfont/dls/dls_preset.js +44 -0
- package/src/soundfont/dls/dls_sample.js +75 -0
- package/src/soundfont/dls/dls_soundfont.js +186 -0
- package/src/soundfont/dls/dls_sources.js +62 -0
- package/src/soundfont/dls/dls_zone.js +95 -0
- package/src/soundfont/dls/read_articulation.js +299 -0
- package/src/soundfont/dls/read_instrument.js +121 -0
- package/src/soundfont/dls/read_instrument_list.js +17 -0
- package/src/soundfont/dls/read_lart.js +35 -0
- package/src/soundfont/dls/read_region.js +152 -0
- package/src/soundfont/dls/read_samples.js +270 -0
- package/src/soundfont/load_soundfont.js +21 -0
- package/src/soundfont/read_sf2/generators.js +46 -0
- package/{spessasynth_core/soundfont/chunk → src/soundfont/read_sf2}/instruments.js +20 -14
- package/src/soundfont/read_sf2/modulators.js +36 -0
- package/src/soundfont/read_sf2/presets.js +80 -0
- package/src/soundfont/read_sf2/samples.js +304 -0
- package/src/soundfont/read_sf2/soundfont.js +305 -0
- package/{spessasynth_core/soundfont/chunk → src/soundfont/read_sf2}/zones.js +68 -69
- package/src/synthetizer/README.md +7 -0
- package/src/synthetizer/audio_engine/README.md +9 -0
- package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +266 -0
- package/src/synthetizer/audio_engine/engine_components/controller_tables.js +88 -0
- package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +150 -0
- package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/lfo.js +9 -6
- package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +282 -0
- package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +467 -0
- package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +181 -0
- package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/modulator_curves.js +33 -30
- package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +221 -0
- package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +120 -0
- package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/unit_converter.js +11 -4
- package/src/synthetizer/audio_engine/engine_components/voice.js +519 -0
- package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +401 -0
- package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +263 -0
- package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +132 -0
- package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +48 -0
- package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +241 -0
- package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +27 -0
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +253 -0
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +66 -0
- package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +17 -0
- package/src/synthetizer/audio_engine/engine_methods/note_on.js +175 -0
- package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +92 -0
- package/src/synthetizer/audio_engine/engine_methods/program_change.js +61 -0
- package/src/synthetizer/audio_engine/engine_methods/render_voice.js +196 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +30 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +22 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +28 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +31 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +21 -0
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +20 -0
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +55 -0
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +16 -0
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +30 -0
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +63 -0
- package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +776 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +24 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +33 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +31 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +15 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +27 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +19 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +27 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +15 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +34 -0
- package/src/synthetizer/audio_engine/main_processor.js +804 -0
- package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +15 -0
- package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +175 -0
- package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +116 -0
- package/src/synthetizer/synth_constants.js +22 -0
- package/{spessasynth_core → src}/utils/README.md +1 -0
- package/src/utils/buffer_to_wav.js +185 -0
- package/src/utils/byte_functions/big_endian.js +32 -0
- package/src/utils/byte_functions/little_endian.js +77 -0
- package/src/utils/byte_functions/string.js +107 -0
- package/src/utils/byte_functions/variable_length_quantity.js +42 -0
- package/src/utils/fill_with_defaults.js +21 -0
- package/src/utils/indexed_array.js +52 -0
- package/{spessasynth_core → src}/utils/loggin.js +70 -78
- package/src/utils/other.js +92 -0
- package/src/utils/sysex_detector.js +58 -0
- package/src/utils/xg_hacks.js +193 -0
- package/.idea/inspectionProfiles/Project_Default.xml +0 -10
- package/.idea/jsLibraryMappings.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/spessasynth_core.iml +0 -12
- package/.idea/vcs.xml +0 -6
- package/spessasynth_core/midi_parser/README.md +0 -3
- package/spessasynth_core/midi_parser/midi_loader.js +0 -386
- package/spessasynth_core/sequencer/sequencer.js +0 -202
- package/spessasynth_core/sequencer/worklet_sequencer/play.js +0 -209
- package/spessasynth_core/sequencer/worklet_sequencer/process_event.js +0 -120
- package/spessasynth_core/sequencer/worklet_sequencer/song_control.js +0 -112
- package/spessasynth_core/soundfont/README.md +0 -4
- package/spessasynth_core/soundfont/chunk/generators.js +0 -205
- package/spessasynth_core/soundfont/chunk/modulators.js +0 -232
- package/spessasynth_core/soundfont/chunk/presets.js +0 -264
- package/spessasynth_core/soundfont/chunk/riff_chunk.js +0 -46
- package/spessasynth_core/soundfont/chunk/samples.js +0 -250
- package/spessasynth_core/soundfont/soundfont_parser.js +0 -301
- package/spessasynth_core/synthetizer/README.md +0 -6
- package/spessasynth_core/synthetizer/synthesizer.js +0 -303
- package/spessasynth_core/synthetizer/worklet_system/README.md +0 -3
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/controller_control.js +0 -290
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/data_entry.js +0 -280
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_off.js +0 -102
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_on.js +0 -77
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/program_control.js +0 -140
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/system_exclusive.js +0 -266
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -104
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -29
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/voice_control.js +0 -222
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +0 -95
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +0 -73
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +0 -76
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +0 -194
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +0 -83
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_modulator.js +0 -173
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +0 -106
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +0 -313
- package/spessasynth_core/utils/buffer_to_wav.js +0 -70
- package/spessasynth_core/utils/byte_functions.js +0 -141
- package/spessasynth_core/utils/other.js +0 -49
- package/spessasynth_core/utils/shiftable_array.js +0 -26
- package/spessasynth_core/utils/stbvorbis_sync.js +0 -1877
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { midiControllers } from "../../../../midi/midi_message.js";
|
|
2
|
+
import { computeModulators } from "../../engine_components/compute_modulator.js";
|
|
3
|
+
import { channelConfiguration, dataEntryStates } from "../../engine_components/controller_tables.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param controllerNumber {number}
|
|
7
|
+
* @param controllerValue {number}
|
|
8
|
+
* @param force {boolean}
|
|
9
|
+
* @this {MidiAudioChannel}
|
|
10
|
+
*/
|
|
11
|
+
export function controllerChange(controllerNumber, controllerValue, force = false)
|
|
12
|
+
{
|
|
13
|
+
if (controllerNumber > 127)
|
|
14
|
+
{
|
|
15
|
+
// channel configuration. force must be set to true
|
|
16
|
+
if (!force)
|
|
17
|
+
{
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
switch (controllerNumber)
|
|
21
|
+
{
|
|
22
|
+
default:
|
|
23
|
+
return;
|
|
24
|
+
|
|
25
|
+
case channelConfiguration.velocityOverride:
|
|
26
|
+
this.velocityOverride = controllerValue;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// lsb controller values: append them as the lower nibble of the 14-bit value
|
|
31
|
+
// excluding bank select and data entry as it's handled separately
|
|
32
|
+
if (
|
|
33
|
+
controllerNumber >= midiControllers.lsbForControl1ModulationWheel
|
|
34
|
+
&& controllerNumber <= midiControllers.lsbForControl13EffectControl2
|
|
35
|
+
&& controllerNumber !== midiControllers.lsbForControl6DataEntry
|
|
36
|
+
)
|
|
37
|
+
{
|
|
38
|
+
const actualCCNum = controllerNumber - 32;
|
|
39
|
+
if (this.lockedControllers[actualCCNum])
|
|
40
|
+
{
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// append the lower nibble to the main controller
|
|
44
|
+
this.midiControllers[actualCCNum] = (this.midiControllers[actualCCNum] & 0x3F80) | (controllerValue & 0x7F);
|
|
45
|
+
this.voices.forEach(v => computeModulators(v, this.midiControllers, 1, actualCCNum));
|
|
46
|
+
}
|
|
47
|
+
if (this.lockedControllers[controllerNumber])
|
|
48
|
+
{
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// apply the cc to the table
|
|
53
|
+
this.midiControllers[controllerNumber] = controllerValue << 7;
|
|
54
|
+
|
|
55
|
+
// interpret special CCs
|
|
56
|
+
{
|
|
57
|
+
switch (controllerNumber)
|
|
58
|
+
{
|
|
59
|
+
case midiControllers.allNotesOff:
|
|
60
|
+
this.stopAllNotes();
|
|
61
|
+
break;
|
|
62
|
+
|
|
63
|
+
case midiControllers.allSoundOff:
|
|
64
|
+
this.stopAllNotes(true);
|
|
65
|
+
break;
|
|
66
|
+
|
|
67
|
+
// special case: bank select
|
|
68
|
+
case midiControllers.bankSelect:
|
|
69
|
+
this.setBankSelect(controllerValue);
|
|
70
|
+
break;
|
|
71
|
+
|
|
72
|
+
case midiControllers.lsbForControl0BankSelect:
|
|
73
|
+
this.setBankSelect(controllerValue, true);
|
|
74
|
+
break;
|
|
75
|
+
|
|
76
|
+
// check for RPN and NPRN and data entry
|
|
77
|
+
case midiControllers.RPNLsb:
|
|
78
|
+
this.dataEntryState = dataEntryStates.RPFine;
|
|
79
|
+
break;
|
|
80
|
+
|
|
81
|
+
case midiControllers.RPNMsb:
|
|
82
|
+
this.dataEntryState = dataEntryStates.RPCoarse;
|
|
83
|
+
break;
|
|
84
|
+
|
|
85
|
+
case midiControllers.NRPNMsb:
|
|
86
|
+
this.dataEntryState = dataEntryStates.NRPCoarse;
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
case midiControllers.NRPNLsb:
|
|
90
|
+
this.dataEntryState = dataEntryStates.NRPFine;
|
|
91
|
+
break;
|
|
92
|
+
|
|
93
|
+
case midiControllers.dataEntryMsb:
|
|
94
|
+
this.dataEntryCoarse(controllerValue);
|
|
95
|
+
break;
|
|
96
|
+
|
|
97
|
+
case midiControllers.lsbForControl6DataEntry:
|
|
98
|
+
this.dataEntryFine(controllerValue);
|
|
99
|
+
break;
|
|
100
|
+
|
|
101
|
+
case midiControllers.resetAllControllers:
|
|
102
|
+
this.resetControllersRP15Compliant();
|
|
103
|
+
break;
|
|
104
|
+
|
|
105
|
+
case midiControllers.sustainPedal:
|
|
106
|
+
if (controllerValue >= 64)
|
|
107
|
+
{
|
|
108
|
+
this.holdPedal = true;
|
|
109
|
+
}
|
|
110
|
+
else
|
|
111
|
+
{
|
|
112
|
+
this.holdPedal = false;
|
|
113
|
+
this.sustainedVoices.forEach(v =>
|
|
114
|
+
{
|
|
115
|
+
v.release(this.synth.currentSynthTime);
|
|
116
|
+
});
|
|
117
|
+
this.sustainedVoices = [];
|
|
118
|
+
}
|
|
119
|
+
break;
|
|
120
|
+
|
|
121
|
+
// default: just compute modulators
|
|
122
|
+
default:
|
|
123
|
+
this.voices.forEach(v => computeModulators(v, this.midiControllers, 1, controllerNumber));
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
this.synth.callEvent("controllerchange", {
|
|
128
|
+
channel: this.channelNumber,
|
|
129
|
+
controllerNumber: controllerNumber,
|
|
130
|
+
controllerValue: controllerValue
|
|
131
|
+
});
|
|
132
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { SYNTHESIZER_GAIN } from "../../main_processor.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @enum {number}
|
|
5
|
+
*/
|
|
6
|
+
export const masterParameterType = {
|
|
7
|
+
mainVolume: 0,
|
|
8
|
+
masterPan: 1,
|
|
9
|
+
voicesCap: 2,
|
|
10
|
+
interpolationType: 3,
|
|
11
|
+
midiSystem: 4
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @this {SpessaSynthProcessor}
|
|
16
|
+
* @param type {masterParameterType}
|
|
17
|
+
* @param value {number|string|interpolationTypes}
|
|
18
|
+
*/
|
|
19
|
+
export function setMasterParameter(type, value)
|
|
20
|
+
{
|
|
21
|
+
switch (type)
|
|
22
|
+
{
|
|
23
|
+
case masterParameterType.masterPan:
|
|
24
|
+
let pan = value;
|
|
25
|
+
this.pan = pan;
|
|
26
|
+
// clamp to 0-1 (0 is left)
|
|
27
|
+
pan = (pan / 2) + 0.5;
|
|
28
|
+
this.panLeft = (1 - pan);
|
|
29
|
+
this.panRight = (pan);
|
|
30
|
+
break;
|
|
31
|
+
|
|
32
|
+
case masterParameterType.mainVolume:
|
|
33
|
+
this.masterGain = value * SYNTHESIZER_GAIN;
|
|
34
|
+
this.setMasterParameter(masterParameterType.masterPan, this.pan);
|
|
35
|
+
break;
|
|
36
|
+
|
|
37
|
+
case masterParameterType.voicesCap:
|
|
38
|
+
this.voiceCap = value;
|
|
39
|
+
break;
|
|
40
|
+
|
|
41
|
+
case masterParameterType.interpolationType:
|
|
42
|
+
this.interpolationType = value;
|
|
43
|
+
break;
|
|
44
|
+
|
|
45
|
+
case masterParameterType.midiSystem:
|
|
46
|
+
this.setSystem(value);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { consoleColors } from "../../../../utils/other.js";
|
|
2
|
+
import { SpessaSynthInfo } from "../../../../utils/loggin.js";
|
|
3
|
+
import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
|
|
4
|
+
import {
|
|
5
|
+
customControllers,
|
|
6
|
+
customResetArray,
|
|
7
|
+
dataEntryStates,
|
|
8
|
+
NON_CC_INDEX_OFFSET,
|
|
9
|
+
PORTAMENTO_CONTROL_UNSET,
|
|
10
|
+
resetArray
|
|
11
|
+
} from "../../engine_components/controller_tables.js";
|
|
12
|
+
import { midiControllers } from "../../../../midi/midi_message.js";
|
|
13
|
+
import { DEFAULT_PERCUSSION, DEFAULT_SYNTH_MODE } from "../../../synth_constants.js";
|
|
14
|
+
import { getDefaultBank } from "../../../../utils/xg_hacks.js";
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Full system reset
|
|
19
|
+
* @this {SpessaSynthProcessor}
|
|
20
|
+
* @param log {boolean}
|
|
21
|
+
*/
|
|
22
|
+
export function resetAllControllers(log = true)
|
|
23
|
+
{
|
|
24
|
+
if (log)
|
|
25
|
+
{
|
|
26
|
+
SpessaSynthInfo("%cResetting all controllers!", consoleColors.info);
|
|
27
|
+
}
|
|
28
|
+
this.callEvent("allcontrollerreset", undefined);
|
|
29
|
+
this.setSystem(DEFAULT_SYNTH_MODE);
|
|
30
|
+
for (let channelNumber = 0; channelNumber < this.midiAudioChannels.length; channelNumber++)
|
|
31
|
+
{
|
|
32
|
+
this.midiAudioChannels[channelNumber].resetControllers();
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @type {MidiAudioChannel}
|
|
36
|
+
**/
|
|
37
|
+
const ch = this.midiAudioChannels[channelNumber];
|
|
38
|
+
|
|
39
|
+
// if preset is unlocked, switch to non-drums and call event
|
|
40
|
+
if (!ch.lockPreset)
|
|
41
|
+
{
|
|
42
|
+
ch.setBankSelect(getDefaultBank(this.system));
|
|
43
|
+
if (channelNumber % 16 === DEFAULT_PERCUSSION)
|
|
44
|
+
{
|
|
45
|
+
ch.setPreset(this.drumPreset);
|
|
46
|
+
ch.presetUsesOverride = this.defaultDrumsUsesOverride;
|
|
47
|
+
ch.drumChannel = true;
|
|
48
|
+
this.callEvent("drumchange", {
|
|
49
|
+
channel: channelNumber,
|
|
50
|
+
isDrumChannel: true
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
else
|
|
54
|
+
{
|
|
55
|
+
ch.drumChannel = false;
|
|
56
|
+
ch.presetUsesOverride = this.defaultDrumsUsesOverride;
|
|
57
|
+
ch.setPreset(this.defaultPreset);
|
|
58
|
+
this.callEvent("drumchange", {
|
|
59
|
+
channel: channelNumber,
|
|
60
|
+
isDrumChannel: false
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else
|
|
65
|
+
{
|
|
66
|
+
this.callEvent("drumchange", {
|
|
67
|
+
channel: channelNumber,
|
|
68
|
+
isDrumChannel: ch.drumChannel
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const presetBank = ch.preset.bank;
|
|
73
|
+
const sentBank = presetBank === 128 ? 128 : (ch.presetUsesOverride ? presetBank + this.soundfontBankOffset : presetBank);
|
|
74
|
+
|
|
75
|
+
// call program change
|
|
76
|
+
this.callEvent("programchange", {
|
|
77
|
+
channel: channelNumber,
|
|
78
|
+
program: ch.preset.program,
|
|
79
|
+
bank: sentBank
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
for (let ccNum = 0; ccNum < 128; ccNum++)
|
|
83
|
+
{
|
|
84
|
+
if (this.midiAudioChannels[channelNumber].lockedControllers[ccNum])
|
|
85
|
+
{
|
|
86
|
+
// was not reset so restore the value
|
|
87
|
+
this.callEvent("controllerchange", {
|
|
88
|
+
channel: channelNumber,
|
|
89
|
+
controllerNumber: ccNum,
|
|
90
|
+
controllerValue: this.midiAudioChannels[channelNumber].midiControllers[ccNum] >> 7
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
// restore pitch wheel
|
|
98
|
+
if (this.midiAudioChannels[channelNumber].lockedControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel] === false)
|
|
99
|
+
{
|
|
100
|
+
const val = this.midiAudioChannels[channelNumber].midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel];
|
|
101
|
+
const msb = val >> 7;
|
|
102
|
+
const lsb = val & 0x7F;
|
|
103
|
+
this.callEvent("pitchwheel", {
|
|
104
|
+
channel: channelNumber,
|
|
105
|
+
MSB: msb,
|
|
106
|
+
LSB: lsb
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this.tunings = [];
|
|
111
|
+
this.tunings = [];
|
|
112
|
+
for (let i = 0; i < 128; i++)
|
|
113
|
+
{
|
|
114
|
+
this.tunings.push([]);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
this.setMIDIVolume(1);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Resets all controllers for channel
|
|
122
|
+
* @this {MidiAudioChannel}
|
|
123
|
+
*/
|
|
124
|
+
export function resetControllers()
|
|
125
|
+
{
|
|
126
|
+
this.channelOctaveTuning.fill(0);
|
|
127
|
+
|
|
128
|
+
// reset the array
|
|
129
|
+
for (let i = 0; i < resetArray.length; i++)
|
|
130
|
+
{
|
|
131
|
+
if (this.lockedControllers[i])
|
|
132
|
+
{
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const resetValue = resetArray[i];
|
|
136
|
+
if (this.midiControllers[i] !== resetValue && i < 127)
|
|
137
|
+
{
|
|
138
|
+
if (i === midiControllers.portamentoControl)
|
|
139
|
+
{
|
|
140
|
+
this.midiControllers[i] = PORTAMENTO_CONTROL_UNSET;
|
|
141
|
+
}
|
|
142
|
+
else
|
|
143
|
+
{
|
|
144
|
+
this.controllerChange(i, resetValue >> 7);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else
|
|
148
|
+
{
|
|
149
|
+
// out of range, do a regular reset
|
|
150
|
+
this.midiControllers[i] = resetValue;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
this.channelVibrato = { rate: 0, depth: 0, delay: 0 };
|
|
154
|
+
this.holdPedal = false;
|
|
155
|
+
this.randomPan = false;
|
|
156
|
+
|
|
157
|
+
// reset custom controllers
|
|
158
|
+
// special case: transpose does not get affected
|
|
159
|
+
const transpose = this.customControllers[customControllers.channelTransposeFine];
|
|
160
|
+
this.customControllers.set(customResetArray);
|
|
161
|
+
this.setCustomController(customControllers.channelTransposeFine, transpose);
|
|
162
|
+
|
|
163
|
+
this.resetParameters();
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @type {Set<midiControllers|number>}
|
|
170
|
+
*/
|
|
171
|
+
export const nonResetableCCs = new Set([
|
|
172
|
+
midiControllers.bankSelect,
|
|
173
|
+
midiControllers.lsbForControl0BankSelect,
|
|
174
|
+
midiControllers.mainVolume,
|
|
175
|
+
midiControllers.lsbForControl7MainVolume,
|
|
176
|
+
midiControllers.pan,
|
|
177
|
+
midiControllers.lsbForControl10Pan,
|
|
178
|
+
midiControllers.reverbDepth,
|
|
179
|
+
midiControllers.tremoloDepth,
|
|
180
|
+
midiControllers.chorusDepth,
|
|
181
|
+
midiControllers.detuneDepth,
|
|
182
|
+
midiControllers.phaserDepth,
|
|
183
|
+
midiControllers.soundVariation,
|
|
184
|
+
midiControllers.filterResonance,
|
|
185
|
+
midiControllers.releaseTime,
|
|
186
|
+
midiControllers.attackTime,
|
|
187
|
+
midiControllers.brightness,
|
|
188
|
+
midiControllers.decayTime,
|
|
189
|
+
midiControllers.vibratoRate,
|
|
190
|
+
midiControllers.vibratoDepth,
|
|
191
|
+
midiControllers.vibratoDelay,
|
|
192
|
+
midiControllers.soundController10
|
|
193
|
+
]);
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Reset all controllers for channel, but RP-15 compliant
|
|
197
|
+
* https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
|
|
198
|
+
* @this {MidiAudioChannel}
|
|
199
|
+
*/
|
|
200
|
+
export function resetControllersRP15Compliant()
|
|
201
|
+
{
|
|
202
|
+
// reset tunings
|
|
203
|
+
this.channelOctaveTuning.fill(0);
|
|
204
|
+
|
|
205
|
+
// reset pitch bend
|
|
206
|
+
this.pitchWheel(64, 0);
|
|
207
|
+
|
|
208
|
+
this.channelVibrato = { rate: 0, depth: 0, delay: 0 };
|
|
209
|
+
|
|
210
|
+
for (let i = 0; i < 128; i++)
|
|
211
|
+
{
|
|
212
|
+
const resetValue = resetArray[i];
|
|
213
|
+
if (!nonResetableCCs.has(i) && resetValue !== this.midiControllers[i])
|
|
214
|
+
{
|
|
215
|
+
if (i === midiControllers.portamentoControl)
|
|
216
|
+
{
|
|
217
|
+
this.midiControllers[i] = PORTAMENTO_CONTROL_UNSET;
|
|
218
|
+
}
|
|
219
|
+
else
|
|
220
|
+
{
|
|
221
|
+
this.controllerChange(i, resetValue >> 7);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* @this {MidiAudioChannel}
|
|
229
|
+
*/
|
|
230
|
+
export function resetParameters()
|
|
231
|
+
{
|
|
232
|
+
/**
|
|
233
|
+
* reset the state machine to idle
|
|
234
|
+
* @type {string}
|
|
235
|
+
*/
|
|
236
|
+
this.dataEntryState = dataEntryStates.Idle;
|
|
237
|
+
SpessaSynthInfo(
|
|
238
|
+
"%cResetting Registered and Non-Registered Parameters!",
|
|
239
|
+
consoleColors.info
|
|
240
|
+
);
|
|
241
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MidiAudioChannel } from "../engine_components/midi_audio_channel.js";
|
|
2
|
+
|
|
3
|
+
import { DEFAULT_PERCUSSION } from "../../synth_constants.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param sendEvent {boolean}
|
|
7
|
+
* @this {SpessaSynthProcessor}
|
|
8
|
+
*/
|
|
9
|
+
export function createMidiChannel(sendEvent = false)
|
|
10
|
+
{
|
|
11
|
+
/**
|
|
12
|
+
* @type {MidiAudioChannel}
|
|
13
|
+
*/
|
|
14
|
+
const channel = new MidiAudioChannel(this, this.defaultPreset, this.midiAudioChannels.length);
|
|
15
|
+
this.midiAudioChannels.push(channel);
|
|
16
|
+
channel.resetControllers();
|
|
17
|
+
channel.sendChannelProperty();
|
|
18
|
+
if (sendEvent)
|
|
19
|
+
{
|
|
20
|
+
this.callEvent("newchannel", undefined);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (channel.channelNumber % 16 === DEFAULT_PERCUSSION)
|
|
24
|
+
{
|
|
25
|
+
this.midiAudioChannels[this.midiAudioChannels.length - 1].setDrums(true);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { customControllers, dataEntryStates, NON_CC_INDEX_OFFSET } from "../../engine_components/controller_tables.js";
|
|
2
|
+
import { SpessaSynthInfo, SpessaSynthWarn } from "../../../../utils/loggin.js";
|
|
3
|
+
import { consoleColors } from "../../../../utils/other.js";
|
|
4
|
+
import { midiControllers } from "../../../../midi/midi_message.js";
|
|
5
|
+
import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @enum {number}
|
|
10
|
+
*/
|
|
11
|
+
const registeredParameterTypes = {
|
|
12
|
+
pitchBendRange: 0x0000,
|
|
13
|
+
fineTuning: 0x0001,
|
|
14
|
+
coarseTuning: 0x0002,
|
|
15
|
+
modulationDepth: 0x0005,
|
|
16
|
+
resetParameters: 0x3FFF
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* https://cdn.roland.com/assets/media/pdf/SC-88PRO_OM.pdf
|
|
21
|
+
* http://hummer.stanford.edu/sig/doc/classes/MidiOutput/rpn.html
|
|
22
|
+
* @enum {number}
|
|
23
|
+
*/
|
|
24
|
+
const nonRegisteredParameterNumbers = {
|
|
25
|
+
partParameter: 0x01,
|
|
26
|
+
|
|
27
|
+
vibratoRate: 0x08,
|
|
28
|
+
vibratoDepth: 0x09,
|
|
29
|
+
vibratoDelay: 0x0A,
|
|
30
|
+
|
|
31
|
+
EGAttackTime: 0x64,
|
|
32
|
+
EGReleaseTime: 0x66,
|
|
33
|
+
|
|
34
|
+
TVFFilterCutoff: 0x20,
|
|
35
|
+
drumReverb: 0x1D
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Executes a data entry for an NRP for a sc88pro NRP (because touhou yes) and RPN tuning
|
|
41
|
+
* @param dataValue {number} dataEntryCoarse MSB
|
|
42
|
+
* @this {MidiAudioChannel}
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
export function dataEntryCoarse(dataValue)
|
|
46
|
+
{
|
|
47
|
+
const addDefaultVibrato = () =>
|
|
48
|
+
{
|
|
49
|
+
if (this.channelVibrato.delay === 0 && this.channelVibrato.rate === 0 && this.channelVibrato.depth === 0)
|
|
50
|
+
{
|
|
51
|
+
this.channelVibrato.depth = 50;
|
|
52
|
+
this.channelVibrato.rate = 8;
|
|
53
|
+
this.channelVibrato.delay = 0.6;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const coolInfo = (what, value, type) =>
|
|
58
|
+
{
|
|
59
|
+
if (type.length > 0)
|
|
60
|
+
{
|
|
61
|
+
type = " " + type;
|
|
62
|
+
}
|
|
63
|
+
SpessaSynthInfo(
|
|
64
|
+
`%c${what} for %c${this.channelNumber}%c is now set to %c${value}%c${type}.`,
|
|
65
|
+
consoleColors.info,
|
|
66
|
+
consoleColors.recognized,
|
|
67
|
+
consoleColors.info,
|
|
68
|
+
consoleColors.value,
|
|
69
|
+
consoleColors.info
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
switch (this.dataEntryState)
|
|
73
|
+
{
|
|
74
|
+
default:
|
|
75
|
+
case dataEntryStates.Idle:
|
|
76
|
+
break;
|
|
77
|
+
|
|
78
|
+
// process GS NRPNs
|
|
79
|
+
case dataEntryStates.NRPFine:
|
|
80
|
+
if (this.lockGSNRPNParams)
|
|
81
|
+
{
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* @type {number}
|
|
86
|
+
*/
|
|
87
|
+
const NRPNCoarse = this.midiControllers[midiControllers.NRPNMsb] >> 7;
|
|
88
|
+
/**
|
|
89
|
+
* @type {number}
|
|
90
|
+
*/
|
|
91
|
+
const NRPNFine = this.midiControllers[midiControllers.NRPNLsb] >> 7;
|
|
92
|
+
switch (NRPNCoarse)
|
|
93
|
+
{
|
|
94
|
+
default:
|
|
95
|
+
if (dataValue === 64)
|
|
96
|
+
{
|
|
97
|
+
// default value
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
SpessaSynthWarn(
|
|
101
|
+
`%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNFine.toString(16)
|
|
102
|
+
.toUpperCase()} 0x${NRPNFine.toString(
|
|
103
|
+
16).toUpperCase()})%c data value: %c${dataValue}`,
|
|
104
|
+
consoleColors.warn,
|
|
105
|
+
consoleColors.recognized,
|
|
106
|
+
consoleColors.warn,
|
|
107
|
+
consoleColors.unrecognized,
|
|
108
|
+
consoleColors.warn,
|
|
109
|
+
consoleColors.value
|
|
110
|
+
);
|
|
111
|
+
break;
|
|
112
|
+
|
|
113
|
+
// part parameters: vibrato, cutoff
|
|
114
|
+
case nonRegisteredParameterNumbers.partParameter:
|
|
115
|
+
switch (NRPNFine)
|
|
116
|
+
{
|
|
117
|
+
default:
|
|
118
|
+
if (dataValue === 64)
|
|
119
|
+
{
|
|
120
|
+
// default value
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
SpessaSynthWarn(
|
|
124
|
+
`%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNCoarse.toString(16)} 0x${NRPNFine.toString(
|
|
125
|
+
16)})%c data value: %c${dataValue}`,
|
|
126
|
+
consoleColors.warn,
|
|
127
|
+
consoleColors.recognized,
|
|
128
|
+
consoleColors.warn,
|
|
129
|
+
consoleColors.unrecognized,
|
|
130
|
+
consoleColors.warn,
|
|
131
|
+
consoleColors.value
|
|
132
|
+
);
|
|
133
|
+
break;
|
|
134
|
+
|
|
135
|
+
// vibrato rate
|
|
136
|
+
case nonRegisteredParameterNumbers.vibratoRate:
|
|
137
|
+
if (dataValue === 64)
|
|
138
|
+
{
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
addDefaultVibrato();
|
|
142
|
+
this.channelVibrato.rate = (dataValue / 64) * 8;
|
|
143
|
+
coolInfo("Vibrato rate", `${dataValue} = ${this.channelVibrato.rate}`, "Hz");
|
|
144
|
+
break;
|
|
145
|
+
|
|
146
|
+
// vibrato depth
|
|
147
|
+
case nonRegisteredParameterNumbers.vibratoDepth:
|
|
148
|
+
if (dataValue === 64)
|
|
149
|
+
{
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
addDefaultVibrato();
|
|
153
|
+
this.channelVibrato.depth = dataValue / 2;
|
|
154
|
+
coolInfo("Vibrato depth", `${dataValue} = ${this.channelVibrato.depth}`, "cents of detune");
|
|
155
|
+
break;
|
|
156
|
+
|
|
157
|
+
// vibrato delay
|
|
158
|
+
case nonRegisteredParameterNumbers.vibratoDelay:
|
|
159
|
+
if (dataValue === 64)
|
|
160
|
+
{
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
addDefaultVibrato();
|
|
164
|
+
this.channelVibrato.delay = (dataValue / 64) / 3;
|
|
165
|
+
coolInfo("Vibrato delay", `${dataValue} = ${this.channelVibrato.delay}`, "seconds");
|
|
166
|
+
break;
|
|
167
|
+
|
|
168
|
+
// filter cutoff
|
|
169
|
+
case nonRegisteredParameterNumbers.TVFFilterCutoff:
|
|
170
|
+
// affect the "brightness" controller as we have a default modulator that controls it
|
|
171
|
+
this.controllerChange(midiControllers.brightness, dataValue);
|
|
172
|
+
coolInfo("Filter cutoff", dataValue.toString(), "");
|
|
173
|
+
break;
|
|
174
|
+
|
|
175
|
+
// attack time
|
|
176
|
+
case nonRegisteredParameterNumbers.EGAttackTime:
|
|
177
|
+
// affect the "attack time" controller as we have a default modulator that controls it
|
|
178
|
+
this.controllerChange(midiControllers.attackTime, dataValue);
|
|
179
|
+
coolInfo("EG attack time", dataValue.toString(), "");
|
|
180
|
+
break;
|
|
181
|
+
|
|
182
|
+
// release time
|
|
183
|
+
case nonRegisteredParameterNumbers.EGReleaseTime:
|
|
184
|
+
// affect the "release time" controller as we have a default modulator that controls it
|
|
185
|
+
this.controllerChange(midiControllers.releaseTime, dataValue);
|
|
186
|
+
coolInfo("EG release time", dataValue.toString(), "");
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
|
|
191
|
+
// drum reverb
|
|
192
|
+
case nonRegisteredParameterNumbers.drumReverb:
|
|
193
|
+
const reverb = dataValue;
|
|
194
|
+
this.controllerChange(midiControllers.reverbDepth, reverb);
|
|
195
|
+
coolInfo("GS Drum reverb", reverb.toString(), "percent");
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
|
|
200
|
+
case dataEntryStates.RPCoarse:
|
|
201
|
+
case dataEntryStates.RPFine:
|
|
202
|
+
/**
|
|
203
|
+
* @type {number}
|
|
204
|
+
*/
|
|
205
|
+
const rpnValue = this.midiControllers[midiControllers.RPNMsb] | (this.midiControllers[midiControllers.RPNLsb] >> 7);
|
|
206
|
+
switch (rpnValue)
|
|
207
|
+
{
|
|
208
|
+
default:
|
|
209
|
+
SpessaSynthWarn(
|
|
210
|
+
`%cUnrecognized RPN for %c${this.channelNumber}%c: %c(0x${rpnValue.toString(16)})%c data value: %c${dataValue}`,
|
|
211
|
+
consoleColors.warn,
|
|
212
|
+
consoleColors.recognized,
|
|
213
|
+
consoleColors.warn,
|
|
214
|
+
consoleColors.unrecognized,
|
|
215
|
+
consoleColors.warn,
|
|
216
|
+
consoleColors.value
|
|
217
|
+
);
|
|
218
|
+
break;
|
|
219
|
+
|
|
220
|
+
// pitch bend range
|
|
221
|
+
case registeredParameterTypes.pitchBendRange:
|
|
222
|
+
this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] = dataValue << 7;
|
|
223
|
+
coolInfo("Pitch bend range", dataValue.toString(), "semitones");
|
|
224
|
+
break;
|
|
225
|
+
|
|
226
|
+
// coarse tuning
|
|
227
|
+
case registeredParameterTypes.coarseTuning:
|
|
228
|
+
// semitones
|
|
229
|
+
const semitones = dataValue - 64;
|
|
230
|
+
this.setCustomController(customControllers.channelTuningSemitones, semitones);
|
|
231
|
+
coolInfo("Coarse tuning", semitones.toString(), "semitones");
|
|
232
|
+
break;
|
|
233
|
+
|
|
234
|
+
// fine-tuning
|
|
235
|
+
case registeredParameterTypes.fineTuning:
|
|
236
|
+
// note: this will not work properly unless the lsb is sent!
|
|
237
|
+
// here we store the raw value to then adjust in fine
|
|
238
|
+
this.setTuning(dataValue - 64, false);
|
|
239
|
+
break;
|
|
240
|
+
|
|
241
|
+
// modulation depth
|
|
242
|
+
case registeredParameterTypes.modulationDepth:
|
|
243
|
+
this.setModulationDepth(dataValue * 100);
|
|
244
|
+
break;
|
|
245
|
+
|
|
246
|
+
case registeredParameterTypes.resetParameters:
|
|
247
|
+
this.resetParameters();
|
|
248
|
+
break;
|
|
249
|
+
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
}
|
|
253
|
+
}
|