spessasynth_core 1.1.3 → 1.1.5
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 +74 -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 -313
- 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 -223
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +0 -133
- 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 -272
- 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 -175
- 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 -285
- 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,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @enum {number}
|
|
3
|
+
*/
|
|
4
|
+
export const generatorTypes = {
|
|
5
|
+
INVALID: -1, // invalid generator
|
|
6
|
+
startAddrsOffset: 0, // sample control - moves sample start point
|
|
7
|
+
endAddrOffset: 1, // sample control - moves sample end point
|
|
8
|
+
startloopAddrsOffset: 2, // loop control - moves loop start point
|
|
9
|
+
endloopAddrsOffset: 3, // loop control - moves loop end point
|
|
10
|
+
startAddrsCoarseOffset: 4, // sample control - moves sample start point in 32,768 increments
|
|
11
|
+
modLfoToPitch: 5, // pitch modulation - modulation lfo pitch modulation in cents
|
|
12
|
+
vibLfoToPitch: 6, // pitch modulation - vibrato lfo pitch modulation in cents
|
|
13
|
+
modEnvToPitch: 7, // pitch modulation - modulation envelope pitch modulation in cents
|
|
14
|
+
initialFilterFc: 8, // filter - lowpass filter cutoff in cents
|
|
15
|
+
initialFilterQ: 9, // filter - lowpass filter resonance
|
|
16
|
+
modLfoToFilterFc: 10, // filter modulation - modulation lfo lowpass filter cutoff in cents
|
|
17
|
+
modEnvToFilterFc: 11, // filter modulation - modulation envelope lowpass filter cutoff in cents
|
|
18
|
+
endAddrsCoarseOffset: 12, // ample control - move sample end point in 32,768 increments
|
|
19
|
+
modLfoToVolume: 13, // modulation lfo - volume (tremolo), where 100 = 10dB
|
|
20
|
+
unused1: 14, // unused
|
|
21
|
+
chorusEffectsSend: 15, // effect send - how much is sent to chorus 0 - 1000
|
|
22
|
+
reverbEffectsSend: 16, // effect send - how much is sent to reverb 0 - 1000
|
|
23
|
+
pan: 17, // panning - where -500 = left, 0 = center, 500 = right
|
|
24
|
+
unused2: 18, // unused
|
|
25
|
+
unused3: 19, // unused
|
|
26
|
+
unused4: 20, // unused
|
|
27
|
+
delayModLFO: 21, // mod lfo - delay for mod lfo to start from zero
|
|
28
|
+
freqModLFO: 22, // mod lfo - frequency of mod lfo, 0 = 8.176 Hz, units: f => 1200log2(f/8.176)
|
|
29
|
+
delayVibLFO: 23, // vib lfo - delay for vibrato lfo to start from zero
|
|
30
|
+
freqVibLFO: 24, // vib lfo - frequency of vibrato lfo, 0 = 8.176Hz, unit: f => 1200log2(f/8.176)
|
|
31
|
+
delayModEnv: 25, // mod env - 0 = 1 s decay till mod env starts
|
|
32
|
+
attackModEnv: 26, // mod env - attack of mod env
|
|
33
|
+
holdModEnv: 27, // mod env - hold of mod env
|
|
34
|
+
decayModEnv: 28, // mod env - decay of mod env
|
|
35
|
+
sustainModEnv: 29, // mod env - sustain of mod env
|
|
36
|
+
releaseModEnv: 30, // mod env - release of mod env
|
|
37
|
+
keyNumToModEnvHold: 31, // mod env - also modulating mod envelope hold with key number
|
|
38
|
+
keyNumToModEnvDecay: 32, // mod env - also modulating mod envelope decay with key number
|
|
39
|
+
delayVolEnv: 33, // vol env - delay of envelope from zero (weird scale)
|
|
40
|
+
attackVolEnv: 34, // vol env - attack of envelope
|
|
41
|
+
holdVolEnv: 35, // vol env - hold of envelope
|
|
42
|
+
decayVolEnv: 36, // vol env - decay of envelope
|
|
43
|
+
sustainVolEnv: 37, // vol env - sustain of envelope
|
|
44
|
+
releaseVolEnv: 38, // vol env - release of envelope
|
|
45
|
+
keyNumToVolEnvHold: 39, // vol env - key number to volume envelope hold
|
|
46
|
+
keyNumToVolEnvDecay: 40, // vol env - key number to volume envelope decay
|
|
47
|
+
instrument: 41, // zone - instrument index to use for preset zone
|
|
48
|
+
reserved1: 42, // reserved
|
|
49
|
+
keyRange: 43, // zone - key range for which preset / instrument zone is active
|
|
50
|
+
velRange: 44, // zone - velocity range for which preset / instrument zone is active
|
|
51
|
+
startloopAddrsCoarseOffset: 45, // sample control - moves sample loop start point in 32,768 increments
|
|
52
|
+
keyNum: 46, // zone - instrument only: always use this midi number (ignore what's pressed)
|
|
53
|
+
velocity: 47, // zone - instrument only: always use this velocity (ignore what's pressed)
|
|
54
|
+
initialAttenuation: 48, // zone - allows turning down the volume, 10 = -1dB
|
|
55
|
+
reserved2: 49, // reserved
|
|
56
|
+
endloopAddrsCoarseOffset: 50, // sample control - moves sample loop end point in 32,768 increments
|
|
57
|
+
coarseTune: 51, // tune - pitch offset in semitones
|
|
58
|
+
fineTune: 52, // tune - pitch offset in cents
|
|
59
|
+
sampleID: 53, // sample - instrument zone only: which sample to use
|
|
60
|
+
sampleModes: 54, // sample - 0 = no loop, 1 = loop, 2 = reserved, 3 = loop and play till the end in release phase
|
|
61
|
+
reserved3: 55, // reserved
|
|
62
|
+
scaleTuning: 56, // sample - the degree to which MIDI key number influences pitch, 100 = default
|
|
63
|
+
exclusiveClass: 57, // sample - = cut = choke group
|
|
64
|
+
overridingRootKey: 58, // sample - can override the sample's original pitch
|
|
65
|
+
unused5: 59, // unused
|
|
66
|
+
endOper: 60 // end marker
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* @type {{min: number, max: number, def: number}[]}
|
|
70
|
+
*/
|
|
71
|
+
export const generatorLimits = [];
|
|
72
|
+
// offsets
|
|
73
|
+
generatorLimits[generatorTypes.startAddrsOffset] = { min: 0, max: 32768, def: 0 };
|
|
74
|
+
generatorLimits[generatorTypes.endAddrOffset] = { min: -32768, max: 32768, def: 0 };
|
|
75
|
+
generatorLimits[generatorTypes.startloopAddrsOffset] = { min: -32768, max: 32768, def: 0 };
|
|
76
|
+
generatorLimits[generatorTypes.endloopAddrsOffset] = { min: -32768, max: 32768, def: 0 };
|
|
77
|
+
generatorLimits[generatorTypes.startAddrsCoarseOffset] = { min: 0, max: 32768, def: 0 };
|
|
78
|
+
|
|
79
|
+
// pitch influence
|
|
80
|
+
generatorLimits[generatorTypes.modLfoToPitch] = { min: -12000, max: 12000, def: 0 };
|
|
81
|
+
generatorLimits[generatorTypes.vibLfoToPitch] = { min: -12000, max: 12000, def: 0 };
|
|
82
|
+
generatorLimits[generatorTypes.modEnvToPitch] = { min: -12000, max: 12000, def: 0 };
|
|
83
|
+
|
|
84
|
+
// lowpass
|
|
85
|
+
generatorLimits[generatorTypes.initialFilterFc] = { min: 1500, max: 13500, def: 13500 };
|
|
86
|
+
generatorLimits[generatorTypes.initialFilterQ] = { min: 0, max: 960, def: 0 };
|
|
87
|
+
generatorLimits[generatorTypes.modLfoToFilterFc] = { min: -12000, max: 12000, def: 0 };
|
|
88
|
+
generatorLimits[generatorTypes.modEnvToFilterFc] = { min: -12000, max: 12000, def: 0 };
|
|
89
|
+
|
|
90
|
+
generatorLimits[generatorTypes.endAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0 };
|
|
91
|
+
|
|
92
|
+
generatorLimits[generatorTypes.modLfoToVolume] = { min: -960, max: 960, def: 0 };
|
|
93
|
+
|
|
94
|
+
// effects, pan
|
|
95
|
+
generatorLimits[generatorTypes.chorusEffectsSend] = { min: 0, max: 1000, def: 0 };
|
|
96
|
+
generatorLimits[generatorTypes.reverbEffectsSend] = { min: 0, max: 1000, def: 0 };
|
|
97
|
+
generatorLimits[generatorTypes.pan] = { min: -500, max: 500, def: 0 };
|
|
98
|
+
|
|
99
|
+
// lfo
|
|
100
|
+
generatorLimits[generatorTypes.delayModLFO] = { min: -12000, max: 5000, def: -12000 };
|
|
101
|
+
generatorLimits[generatorTypes.freqModLFO] = { min: -16000, max: 4500, def: 0 };
|
|
102
|
+
generatorLimits[generatorTypes.delayVibLFO] = { min: -12000, max: 5000, def: -12000 };
|
|
103
|
+
generatorLimits[generatorTypes.freqVibLFO] = { min: -16000, max: 4500, def: 0 };
|
|
104
|
+
|
|
105
|
+
// mod env
|
|
106
|
+
generatorLimits[generatorTypes.delayModEnv] = { min: -32768, max: 5000, def: -32768 }; // -32,768 indicates instant phase,
|
|
107
|
+
// this is done to prevent click at the start of filter modenv
|
|
108
|
+
generatorLimits[generatorTypes.attackModEnv] = { min: -32768, max: 8000, def: -32768 };
|
|
109
|
+
generatorLimits[generatorTypes.holdModEnv] = { min: -12000, max: 5000, def: -12000 };
|
|
110
|
+
generatorLimits[generatorTypes.decayModEnv] = { min: -12000, max: 8000, def: -12000 };
|
|
111
|
+
generatorLimits[generatorTypes.sustainModEnv] = { min: 0, max: 1000, def: 0 };
|
|
112
|
+
generatorLimits[generatorTypes.releaseModEnv] = { min: -7200, max: 8000, def: -12000 }; // min is set to -7200 to prevent lowpass clicks
|
|
113
|
+
// key num to mod env
|
|
114
|
+
generatorLimits[generatorTypes.keyNumToModEnvHold] = { min: -1200, max: 1200, def: 0 };
|
|
115
|
+
generatorLimits[generatorTypes.keyNumToModEnvDecay] = { min: -1200, max: 1200, def: 0 };
|
|
116
|
+
|
|
117
|
+
// vol env
|
|
118
|
+
generatorLimits[generatorTypes.delayVolEnv] = { min: -12000, max: 5000, def: -12000 };
|
|
119
|
+
generatorLimits[generatorTypes.attackVolEnv] = { min: -12000, max: 8000, def: -12000 };
|
|
120
|
+
generatorLimits[generatorTypes.holdVolEnv] = { min: -12000, max: 5000, def: -12000 };
|
|
121
|
+
generatorLimits[generatorTypes.decayVolEnv] = { min: -12000, max: 8000, def: -12000 };
|
|
122
|
+
generatorLimits[generatorTypes.sustainVolEnv] = { min: 0, max: 1440, def: 0 };
|
|
123
|
+
generatorLimits[generatorTypes.releaseVolEnv] = { min: -7200, max: 8000, def: -12000 }; // min is set to -7200 prevent clicks
|
|
124
|
+
// key num to vol env
|
|
125
|
+
generatorLimits[generatorTypes.keyNumToVolEnvHold] = { min: -1200, max: 1200, def: 0 };
|
|
126
|
+
generatorLimits[generatorTypes.keyNumToVolEnvDecay] = { min: -1200, max: 1200, def: 0 };
|
|
127
|
+
|
|
128
|
+
generatorLimits[generatorTypes.startloopAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0 };
|
|
129
|
+
generatorLimits[generatorTypes.keyNum] = { min: -1, max: 127, def: -1 };
|
|
130
|
+
generatorLimits[generatorTypes.velocity] = { min: -1, max: 127, def: -1 };
|
|
131
|
+
|
|
132
|
+
generatorLimits[generatorTypes.initialAttenuation] = { min: 0, max: 1440, def: 0 };
|
|
133
|
+
|
|
134
|
+
generatorLimits[generatorTypes.endloopAddrsCoarseOffset] = { min: -32768, max: 32768, def: 0 };
|
|
135
|
+
|
|
136
|
+
generatorLimits[generatorTypes.coarseTune] = { min: -120, max: 120, def: 0 };
|
|
137
|
+
generatorLimits[generatorTypes.fineTune] = { min: -12700, max: 12700, def: 0 }; // this generator is used as initial pitch, hence this range
|
|
138
|
+
generatorLimits[generatorTypes.scaleTuning] = { min: 0, max: 1200, def: 100 };
|
|
139
|
+
generatorLimits[generatorTypes.exclusiveClass] = { min: 0, max: 99999, def: 0 };
|
|
140
|
+
generatorLimits[generatorTypes.overridingRootKey] = { min: 0 - 1, max: 127, def: -1 };
|
|
141
|
+
generatorLimits[generatorTypes.sampleModes] = { min: 0, max: 3, def: 0 };
|
|
142
|
+
|
|
143
|
+
export class Generator
|
|
144
|
+
{
|
|
145
|
+
/**
|
|
146
|
+
* The generator's enum number
|
|
147
|
+
* @type {generatorTypes|number}
|
|
148
|
+
*/
|
|
149
|
+
generatorType = generatorTypes.INVALID;
|
|
150
|
+
/**
|
|
151
|
+
* The generator's 16-bit value
|
|
152
|
+
* @type {number}
|
|
153
|
+
*/
|
|
154
|
+
generatorValue = 0;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Constructs a new generator
|
|
158
|
+
* @param type {generatorTypes|number}
|
|
159
|
+
* @param value {number}
|
|
160
|
+
* @param validate {boolean}
|
|
161
|
+
*/
|
|
162
|
+
constructor(type = generatorTypes.INVALID, value = 0, validate = true)
|
|
163
|
+
{
|
|
164
|
+
this.generatorType = type;
|
|
165
|
+
if (value === undefined)
|
|
166
|
+
{
|
|
167
|
+
throw new Error("No value provided.");
|
|
168
|
+
}
|
|
169
|
+
this.generatorValue = Math.round(value);
|
|
170
|
+
if (validate)
|
|
171
|
+
{
|
|
172
|
+
const lim = generatorLimits[type];
|
|
173
|
+
|
|
174
|
+
if (lim !== undefined)
|
|
175
|
+
{
|
|
176
|
+
this.generatorValue = Math.max(lim.min, Math.min(lim.max, this.generatorValue));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* generator.js
|
|
184
|
+
* purpose: contains enums for generators,
|
|
185
|
+
* and their limis parses reads soundfont generators, sums them and applies limits
|
|
186
|
+
*/
|
|
187
|
+
/**
|
|
188
|
+
* @param generatorType {number}
|
|
189
|
+
* @param presetGens {Generator[]}
|
|
190
|
+
* @param instrumentGens {Generator[]}
|
|
191
|
+
*/
|
|
192
|
+
export function addAndClampGenerator(generatorType, presetGens, instrumentGens)
|
|
193
|
+
{
|
|
194
|
+
const limits = generatorLimits[generatorType] || { min: 0, max: 32768, def: 0 };
|
|
195
|
+
let presetGen = presetGens.find(g => g.generatorType === generatorType);
|
|
196
|
+
let presetValue = 0;
|
|
197
|
+
if (presetGen)
|
|
198
|
+
{
|
|
199
|
+
presetValue = presetGen.generatorValue;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let instruGen = instrumentGens.find(g => g.generatorType === generatorType);
|
|
203
|
+
let instruValue = limits.def;
|
|
204
|
+
if (instruGen)
|
|
205
|
+
{
|
|
206
|
+
instruValue = instruGen.generatorValue;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
let value = instruValue + presetValue;
|
|
210
|
+
|
|
211
|
+
// Special case, initial attenuation.
|
|
212
|
+
// Shall get clamped in the volume envelope,
|
|
213
|
+
// so the modulators can be affected by negative generators (the "Brass" patch was problematic...)
|
|
214
|
+
if (generatorType === generatorTypes.initialAttenuation)
|
|
215
|
+
{
|
|
216
|
+
return value;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return Math.max(limits.min, Math.min(limits.max, value));
|
|
220
|
+
}
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { generatorTypes } from "./generator.js";
|
|
2
|
+
import { midiControllers } from "../../midi/midi_message.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* modulators.js
|
|
6
|
+
* purpose: parses soundfont modulators and the source enums, also includes the default modulators list
|
|
7
|
+
**/
|
|
8
|
+
|
|
9
|
+
export const modulatorSources = {
|
|
10
|
+
noController: 0,
|
|
11
|
+
noteOnVelocity: 2,
|
|
12
|
+
noteOnKeyNum: 3,
|
|
13
|
+
polyPressure: 10,
|
|
14
|
+
channelPressure: 13,
|
|
15
|
+
pitchWheel: 14,
|
|
16
|
+
pitchWheelRange: 16,
|
|
17
|
+
link: 127
|
|
18
|
+
|
|
19
|
+
};
|
|
20
|
+
export const modulatorCurveTypes = {
|
|
21
|
+
linear: 0,
|
|
22
|
+
concave: 1,
|
|
23
|
+
convex: 2,
|
|
24
|
+
switch: 3
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export class Modulator
|
|
28
|
+
{
|
|
29
|
+
/**
|
|
30
|
+
* The current computed value of this modulator
|
|
31
|
+
* @type {number}
|
|
32
|
+
*/
|
|
33
|
+
currentValue = 0;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The source enumeration for this modulator
|
|
37
|
+
* @type {number}
|
|
38
|
+
*/
|
|
39
|
+
sourceEnum;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The secondary source enumeration for this modulator
|
|
43
|
+
* @type {number}
|
|
44
|
+
*/
|
|
45
|
+
secondarySourceEnum;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The generator destination of this modulator
|
|
49
|
+
* @type {generatorTypes}
|
|
50
|
+
*/
|
|
51
|
+
modulatorDestination;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The transform amount for this modulator
|
|
55
|
+
* @type {number}
|
|
56
|
+
*/
|
|
57
|
+
transformAmount;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The transform type for this modulator
|
|
61
|
+
* @type {0|2}
|
|
62
|
+
*/
|
|
63
|
+
transformType;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* creates a modulator
|
|
67
|
+
* @param srcEnum {number}
|
|
68
|
+
* @param secSrcEnum {number}
|
|
69
|
+
* @param destination {generatorTypes|number}
|
|
70
|
+
* @param amount {number}
|
|
71
|
+
* @param transformType {number}
|
|
72
|
+
*/
|
|
73
|
+
constructor(srcEnum, secSrcEnum, destination, amount, transformType)
|
|
74
|
+
{
|
|
75
|
+
this.sourceEnum = srcEnum;
|
|
76
|
+
this.modulatorDestination = destination;
|
|
77
|
+
this.secondarySourceEnum = secSrcEnum;
|
|
78
|
+
this.transformAmount = amount;
|
|
79
|
+
this.transformType = transformType;
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if (this.modulatorDestination > 58)
|
|
83
|
+
{
|
|
84
|
+
this.modulatorDestination = generatorTypes.INVALID; // flag as invalid (for linked ones)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// decode the source
|
|
88
|
+
this.sourcePolarity = this.sourceEnum >> 9 & 1;
|
|
89
|
+
this.sourceDirection = this.sourceEnum >> 8 & 1;
|
|
90
|
+
this.sourceUsesCC = this.sourceEnum >> 7 & 1;
|
|
91
|
+
this.sourceIndex = this.sourceEnum & 127;
|
|
92
|
+
this.sourceCurveType = this.sourceEnum >> 10 & 3;
|
|
93
|
+
|
|
94
|
+
// decode the secondary source
|
|
95
|
+
this.secSrcPolarity = this.secondarySourceEnum >> 9 & 1;
|
|
96
|
+
this.secSrcDirection = this.secondarySourceEnum >> 8 & 1;
|
|
97
|
+
this.secSrcUsesCC = this.secondarySourceEnum >> 7 & 1;
|
|
98
|
+
this.secSrcIndex = this.secondarySourceEnum & 127;
|
|
99
|
+
this.secSrcCurveType = this.secondarySourceEnum >> 10 & 3;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Indicates if the given modulator is chorus or reverb effects modulator.
|
|
103
|
+
* This is done to simulate BASSMIDI effects behavior:
|
|
104
|
+
* - defaults to 1000 transform amount rather than 200
|
|
105
|
+
* - values can be changed, but anything above 200 is 1000
|
|
106
|
+
* (except for values above 1000, they are copied directly)
|
|
107
|
+
* - all values below are multiplied by 5 (200 * 5 = 1000)
|
|
108
|
+
* - still can be disabled if the soundfont has its own modulator curve
|
|
109
|
+
* - this fixes the very low amount of reverb by default and doesn't break soundfonts
|
|
110
|
+
* @type {boolean}
|
|
111
|
+
*/
|
|
112
|
+
this.isEffectModulator =
|
|
113
|
+
(
|
|
114
|
+
this.sourceEnum === 0x00DB
|
|
115
|
+
|| this.sourceEnum === 0x00DD
|
|
116
|
+
)
|
|
117
|
+
&& this.secondarySourceEnum === 0x0
|
|
118
|
+
&& (
|
|
119
|
+
this.modulatorDestination === generatorTypes.reverbEffectsSend
|
|
120
|
+
|| this.modulatorDestination === generatorTypes.chorusEffectsSend
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @param modulator {Modulator}
|
|
126
|
+
* @returns {Modulator}
|
|
127
|
+
*/
|
|
128
|
+
static copy(modulator)
|
|
129
|
+
{
|
|
130
|
+
return new Modulator(
|
|
131
|
+
modulator.sourceEnum,
|
|
132
|
+
modulator.secondarySourceEnum,
|
|
133
|
+
modulator.modulatorDestination,
|
|
134
|
+
modulator.transformAmount,
|
|
135
|
+
modulator.transformType
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param mod1 {Modulator}
|
|
141
|
+
* @param mod2 {Modulator}
|
|
142
|
+
* @param checkAmount {boolean}
|
|
143
|
+
* @returns {boolean}
|
|
144
|
+
*/
|
|
145
|
+
static isIdentical(mod1, mod2, checkAmount = false)
|
|
146
|
+
{
|
|
147
|
+
return (mod1.sourceEnum === mod2.sourceEnum)
|
|
148
|
+
&& (mod1.modulatorDestination === mod2.modulatorDestination)
|
|
149
|
+
&& (mod1.secondarySourceEnum === mod2.secondarySourceEnum)
|
|
150
|
+
&& (mod1.transformType === mod2.transformType)
|
|
151
|
+
&& (!checkAmount || (mod1.transformAmount === mod2.transformAmount));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @param mod {Modulator}
|
|
156
|
+
* @returns {string}
|
|
157
|
+
*/
|
|
158
|
+
static debugString(mod)
|
|
159
|
+
{
|
|
160
|
+
function getKeyByValue(object, value)
|
|
161
|
+
{
|
|
162
|
+
return Object.keys(object).find(key => object[key] === value);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
let sourceString = getKeyByValue(modulatorCurveTypes, mod.sourceCurveType);
|
|
166
|
+
sourceString += mod.sourcePolarity === 0 ? " unipolar " : " bipolar ";
|
|
167
|
+
sourceString += mod.sourceDirection === 0 ? "forwards " : "backwards ";
|
|
168
|
+
if (mod.sourceUsesCC)
|
|
169
|
+
{
|
|
170
|
+
sourceString += getKeyByValue(midiControllers, mod.sourceIndex);
|
|
171
|
+
}
|
|
172
|
+
else
|
|
173
|
+
{
|
|
174
|
+
sourceString += getKeyByValue(modulatorSources, mod.sourceIndex);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
let secSrcString = getKeyByValue(modulatorCurveTypes, mod.secSrcCurveType);
|
|
178
|
+
secSrcString += mod.secSrcPolarity === 0 ? " unipolar " : " bipolar ";
|
|
179
|
+
secSrcString += mod.secSrcCurveType === 0 ? "forwards " : "backwards ";
|
|
180
|
+
if (mod.secSrcUsesCC)
|
|
181
|
+
{
|
|
182
|
+
secSrcString += getKeyByValue(midiControllers, mod.secSrcIndex);
|
|
183
|
+
}
|
|
184
|
+
else
|
|
185
|
+
{
|
|
186
|
+
secSrcString += getKeyByValue(modulatorSources, mod.secSrcIndex);
|
|
187
|
+
}
|
|
188
|
+
return `Modulator:
|
|
189
|
+
Source: ${sourceString}
|
|
190
|
+
Secondary source: ${secSrcString}
|
|
191
|
+
Destination: ${getKeyByValue(generatorTypes, mod.modulatorDestination)}
|
|
192
|
+
Trasform amount: ${mod.transformAmount}
|
|
193
|
+
Transform type: ${mod.transformType}
|
|
194
|
+
\n\n`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Sum transform and create a NEW modulator
|
|
199
|
+
* @param modulator {Modulator}
|
|
200
|
+
* @returns {Modulator}
|
|
201
|
+
*/
|
|
202
|
+
sumTransform(modulator)
|
|
203
|
+
{
|
|
204
|
+
return new Modulator(
|
|
205
|
+
this.sourceEnum,
|
|
206
|
+
this.secondarySourceEnum,
|
|
207
|
+
this.modulatorDestination,
|
|
208
|
+
this.transformAmount + modulator.transformAmount,
|
|
209
|
+
this.transformType
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export const DEFAULT_ATTENUATION_MOD_AMOUNT = 960;
|
|
215
|
+
export const DEFAULT_ATTENUATION_MOD_CURVE_TYPE = modulatorCurveTypes.concave;
|
|
216
|
+
|
|
217
|
+
export function getModSourceEnum(curveType, polarity, direction, isCC, index)
|
|
218
|
+
{
|
|
219
|
+
return (curveType << 10) | (polarity << 9) | (direction << 8) | (isCC << 7) | index;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const soundFontModulators = [
|
|
223
|
+
// vel to attenuation
|
|
224
|
+
new Modulator(
|
|
225
|
+
getModSourceEnum(
|
|
226
|
+
DEFAULT_ATTENUATION_MOD_CURVE_TYPE,
|
|
227
|
+
0,
|
|
228
|
+
1,
|
|
229
|
+
0,
|
|
230
|
+
modulatorSources.noteOnVelocity
|
|
231
|
+
),
|
|
232
|
+
0x0,
|
|
233
|
+
generatorTypes.initialAttenuation,
|
|
234
|
+
DEFAULT_ATTENUATION_MOD_AMOUNT,
|
|
235
|
+
0
|
|
236
|
+
),
|
|
237
|
+
|
|
238
|
+
// mod wheel to vibrato
|
|
239
|
+
new Modulator(0x0081, 0x0, generatorTypes.vibLfoToPitch, 50, 0),
|
|
240
|
+
|
|
241
|
+
// vol to attenuation
|
|
242
|
+
new Modulator(
|
|
243
|
+
getModSourceEnum(
|
|
244
|
+
DEFAULT_ATTENUATION_MOD_CURVE_TYPE,
|
|
245
|
+
0,
|
|
246
|
+
1,
|
|
247
|
+
1,
|
|
248
|
+
midiControllers.mainVolume
|
|
249
|
+
),
|
|
250
|
+
0x0,
|
|
251
|
+
generatorTypes.initialAttenuation,
|
|
252
|
+
DEFAULT_ATTENUATION_MOD_AMOUNT,
|
|
253
|
+
0
|
|
254
|
+
),
|
|
255
|
+
|
|
256
|
+
// channel pressure to vibrato
|
|
257
|
+
new Modulator(0x000D, 0x0, generatorTypes.vibLfoToPitch, 50, 0),
|
|
258
|
+
|
|
259
|
+
// pitch wheel to tuning
|
|
260
|
+
new Modulator(0x020E, 0x0010, generatorTypes.fineTune, 12700, 0),
|
|
261
|
+
|
|
262
|
+
// pan to uhh, pan
|
|
263
|
+
// amount is 500 instead of 1000, see #59
|
|
264
|
+
new Modulator(0x028A, 0x0, generatorTypes.pan, 500, 0),
|
|
265
|
+
|
|
266
|
+
// expression to attenuation
|
|
267
|
+
new Modulator(
|
|
268
|
+
getModSourceEnum(
|
|
269
|
+
DEFAULT_ATTENUATION_MOD_CURVE_TYPE,
|
|
270
|
+
0,
|
|
271
|
+
1,
|
|
272
|
+
1,
|
|
273
|
+
midiControllers.expressionController
|
|
274
|
+
),
|
|
275
|
+
0x0,
|
|
276
|
+
generatorTypes.initialAttenuation,
|
|
277
|
+
DEFAULT_ATTENUATION_MOD_AMOUNT,
|
|
278
|
+
0
|
|
279
|
+
),
|
|
280
|
+
|
|
281
|
+
// reverb effects to send
|
|
282
|
+
new Modulator(0x00DB, 0x0, generatorTypes.reverbEffectsSend, 200, 0),
|
|
283
|
+
|
|
284
|
+
// chorus effects to send
|
|
285
|
+
new Modulator(0x00DD, 0x0, generatorTypes.chorusEffectsSend, 200, 0)
|
|
286
|
+
];
|
|
287
|
+
|
|
288
|
+
const customModulators = [
|
|
289
|
+
// custom modulators heck yeah
|
|
290
|
+
// poly pressure to vibrato
|
|
291
|
+
new Modulator(
|
|
292
|
+
getModSourceEnum(modulatorCurveTypes.linear, 0, 0, 0, modulatorSources.polyPressure),
|
|
293
|
+
0x0,
|
|
294
|
+
generatorTypes.vibLfoToPitch,
|
|
295
|
+
50,
|
|
296
|
+
0
|
|
297
|
+
),
|
|
298
|
+
|
|
299
|
+
// cc 92 (tremolo) to modLFO volume
|
|
300
|
+
new Modulator(
|
|
301
|
+
getModSourceEnum(
|
|
302
|
+
modulatorCurveTypes.linear,
|
|
303
|
+
0,
|
|
304
|
+
0,
|
|
305
|
+
1,
|
|
306
|
+
midiControllers.tremoloDepth
|
|
307
|
+
), /*linear forward unipolar cc 92 */
|
|
308
|
+
0x0, // no controller
|
|
309
|
+
generatorTypes.modLfoToVolume,
|
|
310
|
+
24,
|
|
311
|
+
0
|
|
312
|
+
),
|
|
313
|
+
|
|
314
|
+
// cc 73 (attack time) to volEnv attack
|
|
315
|
+
new Modulator(
|
|
316
|
+
getModSourceEnum(
|
|
317
|
+
modulatorCurveTypes.convex,
|
|
318
|
+
1,
|
|
319
|
+
0,
|
|
320
|
+
1,
|
|
321
|
+
midiControllers.attackTime
|
|
322
|
+
), // linear forward bipolar cc 72
|
|
323
|
+
0x0, // no controller
|
|
324
|
+
generatorTypes.attackVolEnv,
|
|
325
|
+
6000,
|
|
326
|
+
0
|
|
327
|
+
),
|
|
328
|
+
|
|
329
|
+
// cc 72 (release time) to volEnv release
|
|
330
|
+
new Modulator(
|
|
331
|
+
getModSourceEnum(
|
|
332
|
+
modulatorCurveTypes.linear,
|
|
333
|
+
1,
|
|
334
|
+
0,
|
|
335
|
+
1,
|
|
336
|
+
midiControllers.releaseTime
|
|
337
|
+
), // linear forward bipolar cc 72
|
|
338
|
+
0x0, // no controller
|
|
339
|
+
generatorTypes.releaseVolEnv,
|
|
340
|
+
3600,
|
|
341
|
+
0
|
|
342
|
+
),
|
|
343
|
+
|
|
344
|
+
// cc 74 (brightness) to filterFc
|
|
345
|
+
new Modulator(
|
|
346
|
+
getModSourceEnum(
|
|
347
|
+
modulatorCurveTypes.linear,
|
|
348
|
+
1,
|
|
349
|
+
0,
|
|
350
|
+
1,
|
|
351
|
+
midiControllers.brightness
|
|
352
|
+
), // linear forwards bipolar cc 74
|
|
353
|
+
0x0, // no controller
|
|
354
|
+
generatorTypes.initialFilterFc,
|
|
355
|
+
6000,
|
|
356
|
+
0
|
|
357
|
+
),
|
|
358
|
+
|
|
359
|
+
// cc 71 (filter Q) to filter Q
|
|
360
|
+
new Modulator(
|
|
361
|
+
getModSourceEnum(
|
|
362
|
+
modulatorCurveTypes.linear,
|
|
363
|
+
1,
|
|
364
|
+
0,
|
|
365
|
+
1,
|
|
366
|
+
midiControllers.filterResonance
|
|
367
|
+
), // linear forwards bipolar cc 74
|
|
368
|
+
0x0, // no controller
|
|
369
|
+
generatorTypes.initialFilterQ,
|
|
370
|
+
250,
|
|
371
|
+
0
|
|
372
|
+
)
|
|
373
|
+
];
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* @type {Modulator[]}
|
|
377
|
+
*/
|
|
378
|
+
export const defaultModulators = soundFontModulators.concat(customModulators);
|