spessasynth_lib 3.25.23 → 3.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -114
- package/external_midi/midi_handler.js +14 -14
- package/external_midi/web_midi_link.js +3 -3
- package/index.js +33 -33
- package/package.json +19 -6
- package/{midi → sequencer}/midi_data.js +1 -1
- package/sequencer/{worklet_wrapper/sequencer.js → sequencer.js} +13 -12
- package/sequencer/{worklet_wrapper/sequencer_message.js → sequencer_message.js} +1 -1
- package/synthetizer/README.md +29 -1
- package/synthetizer/audio_effects/reverb_as_binary.js +2 -2
- package/synthetizer/{worklet_wrapper/key_modifier_manager.js → key_modifier_manager.js} +11 -2
- package/synthetizer/{worklet_wrapper/synth_event_handler.js → synth_event_handler.js} +16 -13
- package/synthetizer/{worklet_wrapper/synth_soundfont_manager.js → synth_soundfont_manager.js} +8 -5
- package/synthetizer/{worklet_wrapper/synthetizer.js → synthetizer.js} +29 -23
- package/synthetizer/{audio_engine/message_protocol/worklet_message.js → worklet_message.js} +15 -2
- package/synthetizer/{worklet_wrapper/worklet_processor.js → worklet_processor.js} +214 -31
- package/synthetizer/worklet_processor.min.js +13 -12
- package/synthetizer/worklet_processor.min.js.map +7 -0
- package/synthetizer/{worklet_wrapper/worklet_url.js → worklet_url.js} +2 -0
- package/utils/buffer_to_wav.js +7 -165
- package/utils/other.js +3 -84
- package/externals/fflate/LICENSE +0 -21
- package/externals/fflate/fflate.min.js +0 -1
- package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
- package/externals/stbvorbis_sync/LICENSE +0 -202
- package/externals/stbvorbis_sync/NOTICE +0 -6
- package/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
- package/midi/README.md +0 -32
- package/midi/basic_midi.js +0 -565
- package/midi/midi_builder.js +0 -202
- package/midi/midi_loader.js +0 -324
- package/midi/midi_message.js +0 -254
- package/midi/midi_sequence.js +0 -225
- package/midi/midi_tools/get_note_times.js +0 -154
- package/midi/midi_tools/midi_editor.js +0 -611
- package/midi/midi_tools/midi_writer.js +0 -99
- package/midi/midi_tools/rmidi_writer.js +0 -567
- package/midi/midi_tools/used_keys_loaded.js +0 -238
- package/midi/xmf_loader.js +0 -454
- package/sequencer/sequencer_engine/events.js +0 -104
- package/sequencer/sequencer_engine/play.js +0 -353
- package/sequencer/sequencer_engine/process_event.js +0 -169
- package/sequencer/sequencer_engine/process_tick.js +0 -106
- package/sequencer/sequencer_engine/sequencer_engine.js +0 -335
- package/sequencer/sequencer_engine/song_control.js +0 -229
- package/soundfont/README.md +0 -13
- package/soundfont/basic_soundfont/basic_instrument.js +0 -77
- package/soundfont/basic_soundfont/basic_preset.js +0 -336
- package/soundfont/basic_soundfont/basic_sample.js +0 -197
- package/soundfont/basic_soundfont/basic_soundfont.js +0 -565
- package/soundfont/basic_soundfont/basic_zone.js +0 -64
- package/soundfont/basic_soundfont/basic_zones.js +0 -43
- package/soundfont/basic_soundfont/generator.js +0 -220
- package/soundfont/basic_soundfont/modulator.js +0 -378
- package/soundfont/basic_soundfont/riff_chunk.js +0 -149
- package/soundfont/basic_soundfont/write_dls/art2.js +0 -173
- package/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
- package/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -400
- package/soundfont/basic_soundfont/write_dls/ins.js +0 -103
- package/soundfont/basic_soundfont/write_dls/lins.js +0 -18
- package/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
- package/soundfont/basic_soundfont/write_dls/rgn2.js +0 -121
- package/soundfont/basic_soundfont/write_dls/wave.js +0 -94
- package/soundfont/basic_soundfont/write_dls/write_dls.js +0 -119
- package/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
- package/soundfont/basic_soundfont/write_dls/wvpl.js +0 -32
- package/soundfont/basic_soundfont/write_sf2/ibag.js +0 -39
- package/soundfont/basic_soundfont/write_sf2/igen.js +0 -80
- package/soundfont/basic_soundfont/write_sf2/imod.js +0 -46
- package/soundfont/basic_soundfont/write_sf2/inst.js +0 -34
- package/soundfont/basic_soundfont/write_sf2/pbag.js +0 -39
- package/soundfont/basic_soundfont/write_sf2/pgen.js +0 -82
- package/soundfont/basic_soundfont/write_sf2/phdr.js +0 -42
- package/soundfont/basic_soundfont/write_sf2/pmod.js +0 -46
- package/soundfont/basic_soundfont/write_sf2/sdta.js +0 -80
- package/soundfont/basic_soundfont/write_sf2/shdr.js +0 -55
- package/soundfont/basic_soundfont/write_sf2/write.js +0 -222
- package/soundfont/dls/articulator_converter.js +0 -396
- package/soundfont/dls/dls_destinations.js +0 -38
- package/soundfont/dls/dls_preset.js +0 -44
- package/soundfont/dls/dls_sample.js +0 -75
- package/soundfont/dls/dls_soundfont.js +0 -186
- package/soundfont/dls/dls_sources.js +0 -62
- package/soundfont/dls/dls_zone.js +0 -95
- package/soundfont/dls/read_articulation.js +0 -299
- package/soundfont/dls/read_instrument.js +0 -121
- package/soundfont/dls/read_instrument_list.js +0 -17
- package/soundfont/dls/read_lart.js +0 -35
- package/soundfont/dls/read_region.js +0 -152
- package/soundfont/dls/read_samples.js +0 -270
- package/soundfont/load_soundfont.js +0 -21
- package/soundfont/read_sf2/generators.js +0 -46
- package/soundfont/read_sf2/instruments.js +0 -66
- package/soundfont/read_sf2/modulators.js +0 -36
- package/soundfont/read_sf2/presets.js +0 -80
- package/soundfont/read_sf2/samples.js +0 -304
- package/soundfont/read_sf2/soundfont.js +0 -305
- package/soundfont/read_sf2/zones.js +0 -263
- package/synthetizer/audio_engine/README.md +0 -25
- package/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -266
- package/synthetizer/audio_engine/engine_components/controller_tables.js +0 -88
- package/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -149
- package/synthetizer/audio_engine/engine_components/lfo.js +0 -26
- package/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
- package/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -471
- package/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
- package/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
- package/synthetizer/audio_engine/engine_components/soundfont_manager.js +0 -228
- package/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -120
- package/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
- package/synthetizer/audio_engine/engine_components/voice.js +0 -519
- package/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -401
- package/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -263
- package/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -132
- package/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
- package/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -241
- package/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -27
- package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -253
- package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -66
- package/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
- package/synthetizer/audio_engine/engine_methods/note_on.js +0 -175
- package/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
- package/synthetizer/audio_engine/engine_methods/program_change.js +0 -61
- package/synthetizer/audio_engine/engine_methods/render_voice.js +0 -196
- package/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +0 -30
- package/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -22
- package/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +0 -40
- package/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +0 -34
- package/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +0 -21
- package/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -20
- package/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -55
- package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
- package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
- package/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
- package/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -776
- package/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -24
- package/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -33
- package/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -31
- package/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
- package/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
- package/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
- package/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
- package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
- package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
- package/synthetizer/audio_engine/main_processor.js +0 -765
- package/synthetizer/audio_engine/message_protocol/README.md +0 -13
- package/synthetizer/audio_engine/message_protocol/message_sending.js +0 -22
- package/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -14
- package/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
- package/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -122
- package/synthetizer/synth_constants.js +0 -20
- package/utils/README.md +0 -5
- package/utils/byte_functions/big_endian.js +0 -32
- package/utils/byte_functions/little_endian.js +0 -77
- package/utils/byte_functions/string.js +0 -107
- package/utils/byte_functions/variable_length_quantity.js +0 -42
- package/utils/indexed_array.js +0 -52
- package/utils/loggin.js +0 -79
- package/utils/sysex_detector.js +0 -58
- package/utils/xg_hacks.js +0 -193
- /package/sequencer/{worklet_wrapper/default_sequencer_options.js → default_sequencer_options.js} +0 -0
- /package/synthetizer/{worklet_wrapper/sfman_message.js → sfman_message.js} +0 -0
|
@@ -1,765 +0,0 @@
|
|
|
1
|
-
import { SpessaSynthSequencer } from "../../sequencer/sequencer_engine/sequencer_engine.js";
|
|
2
|
-
import { SpessaSynthInfo } from "../../utils/loggin.js";
|
|
3
|
-
import { consoleColors } from "../../utils/other.js";
|
|
4
|
-
import { voiceKilling } from "./engine_methods/stopping_notes/voice_killing.js";
|
|
5
|
-
import { ALL_CHANNELS_OR_DIFFERENT_ACTION, returnMessageType } from "./message_protocol/worklet_message.js";
|
|
6
|
-
import { stbvorbis } from "../../externals/stbvorbis_sync/stbvorbis_sync.min.js";
|
|
7
|
-
import { VOLUME_ENVELOPE_SMOOTHING_FACTOR } from "./engine_components/volume_envelope.js";
|
|
8
|
-
import { callEvent } from "./message_protocol/message_sending.js";
|
|
9
|
-
import { systemExclusive } from "./engine_methods/system_exclusive.js";
|
|
10
|
-
import { masterParameterType, setMasterParameter } from "./engine_methods/controller_control/master_parameters.js";
|
|
11
|
-
import { resetAllControllers } from "./engine_methods/controller_control/reset_controllers.js";
|
|
12
|
-
import { WorkletSoundfontManager } from "./engine_components/soundfont_manager.js";
|
|
13
|
-
import { interpolationTypes } from "./engine_components/wavetable_oscillator.js";
|
|
14
|
-
import { KeyModifierManager } from "./engine_components/key_modifier_manager.js";
|
|
15
|
-
import { getVoices } from "./engine_components/voice.js";
|
|
16
|
-
import { PAN_SMOOTHING_FACTOR } from "./engine_components/stereo_panner.js";
|
|
17
|
-
import { stopAllChannels } from "./engine_methods/stopping_notes/stop_all_channels.js";
|
|
18
|
-
import { setEmbeddedSoundFont } from "./engine_methods/soundfont_management/set_embedded_sound_font.js";
|
|
19
|
-
import { reloadSoundFont } from "./engine_methods/soundfont_management/reload_sound_font.js";
|
|
20
|
-
import { clearSoundFont } from "./engine_methods/soundfont_management/clear_sound_font.js";
|
|
21
|
-
import { sendPresetList } from "./engine_methods/soundfont_management/send_preset_list.js";
|
|
22
|
-
import { getPreset } from "./engine_methods/soundfont_management/get_preset.js";
|
|
23
|
-
import { transposeAllChannels } from "./engine_methods/tuning_control/transpose_all_channels.js";
|
|
24
|
-
import { setMasterTuning } from "./engine_methods/tuning_control/set_master_tuning.js";
|
|
25
|
-
import { applySynthesizerSnapshot } from "./snapshot/apply_synthesizer_snapshot.js";
|
|
26
|
-
import { createMidiChannel } from "./engine_methods/create_midi_channel.js";
|
|
27
|
-
import { FILTER_SMOOTHING_FACTOR } from "./engine_components/lowpass_filter.js";
|
|
28
|
-
import { DEFAULT_PERCUSSION, DEFAULT_SYNTH_MODE, VOICE_CAP } from "../synth_constants.js";
|
|
29
|
-
import { fillWithDefaults } from "../../utils/fill_with_defaults.js";
|
|
30
|
-
import { DEFAULT_SEQUENCER_OPTIONS } from "../../sequencer/worklet_wrapper/default_sequencer_options.js";
|
|
31
|
-
import { getEvent, messageTypes } from "../../midi/midi_message.js";
|
|
32
|
-
import { IndexedByteArray } from "../../utils/indexed_array.js";
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @typedef {"gm"|"gm2"|"gs"|"xg"} SynthSystem
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* main_processor.js
|
|
41
|
-
* purpose: the core synthesis engine
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
// if the note is released faster than that, it forced to last that long
|
|
45
|
-
// this is used mostly for drum channels, where a lot of midis like to send instant note off after a note on
|
|
46
|
-
export const MIN_NOTE_LENGTH = 0.03;
|
|
47
|
-
// this sounds way nicer for an instant hi-hat cutoff
|
|
48
|
-
export const MIN_EXCLUSIVE_LENGTH = 0.07;
|
|
49
|
-
|
|
50
|
-
export const SYNTHESIZER_GAIN = 1.0;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// the core synthesis engine of spessasynth.
|
|
54
|
-
class SpessaSynthProcessor
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Cached voices for all presets for this synthesizer.
|
|
59
|
-
* Nesting goes like this:
|
|
60
|
-
* this.cachedVoices[bankNumber][programNumber][midiNote][velocity] = a list of Voices for that.
|
|
61
|
-
* @type {Voice[][][][][]}
|
|
62
|
-
*/
|
|
63
|
-
cachedVoices = [];
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Synth's device id: -1 means all
|
|
67
|
-
* @type {number}
|
|
68
|
-
*/
|
|
69
|
-
deviceID = ALL_CHANNELS_OR_DIFFERENT_ACTION;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Synth's event queue from the main thread
|
|
73
|
-
* @type {{callback: function(), time: number}[]}
|
|
74
|
-
*/
|
|
75
|
-
eventQueue = [];
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Interpolation type used
|
|
79
|
-
* @type {interpolationTypes}
|
|
80
|
-
*/
|
|
81
|
-
interpolationType = interpolationTypes.fourthOrder;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* The sequencer attached to this processor
|
|
85
|
-
* @type {SpessaSynthSequencer}
|
|
86
|
-
*/
|
|
87
|
-
sequencer = new SpessaSynthSequencer(this);
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Global transposition in semitones
|
|
91
|
-
* @type {number}
|
|
92
|
-
*/
|
|
93
|
-
transposition = 0;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* this.tunings[program][key] = tuning
|
|
97
|
-
* @type {MTSProgramTuning[]}
|
|
98
|
-
*/
|
|
99
|
-
tunings = [];
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Bank offset for things like embedded RMIDIS. Added for every program change
|
|
104
|
-
* @type {number}
|
|
105
|
-
*/
|
|
106
|
-
soundfontBankOffset = 0;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* The volume gain, set by user
|
|
111
|
-
* @type {number}
|
|
112
|
-
*/
|
|
113
|
-
masterGain = SYNTHESIZER_GAIN;
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* The volume gain, set by MIDI sysEx
|
|
117
|
-
* @type {number}
|
|
118
|
-
*/
|
|
119
|
-
midiVolume = 1;
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Reverb linear gain
|
|
123
|
-
* @type {number}
|
|
124
|
-
*/
|
|
125
|
-
reverbGain = 1;
|
|
126
|
-
/**
|
|
127
|
-
* Chorus linear gain
|
|
128
|
-
* @type {number}
|
|
129
|
-
*/
|
|
130
|
-
chorusGain = 1;
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Maximum number of voices allowed at once
|
|
134
|
-
* @type {number}
|
|
135
|
-
*/
|
|
136
|
-
voiceCap = VOICE_CAP;
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* (-1 to 1)
|
|
140
|
-
* @type {number}
|
|
141
|
-
*/
|
|
142
|
-
pan = 0.0;
|
|
143
|
-
/**
|
|
144
|
-
* the pan of the left channel
|
|
145
|
-
* @type {number}
|
|
146
|
-
*/
|
|
147
|
-
panLeft = 0.5;
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* the pan of the right channel
|
|
151
|
-
* @type {number}
|
|
152
|
-
*/
|
|
153
|
-
panRight = 0.5;
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* forces note killing instead of releasing
|
|
157
|
-
* @type {boolean}
|
|
158
|
-
*/
|
|
159
|
-
highPerformanceMode = false;
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Handlese custom key overrides: velocity and preset
|
|
163
|
-
* @type {KeyModifierManager}
|
|
164
|
-
*/
|
|
165
|
-
keyModifierManager = new KeyModifierManager();
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Overrides the main soundfont (embedded, for example)
|
|
169
|
-
* @type {BasicSoundBank}
|
|
170
|
-
*/
|
|
171
|
-
overrideSoundfont = undefined;
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* contains all the channels with their voices on the processor size
|
|
175
|
-
* @type {MidiAudioChannel[]}
|
|
176
|
-
*/
|
|
177
|
-
midiAudioChannels = [];
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Controls the bank selection & SysEx
|
|
181
|
-
* @type {SynthSystem}
|
|
182
|
-
*/
|
|
183
|
-
system = DEFAULT_SYNTH_MODE;
|
|
184
|
-
/**
|
|
185
|
-
* Current total voices amount
|
|
186
|
-
* @type {number}
|
|
187
|
-
*/
|
|
188
|
-
totalVoicesAmount = 0;
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Synth's default (reset) preset
|
|
192
|
-
* @type {BasicPreset}
|
|
193
|
-
*/
|
|
194
|
-
defaultPreset;
|
|
195
|
-
|
|
196
|
-
defaultPresetUsesOverride = false;
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Synth's default (reset) drum preset
|
|
200
|
-
* @type {BasicPreset}
|
|
201
|
-
*/
|
|
202
|
-
drumPreset;
|
|
203
|
-
|
|
204
|
-
defaultDrumsUsesOverride = false;
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Controls if the worklet processor is fully initialized
|
|
208
|
-
* @type {Promise<boolean>}
|
|
209
|
-
*/
|
|
210
|
-
processorInitialized = stbvorbis.isInitialized;
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Current audio time
|
|
214
|
-
* @type {number}
|
|
215
|
-
*/
|
|
216
|
-
currentSynthTime = 0;
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* in hertz
|
|
220
|
-
* @type {number}
|
|
221
|
-
*/
|
|
222
|
-
sampleRate;
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Creates a new worklet synthesis system. contains all channels
|
|
226
|
-
* @param midiChannels {number}
|
|
227
|
-
* @param soundfont {ArrayBuffer}
|
|
228
|
-
* @param enableEventSystem {boolean}
|
|
229
|
-
* @param startRenderingData {StartRenderingDataConfig}
|
|
230
|
-
* @param postCallback {function(data: WorkletReturnMessage)}
|
|
231
|
-
* @param sampleRate {number}
|
|
232
|
-
* @param initialTime {number}
|
|
233
|
-
* @param effectsEnabled {boolean}
|
|
234
|
-
*/
|
|
235
|
-
constructor(midiChannels,
|
|
236
|
-
soundfont,
|
|
237
|
-
sampleRate,
|
|
238
|
-
postCallback,
|
|
239
|
-
effectsEnabled = true,
|
|
240
|
-
enableEventSystem = true,
|
|
241
|
-
startRenderingData = {},
|
|
242
|
-
initialTime = 0)
|
|
243
|
-
{
|
|
244
|
-
/**
|
|
245
|
-
* Midi output count
|
|
246
|
-
* @type {number}
|
|
247
|
-
*/
|
|
248
|
-
this.midiOutputsCount = midiChannels;
|
|
249
|
-
/**
|
|
250
|
-
* are the chorus and reverb effects enabled?
|
|
251
|
-
* @type {boolean}
|
|
252
|
-
*/
|
|
253
|
-
this.effectsEnabled = effectsEnabled;
|
|
254
|
-
let initialChannelCount = this.midiOutputsCount;
|
|
255
|
-
/**
|
|
256
|
-
* @type {function(WorkletReturnMessage)}
|
|
257
|
-
*/
|
|
258
|
-
this.postCallback = postCallback;
|
|
259
|
-
|
|
260
|
-
this.currentSynthTime = initialTime;
|
|
261
|
-
this.sampleRate = sampleRate;
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Sample time in seconds
|
|
265
|
-
* @type {number}
|
|
266
|
-
*/
|
|
267
|
-
this.sampleTime = 1 / sampleRate;
|
|
268
|
-
|
|
269
|
-
this.enableEventSystem = enableEventSystem && typeof postCallback === "function";
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
for (let i = 0; i < 128; i++)
|
|
273
|
-
{
|
|
274
|
-
this.tunings.push([]);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
try
|
|
278
|
-
{
|
|
279
|
-
/**
|
|
280
|
-
* @type {WorkletSoundfontManager}
|
|
281
|
-
*/
|
|
282
|
-
this.soundfontManager = new WorkletSoundfontManager(
|
|
283
|
-
soundfont,
|
|
284
|
-
this.postReady.bind(this)
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
catch (e)
|
|
288
|
-
{
|
|
289
|
-
this.post({
|
|
290
|
-
messageType: returnMessageType.soundfontError,
|
|
291
|
-
messageData: e
|
|
292
|
-
});
|
|
293
|
-
throw e;
|
|
294
|
-
}
|
|
295
|
-
this.sendPresetList();
|
|
296
|
-
|
|
297
|
-
this.getDefaultPresets();
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
for (let i = 0; i < initialChannelCount; i++)
|
|
301
|
-
{
|
|
302
|
-
this.createWorkletChannel(false);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
this.midiAudioChannels[DEFAULT_PERCUSSION].preset = this.drumPreset;
|
|
306
|
-
this.midiAudioChannels[DEFAULT_PERCUSSION].drumChannel = true;
|
|
307
|
-
|
|
308
|
-
// these smoothing factors were tested on 44,100 Hz, adjust them to target sample rate here
|
|
309
|
-
this.volumeEnvelopeSmoothingFactor = VOLUME_ENVELOPE_SMOOTHING_FACTOR * (44100 / sampleRate);
|
|
310
|
-
this.panSmoothingFactor = PAN_SMOOTHING_FACTOR * (44100 / sampleRate);
|
|
311
|
-
this.filterSmoothingFactor = FILTER_SMOOTHING_FACTOR * (44100 / sampleRate);
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* The snapshot that synth was restored from
|
|
315
|
-
* @type {SynthesizerSnapshot|undefined}
|
|
316
|
-
* @private
|
|
317
|
-
*/
|
|
318
|
-
this._snapshot = startRenderingData?.snapshot;
|
|
319
|
-
|
|
320
|
-
// if sent, start rendering
|
|
321
|
-
if (startRenderingData)
|
|
322
|
-
{
|
|
323
|
-
if (this._snapshot !== undefined)
|
|
324
|
-
{
|
|
325
|
-
this.applySynthesizerSnapshot(this._snapshot);
|
|
326
|
-
this.resetAllControllers();
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
SpessaSynthInfo("%cRendering enabled! Starting render.", consoleColors.info);
|
|
330
|
-
if (startRenderingData.parsedMIDI)
|
|
331
|
-
{
|
|
332
|
-
if (startRenderingData?.loopCount !== undefined)
|
|
333
|
-
{
|
|
334
|
-
this.sequencer.loopCount = startRenderingData?.loopCount;
|
|
335
|
-
this.sequencer.loop = true;
|
|
336
|
-
}
|
|
337
|
-
else
|
|
338
|
-
{
|
|
339
|
-
this.sequencer.loop = false;
|
|
340
|
-
}
|
|
341
|
-
// set voice cap to unlimited
|
|
342
|
-
this.voiceCap = Infinity;
|
|
343
|
-
this.processorInitialized.then(() =>
|
|
344
|
-
{
|
|
345
|
-
/**
|
|
346
|
-
* set options
|
|
347
|
-
* @type {SequencerOptions}
|
|
348
|
-
*/
|
|
349
|
-
const seqOptions = fillWithDefaults(
|
|
350
|
-
startRenderingData.sequencerOptions,
|
|
351
|
-
DEFAULT_SEQUENCER_OPTIONS
|
|
352
|
-
);
|
|
353
|
-
this.sequencer.skipToFirstNoteOn = seqOptions.skipToFirstNoteOn;
|
|
354
|
-
this.sequencer.preservePlaybackState = seqOptions.preservePlaybackState;
|
|
355
|
-
// autoplay is ignored
|
|
356
|
-
this.sequencer.loadNewSongList([startRenderingData.parsedMIDI]);
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
this.postReady();
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* @returns {number}
|
|
366
|
-
*/
|
|
367
|
-
get currentGain()
|
|
368
|
-
{
|
|
369
|
-
return this.masterGain * this.midiVolume;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
getDefaultPresets()
|
|
373
|
-
{
|
|
374
|
-
// override this to XG, to set the default preset to NOT be XG drums!
|
|
375
|
-
const sys = this.system;
|
|
376
|
-
this.system = "xg";
|
|
377
|
-
this.defaultPreset = this.getPreset(0, 0);
|
|
378
|
-
this.defaultPresetUsesOverride = this.overrideSoundfont?.presets?.indexOf(this.defaultPreset) >= 0;
|
|
379
|
-
this.system = sys;
|
|
380
|
-
this.drumPreset = this.getPreset(128, 0);
|
|
381
|
-
this.defaultDrumsUsesOverride = this.overrideSoundfont?.presets?.indexOf(this.drumPreset) >= 0;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* @param value {SynthSystem}
|
|
386
|
-
*/
|
|
387
|
-
setSystem(value)
|
|
388
|
-
{
|
|
389
|
-
this.system = value;
|
|
390
|
-
this.post({
|
|
391
|
-
messageType: returnMessageType.masterParameterChange,
|
|
392
|
-
messageData: [masterParameterType.midiSystem, this.system]
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* @param bank {number}
|
|
398
|
-
* @param program {number}
|
|
399
|
-
* @param midiNote {number}
|
|
400
|
-
* @param velocity {number}
|
|
401
|
-
* @returns {Voice[]|undefined}
|
|
402
|
-
*/
|
|
403
|
-
getCachedVoice(bank, program, midiNote, velocity)
|
|
404
|
-
{
|
|
405
|
-
return this.cachedVoices?.[bank]?.[program]?.[midiNote]?.[velocity];
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* @param bank {number}
|
|
410
|
-
* @param program {number}
|
|
411
|
-
* @param midiNote {number}
|
|
412
|
-
* @param velocity {number}
|
|
413
|
-
* @param voices {Voice[]}
|
|
414
|
-
*/
|
|
415
|
-
setCachedVoice(bank, program, midiNote, velocity, voices)
|
|
416
|
-
{
|
|
417
|
-
// make sure that it exists
|
|
418
|
-
if (!this.cachedVoices)
|
|
419
|
-
{
|
|
420
|
-
this.cachedVoices = [];
|
|
421
|
-
}
|
|
422
|
-
if (!this.cachedVoices[bank])
|
|
423
|
-
{
|
|
424
|
-
this.cachedVoices[bank] = [];
|
|
425
|
-
}
|
|
426
|
-
if (!this.cachedVoices[bank][program])
|
|
427
|
-
{
|
|
428
|
-
this.cachedVoices[bank][program] = [];
|
|
429
|
-
}
|
|
430
|
-
if (!this.cachedVoices[bank][program][midiNote])
|
|
431
|
-
{
|
|
432
|
-
this.cachedVoices[bank][program][midiNote] = [];
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// cache
|
|
436
|
-
this.cachedVoices[bank][program][midiNote][velocity] = voices;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
/**
|
|
441
|
-
* @param data {WorkletReturnMessage}
|
|
442
|
-
* @param force {boolean}
|
|
443
|
-
*/
|
|
444
|
-
post(data, force = false)
|
|
445
|
-
{
|
|
446
|
-
if (!this.enableEventSystem && !force)
|
|
447
|
-
{
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
if (this.postCallback)
|
|
451
|
-
{
|
|
452
|
-
this.postCallback(data);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
postReady()
|
|
457
|
-
{
|
|
458
|
-
// ensure stbvorbis is fully initialized
|
|
459
|
-
this.processorInitialized.then(() =>
|
|
460
|
-
{
|
|
461
|
-
// post-ready cannot be constrained by the event system
|
|
462
|
-
this.post({
|
|
463
|
-
messageType: returnMessageType.isFullyInitialized,
|
|
464
|
-
messageData: undefined
|
|
465
|
-
}, true);
|
|
466
|
-
SpessaSynthInfo("%cSpessaSynth is ready!", consoleColors.recognized);
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
debugMessage()
|
|
471
|
-
{
|
|
472
|
-
SpessaSynthInfo({
|
|
473
|
-
channels: this.midiAudioChannels,
|
|
474
|
-
voicesAmount: this.totalVoicesAmount
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// noinspection JSUnusedGlobalSymbols
|
|
479
|
-
/**
|
|
480
|
-
* Renders float32 audio data to stereo outputs; buffer size of 128 is recommended
|
|
481
|
-
* All float arrays must have the same length
|
|
482
|
-
* @param outputs {Float32Array[]} output stereo channels (L, R)
|
|
483
|
-
* @param reverb {Float32Array[]} reverb stereo channels (L, R)
|
|
484
|
-
* @param chorus {Float32Array[]} chorus stereo channels (L, R)
|
|
485
|
-
*/
|
|
486
|
-
renderAudio(outputs, reverb, chorus)
|
|
487
|
-
{
|
|
488
|
-
this.renderAudioSplit(reverb, chorus, Array(16).fill(outputs));
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
/**
|
|
492
|
-
* Renders the float32 audio data of each channel; buffer size of 128 is recommended
|
|
493
|
-
* All float arrays must have the same length
|
|
494
|
-
* @param reverbChannels {Float32Array[]} reverb stereo channels (L, R)
|
|
495
|
-
* @param chorusChannels {Float32Array[]} chorus stereo channels (L, R)
|
|
496
|
-
* @param separateChannels {Float32Array[][]} a total of 16 stereo pairs (L, R) for each MIDI channel
|
|
497
|
-
*/
|
|
498
|
-
renderAudioSplit(reverbChannels, chorusChannels, separateChannels)
|
|
499
|
-
{
|
|
500
|
-
// process the sequencer playback
|
|
501
|
-
this.sequencer.processTick();
|
|
502
|
-
|
|
503
|
-
// process event queue
|
|
504
|
-
const time = this.currentSynthTime;
|
|
505
|
-
while (this.eventQueue[0]?.time <= time)
|
|
506
|
-
{
|
|
507
|
-
this.eventQueue.shift().callback();
|
|
508
|
-
}
|
|
509
|
-
const revL = reverbChannels[0];
|
|
510
|
-
const revR = reverbChannels[1];
|
|
511
|
-
const chrL = chorusChannels[0];
|
|
512
|
-
const chrR = chorusChannels[1];
|
|
513
|
-
|
|
514
|
-
// for every channel
|
|
515
|
-
this.totalVoicesAmount = 0;
|
|
516
|
-
this.midiAudioChannels.forEach((channel, index) =>
|
|
517
|
-
{
|
|
518
|
-
if (channel.voices.length < 1 || channel.isMuted)
|
|
519
|
-
{
|
|
520
|
-
// there's nothing to do!
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
|
-
let voiceCount = channel.voices.length;
|
|
524
|
-
const ch = index % 16;
|
|
525
|
-
|
|
526
|
-
// render to the appropriate output
|
|
527
|
-
channel.renderAudio(
|
|
528
|
-
separateChannels[ch][0], separateChannels[ch][1],
|
|
529
|
-
revL, revR,
|
|
530
|
-
chrL, chrR
|
|
531
|
-
);
|
|
532
|
-
|
|
533
|
-
this.totalVoicesAmount += channel.voices.length;
|
|
534
|
-
// if voice count changed, update voice amount
|
|
535
|
-
if (channel.voices.length !== voiceCount)
|
|
536
|
-
{
|
|
537
|
-
channel.sendChannelProperty();
|
|
538
|
-
}
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
// advance the time appropriately
|
|
542
|
-
this.currentSynthTime += separateChannels[0][0].length * this.sampleTime;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
destroySynthProcessor()
|
|
546
|
-
{
|
|
547
|
-
this.midiAudioChannels.forEach(c =>
|
|
548
|
-
{
|
|
549
|
-
delete c.midiControllers;
|
|
550
|
-
delete c.voices;
|
|
551
|
-
delete c.sustainedVoices;
|
|
552
|
-
delete c.lockedControllers;
|
|
553
|
-
delete c.preset;
|
|
554
|
-
delete c.customControllers;
|
|
555
|
-
});
|
|
556
|
-
delete this.cachedVoices;
|
|
557
|
-
delete this.midiAudioChannels;
|
|
558
|
-
delete this.sequencer.midiData;
|
|
559
|
-
delete this.sequencer;
|
|
560
|
-
this.soundfontManager.destroyManager();
|
|
561
|
-
delete this.soundfontManager;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
/**
|
|
565
|
-
* @param channel {number}
|
|
566
|
-
* @param controllerNumber {number}
|
|
567
|
-
* @param controllerValue {number}
|
|
568
|
-
* @param force {boolean}
|
|
569
|
-
*/
|
|
570
|
-
controllerChange(channel, controllerNumber, controllerValue, force = false)
|
|
571
|
-
{
|
|
572
|
-
this.midiAudioChannels[channel].controllerChange(controllerNumber, controllerValue, force);
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
/**
|
|
576
|
-
* @param channel {number}
|
|
577
|
-
* @param midiNote {number}
|
|
578
|
-
* @param velocity {number}
|
|
579
|
-
*/
|
|
580
|
-
noteOn(channel, midiNote, velocity)
|
|
581
|
-
{
|
|
582
|
-
this.midiAudioChannels[channel].noteOn(midiNote, velocity);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
/**
|
|
586
|
-
* @param channel {number}
|
|
587
|
-
* @param midiNote {number}
|
|
588
|
-
*/
|
|
589
|
-
noteOff(channel, midiNote)
|
|
590
|
-
{
|
|
591
|
-
this.midiAudioChannels[channel].noteOff(midiNote);
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
* @param channel {number}
|
|
596
|
-
* @param midiNote {number}
|
|
597
|
-
* @param pressure {number}
|
|
598
|
-
*/
|
|
599
|
-
polyPressure(channel, midiNote, pressure)
|
|
600
|
-
{
|
|
601
|
-
this.midiAudioChannels[channel].polyPressure(midiNote, pressure);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
/**
|
|
605
|
-
* @param channel {number}
|
|
606
|
-
* @param pressure {number}
|
|
607
|
-
*/
|
|
608
|
-
channelPressure(channel, pressure)
|
|
609
|
-
{
|
|
610
|
-
this.midiAudioChannels[channel].channelPressure(pressure);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
/**
|
|
614
|
-
* @param channel {number}
|
|
615
|
-
* @param MSB {number}
|
|
616
|
-
* @param LSB {number}
|
|
617
|
-
*/
|
|
618
|
-
pitchWheel(channel, MSB, LSB)
|
|
619
|
-
{
|
|
620
|
-
this.midiAudioChannels[channel].pitchWheel(MSB, LSB);
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
/**
|
|
624
|
-
* @param channel {number}
|
|
625
|
-
* @param programNumber {number}
|
|
626
|
-
*/
|
|
627
|
-
programChange(channel, programNumber)
|
|
628
|
-
{
|
|
629
|
-
this.midiAudioChannels[channel].programChange(programNumber);
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* @param message {Uint8Array}
|
|
634
|
-
* @param channelOffset {number}
|
|
635
|
-
* @param force {boolean} cool stuff
|
|
636
|
-
* @param options {SynthMethodOptions}
|
|
637
|
-
*/
|
|
638
|
-
processMessage(message, channelOffset, force, options)
|
|
639
|
-
{
|
|
640
|
-
const call = () =>
|
|
641
|
-
{
|
|
642
|
-
const statusByteData = getEvent(message[0]);
|
|
643
|
-
|
|
644
|
-
const channel = statusByteData.channel + channelOffset;
|
|
645
|
-
// process the event
|
|
646
|
-
switch (statusByteData.status)
|
|
647
|
-
{
|
|
648
|
-
case messageTypes.noteOn:
|
|
649
|
-
const velocity = message[2];
|
|
650
|
-
if (velocity > 0)
|
|
651
|
-
{
|
|
652
|
-
this.noteOn(channel, message[1], velocity);
|
|
653
|
-
}
|
|
654
|
-
else
|
|
655
|
-
{
|
|
656
|
-
this.noteOff(channel, message[1]);
|
|
657
|
-
}
|
|
658
|
-
break;
|
|
659
|
-
|
|
660
|
-
case messageTypes.noteOff:
|
|
661
|
-
if (force)
|
|
662
|
-
{
|
|
663
|
-
this.midiAudioChannels[channel].killNote(message[1]);
|
|
664
|
-
}
|
|
665
|
-
else
|
|
666
|
-
{
|
|
667
|
-
this.noteOff(channel, message[1]);
|
|
668
|
-
}
|
|
669
|
-
break;
|
|
670
|
-
|
|
671
|
-
case messageTypes.pitchBend:
|
|
672
|
-
this.pitchWheel(channel, message[2], message[1]);
|
|
673
|
-
break;
|
|
674
|
-
|
|
675
|
-
case messageTypes.controllerChange:
|
|
676
|
-
this.controllerChange(channel, message[1], message[2], force);
|
|
677
|
-
break;
|
|
678
|
-
|
|
679
|
-
case messageTypes.programChange:
|
|
680
|
-
this.programChange(channel, message[1]);
|
|
681
|
-
break;
|
|
682
|
-
|
|
683
|
-
case messageTypes.polyPressure:
|
|
684
|
-
this.polyPressure(channel, message[0], message[1]);
|
|
685
|
-
break;
|
|
686
|
-
|
|
687
|
-
case messageTypes.channelPressure:
|
|
688
|
-
this.channelPressure(channel, message[1]);
|
|
689
|
-
break;
|
|
690
|
-
|
|
691
|
-
case messageTypes.systemExclusive:
|
|
692
|
-
this.systemExclusive(new IndexedByteArray(message.slice(1)), channelOffset);
|
|
693
|
-
break;
|
|
694
|
-
|
|
695
|
-
case messageTypes.reset:
|
|
696
|
-
this.stopAllChannels(true);
|
|
697
|
-
this.resetAllControllers();
|
|
698
|
-
break;
|
|
699
|
-
|
|
700
|
-
default:
|
|
701
|
-
break;
|
|
702
|
-
}
|
|
703
|
-
};
|
|
704
|
-
|
|
705
|
-
const time = options.time;
|
|
706
|
-
if (time > this.currentSynthTime)
|
|
707
|
-
{
|
|
708
|
-
this.eventQueue.push({
|
|
709
|
-
callback: call.bind(this),
|
|
710
|
-
time: time
|
|
711
|
-
});
|
|
712
|
-
this.eventQueue.sort((e1, e2) => e1.time - e2.time);
|
|
713
|
-
}
|
|
714
|
-
else
|
|
715
|
-
{
|
|
716
|
-
call();
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
/**
|
|
721
|
-
* @param volume {number} 0 to 1
|
|
722
|
-
*/
|
|
723
|
-
setMIDIVolume(volume)
|
|
724
|
-
{
|
|
725
|
-
// GM2 specification, section 4.1: volume is squared.
|
|
726
|
-
// though, according to my own testing, Math.E seems like a better choice
|
|
727
|
-
this.midiVolume = Math.pow(volume, Math.E);
|
|
728
|
-
this.setMasterParameter(masterParameterType.masterPan, this.pan);
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
// include other methods
|
|
733
|
-
// voice related
|
|
734
|
-
SpessaSynthProcessor.prototype.voiceKilling = voiceKilling;
|
|
735
|
-
SpessaSynthProcessor.prototype.getVoices = getVoices;
|
|
736
|
-
|
|
737
|
-
// message port related
|
|
738
|
-
SpessaSynthProcessor.prototype.callEvent = callEvent;
|
|
739
|
-
|
|
740
|
-
// system-exclusive related
|
|
741
|
-
SpessaSynthProcessor.prototype.systemExclusive = systemExclusive;
|
|
742
|
-
|
|
743
|
-
// channel related
|
|
744
|
-
SpessaSynthProcessor.prototype.stopAllChannels = stopAllChannels;
|
|
745
|
-
SpessaSynthProcessor.prototype.createWorkletChannel = createMidiChannel;
|
|
746
|
-
SpessaSynthProcessor.prototype.resetAllControllers = resetAllControllers;
|
|
747
|
-
|
|
748
|
-
// master parameter related
|
|
749
|
-
SpessaSynthProcessor.prototype.setMasterParameter = setMasterParameter;
|
|
750
|
-
|
|
751
|
-
// tuning related
|
|
752
|
-
SpessaSynthProcessor.prototype.transposeAllChannels = transposeAllChannels;
|
|
753
|
-
SpessaSynthProcessor.prototype.setMasterTuning = setMasterTuning;
|
|
754
|
-
|
|
755
|
-
// program related
|
|
756
|
-
SpessaSynthProcessor.prototype.getPreset = getPreset;
|
|
757
|
-
SpessaSynthProcessor.prototype.reloadSoundFont = reloadSoundFont;
|
|
758
|
-
SpessaSynthProcessor.prototype.clearSoundFont = clearSoundFont;
|
|
759
|
-
SpessaSynthProcessor.prototype.setEmbeddedSoundFont = setEmbeddedSoundFont;
|
|
760
|
-
SpessaSynthProcessor.prototype.sendPresetList = sendPresetList;
|
|
761
|
-
|
|
762
|
-
// snapshot related
|
|
763
|
-
SpessaSynthProcessor.prototype.applySynthesizerSnapshot = applySynthesizerSnapshot;
|
|
764
|
-
|
|
765
|
-
export { SpessaSynthProcessor };
|