spessasynth_core 3.27.7 → 4.0.0
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 +188 -116
- package/dist/index.d.ts +4057 -0
- package/dist/index.js +17188 -0
- package/dist/index.js.map +1 -0
- package/package.json +23 -6
- package/index.js +0 -132
- package/src/externals/README.md +0 -6
- package/src/externals/fflate/LICENSE +0 -21
- package/src/externals/fflate/fflate.min.js +0 -1
- package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
- package/src/externals/stbvorbis_sync/LICENSE +0 -202
- package/src/externals/stbvorbis_sync/NOTICE +0 -6
- package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
- package/src/midi/README.md +0 -32
- package/src/midi/basic_midi.js +0 -587
- package/src/midi/midi_builder.js +0 -203
- package/src/midi/midi_loader.js +0 -321
- package/src/midi/midi_message.js +0 -254
- package/src/midi/midi_sequence.js +0 -230
- package/src/midi/midi_tools/get_note_times.js +0 -154
- package/src/midi/midi_tools/midi_editor.js +0 -611
- package/src/midi/midi_tools/midi_writer.js +0 -105
- package/src/midi/midi_tools/rmidi_writer.js +0 -566
- package/src/midi/midi_tools/used_keys_loaded.js +0 -256
- package/src/midi/xmf_loader.js +0 -454
- package/src/sequencer/README.md +0 -9
- package/src/sequencer/events.js +0 -81
- package/src/sequencer/play.js +0 -362
- package/src/sequencer/process_event.js +0 -165
- package/src/sequencer/process_tick.js +0 -104
- package/src/sequencer/sequencer_engine.js +0 -372
- package/src/sequencer/song_control.js +0 -196
- package/src/soundfont/README.md +0 -11
- package/src/soundfont/basic_soundfont/basic_global_zone.js +0 -6
- package/src/soundfont/basic_soundfont/basic_instrument.js +0 -115
- package/src/soundfont/basic_soundfont/basic_instrument_zone.js +0 -45
- package/src/soundfont/basic_soundfont/basic_preset.js +0 -313
- package/src/soundfont/basic_soundfont/basic_preset_zone.js +0 -39
- package/src/soundfont/basic_soundfont/basic_sample.js +0 -477
- package/src/soundfont/basic_soundfont/basic_soundbank.js +0 -740
- package/src/soundfont/basic_soundfont/basic_zone.js +0 -145
- package/src/soundfont/basic_soundfont/generator.js +0 -76
- package/src/soundfont/basic_soundfont/generator_types.js +0 -151
- package/src/soundfont/basic_soundfont/modulator.js +0 -581
- package/src/soundfont/basic_soundfont/riff_chunk.js +0 -195
- package/src/soundfont/basic_soundfont/write_dls/art2.js +0 -174
- package/src/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
- package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -374
- package/src/soundfont/basic_soundfont/write_dls/ins.js +0 -85
- package/src/soundfont/basic_soundfont/write_dls/lins.js +0 -15
- package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
- package/src/soundfont/basic_soundfont/write_dls/rgn2.js +0 -120
- package/src/soundfont/basic_soundfont/write_dls/wave.js +0 -71
- package/src/soundfont/basic_soundfont/write_dls/write_dls.js +0 -124
- package/src/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
- package/src/soundfont/basic_soundfont/write_dls/wvpl.js +0 -35
- package/src/soundfont/basic_soundfont/write_sf2/ibag.js +0 -60
- package/src/soundfont/basic_soundfont/write_sf2/igen.js +0 -91
- package/src/soundfont/basic_soundfont/write_sf2/imod.js +0 -62
- package/src/soundfont/basic_soundfont/write_sf2/inst.js +0 -42
- package/src/soundfont/basic_soundfont/write_sf2/pbag.js +0 -57
- package/src/soundfont/basic_soundfont/write_sf2/pgen.js +0 -92
- package/src/soundfont/basic_soundfont/write_sf2/phdr.js +0 -61
- package/src/soundfont/basic_soundfont/write_sf2/pmod.js +0 -62
- package/src/soundfont/basic_soundfont/write_sf2/sdta.js +0 -131
- package/src/soundfont/basic_soundfont/write_sf2/shdr.js +0 -77
- package/src/soundfont/basic_soundfont/write_sf2/write.js +0 -287
- package/src/soundfont/dls/articulator_converter.js +0 -402
- package/src/soundfont/dls/dls_destinations.js +0 -38
- package/src/soundfont/dls/dls_instrument.js +0 -20
- package/src/soundfont/dls/dls_preset.js +0 -43
- package/src/soundfont/dls/dls_sample.js +0 -238
- package/src/soundfont/dls/dls_soundfont.js +0 -183
- package/src/soundfont/dls/dls_sources.js +0 -63
- package/src/soundfont/dls/dls_zone.js +0 -89
- package/src/soundfont/dls/read_articulation.js +0 -300
- package/src/soundfont/dls/read_instrument.js +0 -118
- package/src/soundfont/dls/read_instrument_list.js +0 -17
- package/src/soundfont/dls/read_lart.js +0 -35
- package/src/soundfont/dls/read_region.js +0 -157
- package/src/soundfont/dls/read_samples.js +0 -154
- package/src/soundfont/load_soundfont.js +0 -21
- package/src/soundfont/read_sf2/generators.js +0 -43
- package/src/soundfont/read_sf2/instrument_zones.js +0 -75
- package/src/soundfont/read_sf2/instruments.js +0 -71
- package/src/soundfont/read_sf2/modulators.js +0 -25
- package/src/soundfont/read_sf2/preset_zones.js +0 -79
- package/src/soundfont/read_sf2/presets.js +0 -80
- package/src/soundfont/read_sf2/samples.js +0 -317
- package/src/soundfont/read_sf2/soundfont.js +0 -452
- package/src/soundfont/read_sf2/zones.js +0 -28
- package/src/synthetizer/README.md +0 -7
- package/src/synthetizer/audio_engine/README.md +0 -9
- package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -289
- package/src/synthetizer/audio_engine/engine_components/controller_tables.js +0 -90
- package/src/synthetizer/audio_engine/engine_components/dynamic_modulator_system.js +0 -95
- package/src/synthetizer/audio_engine/engine_components/enums.js +0 -18
- package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -151
- package/src/synthetizer/audio_engine/engine_components/lfo.js +0 -26
- package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
- package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -551
- package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
- package/src/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
- package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +0 -265
- package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -124
- package/src/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
- package/src/synthetizer/audio_engine/engine_components/voice.js +0 -525
- package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -402
- package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -274
- package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -159
- package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
- package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -254
- package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -20
- package/src/synthetizer/audio_engine/engine_methods/data_entry/awe32.js +0 -198
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -281
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -109
- package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
- package/src/synthetizer/audio_engine/engine_methods/note_on.js +0 -214
- package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
- package/src/synthetizer/audio_engine/engine_methods/program_change.js +0 -35
- package/src/synthetizer/audio_engine/engine_methods/render_voice.js +0 -214
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/embedded_sound_bank.js +0 -42
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/update_preset_list.js +0 -19
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -23
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -56
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
- package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -1058
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -23
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -31
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -29
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
- package/src/synthetizer/audio_engine/main_processor.js +0 -813
- package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -16
- package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
- package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -116
- package/src/synthetizer/audio_engine/synth_processor_options.js +0 -18
- package/src/synthetizer/synth_constants.js +0 -26
- package/src/utils/README.md +0 -8
- package/src/utils/buffer_to_wav.js +0 -197
- package/src/utils/byte_functions/big_endian.js +0 -32
- package/src/utils/byte_functions/little_endian.js +0 -77
- package/src/utils/byte_functions/string.js +0 -92
- package/src/utils/byte_functions/variable_length_quantity.js +0 -42
- package/src/utils/fill_with_defaults.js +0 -21
- package/src/utils/indexed_array.js +0 -34
- package/src/utils/loggin.js +0 -71
- package/src/utils/other.js +0 -92
- package/src/utils/sysex_detector.js +0 -58
- package/src/utils/xg_hacks.js +0 -193
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
import { getModulatorCurveValue, MOD_PRECOMPUTED_LENGTH } from "./modulator_curves.js";
|
|
2
|
-
import { VolumeEnvelope } from "./volume_envelope.js";
|
|
3
|
-
import { ModulationEnvelope } from "./modulation_envelope.js";
|
|
4
|
-
import { Modulator, modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
5
|
-
import { NON_CC_INDEX_OFFSET } from "./controller_tables.js";
|
|
6
|
-
import { generatorLimits, generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* compute_modulator.js
|
|
10
|
-
* purpose: precomputes all curve types and computes modulators
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const EFFECT_MODULATOR_TRANSFORM_MULTIPLIER = 1000 / 200;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Computes a given modulator
|
|
17
|
-
* @param controllerTable {Int16Array} all midi controllers as 14bit values + the non-controller indexes, starting at 128
|
|
18
|
-
* @param modulator {Modulator} the modulator to compute
|
|
19
|
-
* @param voice {Voice} the voice belonging to the modulator
|
|
20
|
-
* @returns {number} the computed value
|
|
21
|
-
*/
|
|
22
|
-
export function computeModulator(controllerTable, modulator, voice)
|
|
23
|
-
{
|
|
24
|
-
if (modulator.transformAmount === 0)
|
|
25
|
-
{
|
|
26
|
-
modulator.currentValue = 0;
|
|
27
|
-
return 0;
|
|
28
|
-
}
|
|
29
|
-
// mapped to 0-16,384
|
|
30
|
-
let rawSourceValue;
|
|
31
|
-
if (modulator.sourceUsesCC)
|
|
32
|
-
{
|
|
33
|
-
rawSourceValue = controllerTable[modulator.sourceIndex];
|
|
34
|
-
}
|
|
35
|
-
else
|
|
36
|
-
{
|
|
37
|
-
const index = modulator.sourceIndex + NON_CC_INDEX_OFFSET;
|
|
38
|
-
switch (modulator.sourceIndex)
|
|
39
|
-
{
|
|
40
|
-
case modulatorSources.noController:
|
|
41
|
-
rawSourceValue = 16383; // equals to 1
|
|
42
|
-
break;
|
|
43
|
-
|
|
44
|
-
case modulatorSources.noteOnKeyNum:
|
|
45
|
-
rawSourceValue = voice.midiNote << 7;
|
|
46
|
-
break;
|
|
47
|
-
|
|
48
|
-
case modulatorSources.noteOnVelocity:
|
|
49
|
-
rawSourceValue = voice.velocity << 7;
|
|
50
|
-
break;
|
|
51
|
-
|
|
52
|
-
case modulatorSources.polyPressure:
|
|
53
|
-
rawSourceValue = voice.pressure << 7;
|
|
54
|
-
break;
|
|
55
|
-
|
|
56
|
-
default:
|
|
57
|
-
rawSourceValue = controllerTable[index]; // pitch bend and range are stored in the cc table
|
|
58
|
-
break;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const sourceValue = transforms[modulator.sourceCurveType][modulator.sourcePolarity][modulator.sourceDirection][rawSourceValue];
|
|
64
|
-
|
|
65
|
-
// mapped to 0-127
|
|
66
|
-
let rawSecondSrcValue;
|
|
67
|
-
if (modulator.secSrcUsesCC)
|
|
68
|
-
{
|
|
69
|
-
rawSecondSrcValue = controllerTable[modulator.secSrcIndex];
|
|
70
|
-
}
|
|
71
|
-
else
|
|
72
|
-
{
|
|
73
|
-
const index = modulator.secSrcIndex + NON_CC_INDEX_OFFSET;
|
|
74
|
-
switch (modulator.secSrcIndex)
|
|
75
|
-
{
|
|
76
|
-
case modulatorSources.noController:
|
|
77
|
-
rawSecondSrcValue = 16383; // equals to 1
|
|
78
|
-
break;
|
|
79
|
-
|
|
80
|
-
case modulatorSources.noteOnKeyNum:
|
|
81
|
-
rawSecondSrcValue = voice.midiNote << 7;
|
|
82
|
-
break;
|
|
83
|
-
|
|
84
|
-
case modulatorSources.noteOnVelocity:
|
|
85
|
-
rawSecondSrcValue = voice.velocity << 7;
|
|
86
|
-
break;
|
|
87
|
-
|
|
88
|
-
case modulatorSources.polyPressure:
|
|
89
|
-
rawSecondSrcValue = voice.pressure << 7;
|
|
90
|
-
break;
|
|
91
|
-
|
|
92
|
-
default:
|
|
93
|
-
rawSecondSrcValue = controllerTable[index]; // pitch bend and range are stored in the cc table
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
const secondSrcValue = transforms[modulator.secSrcCurveType][modulator.secSrcPolarity][modulator.secSrcDirection][rawSecondSrcValue];
|
|
98
|
-
|
|
99
|
-
// see the comment for isEffectModulator (modulator.js in basic_soundfont) for explanation
|
|
100
|
-
let transformAmount = modulator.transformAmount;
|
|
101
|
-
if (modulator.isEffectModulator && transformAmount <= 1000)
|
|
102
|
-
{
|
|
103
|
-
transformAmount *= EFFECT_MODULATOR_TRANSFORM_MULTIPLIER;
|
|
104
|
-
transformAmount = Math.min(transformAmount, 1000);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// compute the modulator
|
|
108
|
-
let computedValue = sourceValue * secondSrcValue * transformAmount;
|
|
109
|
-
|
|
110
|
-
if (modulator.transformType === 2)
|
|
111
|
-
{
|
|
112
|
-
// abs value
|
|
113
|
-
computedValue = Math.abs(computedValue);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// resonant modulator: take its value and ensure that it won't change the final gain
|
|
117
|
-
if (modulator.isDefaultResonantModulator)
|
|
118
|
-
{
|
|
119
|
-
// half the gain, negates the filter
|
|
120
|
-
voice.resonanceOffset = Math.max(0, computedValue / 2);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
modulator.currentValue = computedValue;
|
|
124
|
-
return computedValue;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Computes modulators of a given voice. Source and index indicate what modulators shall be computed
|
|
129
|
-
* @param voice {Voice} the voice to compute modulators for
|
|
130
|
-
* @param sourceUsesCC {number} what modulators should be computed, -1 means all, 0 means modulator source enum 1 means midi controller
|
|
131
|
-
* @param sourceIndex {number} enum for the source
|
|
132
|
-
* @this {MidiAudioChannel}
|
|
133
|
-
*/
|
|
134
|
-
export function computeModulators(voice, sourceUsesCC = -1, sourceIndex = 0)
|
|
135
|
-
{
|
|
136
|
-
const modulators = voice.modulators;
|
|
137
|
-
let generators = voice.generators;
|
|
138
|
-
// apply offsets if enabled
|
|
139
|
-
if (this.generatorOffsetsEnabled)
|
|
140
|
-
{
|
|
141
|
-
generators = new Int16Array(generators);
|
|
142
|
-
for (let i = 0; i < generators.length; i++)
|
|
143
|
-
{
|
|
144
|
-
generators[i] += this.generatorOffsets[i];
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
const modulatedGenerators = voice.modulatedGenerators;
|
|
148
|
-
|
|
149
|
-
if (sourceUsesCC === -1)
|
|
150
|
-
{
|
|
151
|
-
// All modulators mode: compute all modulators
|
|
152
|
-
modulatedGenerators.set(generators);
|
|
153
|
-
modulators.forEach(mod =>
|
|
154
|
-
{
|
|
155
|
-
modulatedGenerators[mod.modulatorDestination] += computeModulator(
|
|
156
|
-
this.midiControllers,
|
|
157
|
-
mod,
|
|
158
|
-
voice
|
|
159
|
-
);
|
|
160
|
-
});
|
|
161
|
-
// apply limits
|
|
162
|
-
for (let gen = 0; gen < modulatedGenerators.length; gen++)
|
|
163
|
-
{
|
|
164
|
-
const limit = generatorLimits[gen];
|
|
165
|
-
if (!limit)
|
|
166
|
-
{
|
|
167
|
-
// skip unused
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
modulatedGenerators[gen] = Math.min(limit.max, Math.max(limit.min, modulatedGenerators[gen]));
|
|
171
|
-
}
|
|
172
|
-
VolumeEnvelope.recalculate(voice);
|
|
173
|
-
ModulationEnvelope.recalculate(voice);
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Optimized mode: calculate only modulators that use the given source
|
|
178
|
-
const volenvNeedsRecalculation = new Set([
|
|
179
|
-
generatorTypes.initialAttenuation,
|
|
180
|
-
generatorTypes.delayVolEnv,
|
|
181
|
-
generatorTypes.attackVolEnv,
|
|
182
|
-
generatorTypes.holdVolEnv,
|
|
183
|
-
generatorTypes.decayVolEnv,
|
|
184
|
-
generatorTypes.sustainVolEnv,
|
|
185
|
-
generatorTypes.releaseVolEnv,
|
|
186
|
-
generatorTypes.keyNumToVolEnvHold,
|
|
187
|
-
generatorTypes.keyNumToVolEnvDecay
|
|
188
|
-
]);
|
|
189
|
-
|
|
190
|
-
const computedDestinations = new Set();
|
|
191
|
-
|
|
192
|
-
modulators.forEach(mod =>
|
|
193
|
-
{
|
|
194
|
-
if (
|
|
195
|
-
(mod.sourceUsesCC === sourceUsesCC && mod.sourceIndex === sourceIndex) ||
|
|
196
|
-
(mod.secSrcUsesCC === sourceUsesCC && mod.secSrcIndex === sourceIndex)
|
|
197
|
-
)
|
|
198
|
-
{
|
|
199
|
-
const destination = mod.modulatorDestination;
|
|
200
|
-
if (!computedDestinations.has(destination))
|
|
201
|
-
{
|
|
202
|
-
// Reset this destination
|
|
203
|
-
modulatedGenerators[destination] = generators[destination];
|
|
204
|
-
// compute our modulator
|
|
205
|
-
computeModulator(this.midiControllers, mod, voice);
|
|
206
|
-
// sum the values of all modulators for this destination
|
|
207
|
-
modulators.forEach(m =>
|
|
208
|
-
{
|
|
209
|
-
if (m.modulatorDestination === destination)
|
|
210
|
-
{
|
|
211
|
-
modulatedGenerators[destination] += m.currentValue;
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
// apply limits
|
|
215
|
-
const limits = generatorLimits[destination];
|
|
216
|
-
modulatedGenerators[destination] = Math.max(
|
|
217
|
-
limits.min,
|
|
218
|
-
Math.min(modulatedGenerators[destination], limits.max)
|
|
219
|
-
);
|
|
220
|
-
computedDestinations.add(destination);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
// Recalculate volume envelope if necessary
|
|
226
|
-
if ([...computedDestinations].some(dest => volenvNeedsRecalculation.has(dest)))
|
|
227
|
-
{
|
|
228
|
-
VolumeEnvelope.recalculate(voice);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
ModulationEnvelope.recalculate(voice);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* as follows: transforms[curveType][polarity][direction] is an array
|
|
237
|
-
* @type {Float32Array[][][]}
|
|
238
|
-
*/
|
|
239
|
-
const transforms = [];
|
|
240
|
-
|
|
241
|
-
for (let curve = 0; curve < 4; curve++)
|
|
242
|
-
{
|
|
243
|
-
transforms[curve] =
|
|
244
|
-
[
|
|
245
|
-
[
|
|
246
|
-
new Float32Array(MOD_PRECOMPUTED_LENGTH),
|
|
247
|
-
new Float32Array(MOD_PRECOMPUTED_LENGTH)
|
|
248
|
-
],
|
|
249
|
-
[
|
|
250
|
-
new Float32Array(MOD_PRECOMPUTED_LENGTH),
|
|
251
|
-
new Float32Array(MOD_PRECOMPUTED_LENGTH)
|
|
252
|
-
]
|
|
253
|
-
];
|
|
254
|
-
for (let i = 0; i < MOD_PRECOMPUTED_LENGTH; i++)
|
|
255
|
-
{
|
|
256
|
-
|
|
257
|
-
// polarity 0 dir 0
|
|
258
|
-
transforms[curve][0][0][i] = getModulatorCurveValue(
|
|
259
|
-
0,
|
|
260
|
-
curve,
|
|
261
|
-
i / MOD_PRECOMPUTED_LENGTH,
|
|
262
|
-
0
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
// polarity 1 dir 0
|
|
266
|
-
transforms[curve][1][0][i] = getModulatorCurveValue(
|
|
267
|
-
0,
|
|
268
|
-
curve,
|
|
269
|
-
i / MOD_PRECOMPUTED_LENGTH,
|
|
270
|
-
1
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
// polarity 0 dir 1
|
|
274
|
-
transforms[curve][0][1][i] = getModulatorCurveValue(
|
|
275
|
-
1,
|
|
276
|
-
curve,
|
|
277
|
-
i / MOD_PRECOMPUTED_LENGTH,
|
|
278
|
-
0
|
|
279
|
-
);
|
|
280
|
-
|
|
281
|
-
// polarity 1 dir 1
|
|
282
|
-
transforms[curve][1][1][i] = getModulatorCurveValue(
|
|
283
|
-
1,
|
|
284
|
-
curve,
|
|
285
|
-
i / MOD_PRECOMPUTED_LENGTH,
|
|
286
|
-
1
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { midiControllers } from "../../../midi/midi_message.js";
|
|
2
|
-
import { modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
3
|
-
|
|
4
|
-
/*
|
|
5
|
-
* A bit of explanation:
|
|
6
|
-
* The controller table is stored as an int16 array, it stores 14-bit values.
|
|
7
|
-
* This controller table is then extended with the modulatorSources section,
|
|
8
|
-
* for example, pitch range and pitch range depth.
|
|
9
|
-
* This allows us for precise control range and supports full pitch-wheel resolution.
|
|
10
|
-
*/
|
|
11
|
-
export const NON_CC_INDEX_OFFSET = 128;
|
|
12
|
-
export const CONTROLLER_TABLE_SIZE = 147;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// an array with preset default values, so we can quickly use set() to reset the controllers
|
|
16
|
-
export const resetArray = new Int16Array(CONTROLLER_TABLE_SIZE).fill(0);
|
|
17
|
-
export const setResetValue = (i, v) => resetArray[i] = v << 7;
|
|
18
|
-
|
|
19
|
-
// values come from Falcosoft MidiPlayer 6
|
|
20
|
-
setResetValue(midiControllers.mainVolume, 100);
|
|
21
|
-
setResetValue(midiControllers.balance, 64);
|
|
22
|
-
setResetValue(midiControllers.expressionController, 127);
|
|
23
|
-
setResetValue(midiControllers.pan, 64);
|
|
24
|
-
|
|
25
|
-
setResetValue(midiControllers.portamentoOnOff, 127);
|
|
26
|
-
|
|
27
|
-
setResetValue(midiControllers.filterResonance, 64);
|
|
28
|
-
setResetValue(midiControllers.releaseTime, 64);
|
|
29
|
-
setResetValue(midiControllers.attackTime, 64);
|
|
30
|
-
setResetValue(midiControllers.brightness, 64);
|
|
31
|
-
|
|
32
|
-
setResetValue(midiControllers.decayTime, 64);
|
|
33
|
-
setResetValue(midiControllers.vibratoRate, 64);
|
|
34
|
-
setResetValue(midiControllers.vibratoDepth, 64);
|
|
35
|
-
setResetValue(midiControllers.vibratoDelay, 64);
|
|
36
|
-
setResetValue(midiControllers.generalPurposeController6, 64);
|
|
37
|
-
setResetValue(midiControllers.generalPurposeController8, 64);
|
|
38
|
-
|
|
39
|
-
setResetValue(midiControllers.RPNLsb, 127);
|
|
40
|
-
setResetValue(midiControllers.RPNMsb, 127);
|
|
41
|
-
setResetValue(midiControllers.NRPNLsb, 127);
|
|
42
|
-
setResetValue(midiControllers.NRPNMsb, 127);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
export const PORTAMENTO_CONTROL_UNSET = 1;
|
|
46
|
-
// special case: portamento control
|
|
47
|
-
// since it is only 7-bit, only the values at multiple of 128 are allowed.
|
|
48
|
-
// a value of just 1 indicates no key set, hence no portamento.
|
|
49
|
-
// this is the "initial unset portamento key" flag.
|
|
50
|
-
resetArray[midiControllers.portamentoControl] = PORTAMENTO_CONTROL_UNSET;
|
|
51
|
-
|
|
52
|
-
// pitch wheel
|
|
53
|
-
setResetValue(NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel, 64);
|
|
54
|
-
setResetValue(NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange, 2);
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @enum {number}
|
|
58
|
-
*/
|
|
59
|
-
export const customControllers = {
|
|
60
|
-
channelTuning: 0, // cents, RPN for fine tuning
|
|
61
|
-
channelTransposeFine: 1, // cents, only the decimal tuning, (e.g., transpose is 4.5,
|
|
62
|
-
// then shift by 4 keys + tune by 50 cents)
|
|
63
|
-
modulationMultiplier: 2, // cents, set by modulation depth RPN
|
|
64
|
-
masterTuning: 3, // cents, set by system exclusive
|
|
65
|
-
channelTuningSemitones: 4, // semitones, for RPN coarse tuning
|
|
66
|
-
channelKeyShift: 5, // key shift: for system exclusive
|
|
67
|
-
sf2NPRNGeneratorLSB: 6 // sf2 NPRN LSB for selecting a generator value
|
|
68
|
-
};
|
|
69
|
-
export const CUSTOM_CONTROLLER_TABLE_SIZE = Object.keys(customControllers).length;
|
|
70
|
-
export const customResetArray = new Float32Array(CUSTOM_CONTROLLER_TABLE_SIZE);
|
|
71
|
-
customResetArray[customControllers.modulationMultiplier] = 1;
|
|
72
|
-
/**
|
|
73
|
-
* @enum {number}
|
|
74
|
-
*/
|
|
75
|
-
export const dataEntryStates = {
|
|
76
|
-
Idle: 0,
|
|
77
|
-
RPCoarse: 1,
|
|
78
|
-
RPFine: 2,
|
|
79
|
-
NRPCoarse: 3,
|
|
80
|
-
NRPFine: 4,
|
|
81
|
-
DataCoarse: 5,
|
|
82
|
-
DataFine: 6
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* This is a channel configuration enum, it is internally sent from Synthetizer via controller change
|
|
86
|
-
* @enum {number}
|
|
87
|
-
*/
|
|
88
|
-
export const channelConfiguration = {
|
|
89
|
-
velocityOverride: 128 // overrides velocity for the given channel
|
|
90
|
-
};
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { Modulator, modulatorCurveTypes, modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
2
|
-
import { NON_CC_INDEX_OFFSET } from "./controller_tables.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A class for dynamic modulators
|
|
6
|
-
* that are assigned for more complex system exclusive messages
|
|
7
|
-
*/
|
|
8
|
-
export class DynamicModulatorSystem
|
|
9
|
-
{
|
|
10
|
-
/**
|
|
11
|
-
* the current dynamic modulator list
|
|
12
|
-
* @type {{mod: Modulator, id: string}[]}
|
|
13
|
-
*/
|
|
14
|
-
modulatorList = [];
|
|
15
|
-
|
|
16
|
-
resetModulators()
|
|
17
|
-
{
|
|
18
|
-
this.modulatorList = [];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param source {number}
|
|
23
|
-
* @param destination {generatorTypes}
|
|
24
|
-
* @param isBipolar {boolean}
|
|
25
|
-
* @param isNegative {boolean}
|
|
26
|
-
*/
|
|
27
|
-
_getModulatorId(source, destination, isBipolar, isNegative)
|
|
28
|
-
{
|
|
29
|
-
return `${source}-${destination}-${isBipolar}-${isNegative}`;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @param id {string}
|
|
34
|
-
* @private
|
|
35
|
-
*/
|
|
36
|
-
_deleteModulator(id)
|
|
37
|
-
{
|
|
38
|
-
this.modulatorList = this.modulatorList.filter(m => m.id !== id);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @param source {number} like in midiControllers: values below NON_CC_INDEX_OFFSET are CCs,
|
|
43
|
-
* above are regular modulator sources
|
|
44
|
-
* @param destination {generatorTypes}
|
|
45
|
-
* @param amount {number}
|
|
46
|
-
* @param isBipolar {boolean}
|
|
47
|
-
* @param isNegative {boolean}
|
|
48
|
-
*/
|
|
49
|
-
setModulator(source, destination, amount, isBipolar = false, isNegative = false)
|
|
50
|
-
{
|
|
51
|
-
const id = this._getModulatorId(source, destination, isBipolar, isNegative);
|
|
52
|
-
if (amount === 0)
|
|
53
|
-
{
|
|
54
|
-
this._deleteModulator(id);
|
|
55
|
-
}
|
|
56
|
-
const mod = this.modulatorList.find(m => m.id === id);
|
|
57
|
-
if (mod)
|
|
58
|
-
{
|
|
59
|
-
mod.mod.transformAmount = amount;
|
|
60
|
-
}
|
|
61
|
-
else
|
|
62
|
-
{
|
|
63
|
-
let srcNum, isCC;
|
|
64
|
-
if (source >= NON_CC_INDEX_OFFSET)
|
|
65
|
-
{
|
|
66
|
-
srcNum = source - NON_CC_INDEX_OFFSET;
|
|
67
|
-
isCC = false;
|
|
68
|
-
}
|
|
69
|
-
else
|
|
70
|
-
{
|
|
71
|
-
srcNum = source;
|
|
72
|
-
isCC = true;
|
|
73
|
-
}
|
|
74
|
-
const modulator = new Modulator(
|
|
75
|
-
srcNum,
|
|
76
|
-
modulatorCurveTypes.linear,
|
|
77
|
-
isCC ? 1 : 0,
|
|
78
|
-
isBipolar ? 1 : 0,
|
|
79
|
-
0,
|
|
80
|
-
modulatorSources.noController,
|
|
81
|
-
modulatorCurveTypes.linear,
|
|
82
|
-
0,
|
|
83
|
-
0,
|
|
84
|
-
0,
|
|
85
|
-
destination,
|
|
86
|
-
amount,
|
|
87
|
-
0
|
|
88
|
-
);
|
|
89
|
-
this.modulatorList.push({
|
|
90
|
-
mod: modulator,
|
|
91
|
-
id: id
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* @enum {number}
|
|
4
|
-
*/
|
|
5
|
-
export const interpolationTypes = {
|
|
6
|
-
linear: 0,
|
|
7
|
-
nearestNeighbor: 1,
|
|
8
|
-
fourthOrder: 2
|
|
9
|
-
};
|
|
10
|
-
/**
|
|
11
|
-
* The text types for the synth display
|
|
12
|
-
* @enum {number}
|
|
13
|
-
*/
|
|
14
|
-
export const synthDisplayTypes = {
|
|
15
|
-
SoundCanvasText: 0,
|
|
16
|
-
XGText: 1,
|
|
17
|
-
SoundCanvasDotDisplay: 2
|
|
18
|
-
};
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A manager for custom key overrides for channels
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export class KeyModifier
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The new override velocity. -1 means unchanged
|
|
10
|
-
* @type {number}
|
|
11
|
-
*/
|
|
12
|
-
velocity = -1;
|
|
13
|
-
/**
|
|
14
|
-
* The patch this key uses. -1 on either means default
|
|
15
|
-
* @type {{bank: number, program: number}}
|
|
16
|
-
*/
|
|
17
|
-
patch = { bank: -1, program: -1 };
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Linear gain override for the voice
|
|
21
|
-
*/
|
|
22
|
-
gain = 1;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @param velocity {number}
|
|
26
|
-
* @param bank {number}
|
|
27
|
-
* @param program {number}
|
|
28
|
-
* @param gain {number}
|
|
29
|
-
*/
|
|
30
|
-
constructor(velocity = -1, bank = -1, program = -1, gain = 1)
|
|
31
|
-
{
|
|
32
|
-
this.velocity = velocity;
|
|
33
|
-
this.patch = {
|
|
34
|
-
bank: bank,
|
|
35
|
-
program: program
|
|
36
|
-
};
|
|
37
|
-
this.gain = gain;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export class KeyModifierManager
|
|
42
|
-
{
|
|
43
|
-
/**
|
|
44
|
-
* The velocity override mappings for MIDI keys
|
|
45
|
-
* stored as [channelNumber][midiNote]
|
|
46
|
-
* @type {KeyModifier[][]}
|
|
47
|
-
* @private
|
|
48
|
-
*/
|
|
49
|
-
_keyMappings = [];
|
|
50
|
-
|
|
51
|
-
// noinspection JSUnusedGlobalSymbols
|
|
52
|
-
/**
|
|
53
|
-
* @param channel {number}
|
|
54
|
-
* @param midiNote {number}
|
|
55
|
-
* @param mapping {KeyModifier}
|
|
56
|
-
*/
|
|
57
|
-
addMapping(channel, midiNote, mapping)
|
|
58
|
-
{
|
|
59
|
-
if (this._keyMappings[channel] === undefined)
|
|
60
|
-
{
|
|
61
|
-
this._keyMappings[channel] = [];
|
|
62
|
-
}
|
|
63
|
-
this._keyMappings[channel][midiNote] = mapping;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// noinspection JSUnusedGlobalSymbols
|
|
67
|
-
/**
|
|
68
|
-
* @param channel {number}
|
|
69
|
-
* @param midiNote {number}
|
|
70
|
-
*/
|
|
71
|
-
deleteMapping(channel, midiNote)
|
|
72
|
-
{
|
|
73
|
-
if (this._keyMappings[channel]?.[midiNote] === undefined)
|
|
74
|
-
{
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
this._keyMappings[channel][midiNote] = undefined;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// noinspection JSUnusedGlobalSymbols
|
|
81
|
-
/**
|
|
82
|
-
* Clear all mappings
|
|
83
|
-
*/
|
|
84
|
-
clearMappings()
|
|
85
|
-
{
|
|
86
|
-
this._keyMappings = [];
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* @param mappings {KeyModifier[][]}
|
|
91
|
-
*/
|
|
92
|
-
setMappings(mappings)
|
|
93
|
-
{
|
|
94
|
-
this._keyMappings = mappings;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* @returns {KeyModifier[][]}
|
|
99
|
-
*/
|
|
100
|
-
getMappings()
|
|
101
|
-
{
|
|
102
|
-
return this._keyMappings;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* @param channel {number}
|
|
107
|
-
* @param midiNote {number}
|
|
108
|
-
* @returns {number} velocity, -1 if unchanged
|
|
109
|
-
*/
|
|
110
|
-
getVelocity(channel, midiNote)
|
|
111
|
-
{
|
|
112
|
-
return this._keyMappings[channel]?.[midiNote]?.velocity ?? -1;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* @param channel {number}
|
|
117
|
-
* @param midiNote {number}
|
|
118
|
-
* @returns {number} linear gain
|
|
119
|
-
*/
|
|
120
|
-
getGain(channel, midiNote)
|
|
121
|
-
{
|
|
122
|
-
return this._keyMappings[channel]?.[midiNote]?.gain ?? 1;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* @param channel {number}
|
|
127
|
-
* @param midiNote {number}
|
|
128
|
-
* @returns {boolean}
|
|
129
|
-
*/
|
|
130
|
-
hasOverridePatch(channel, midiNote)
|
|
131
|
-
{
|
|
132
|
-
const bank = this._keyMappings[channel]?.[midiNote]?.patch?.bank;
|
|
133
|
-
return bank !== undefined && bank >= 0;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* @param channel {number}
|
|
138
|
-
* @param midiNote {number}
|
|
139
|
-
* @returns {{bank: number, program: number}} -1 if unchanged
|
|
140
|
-
*/
|
|
141
|
-
getPatch(channel, midiNote)
|
|
142
|
-
{
|
|
143
|
-
const modifier = this._keyMappings[channel]?.[midiNote];
|
|
144
|
-
if (modifier)
|
|
145
|
-
{
|
|
146
|
-
return modifier.patch;
|
|
147
|
-
}
|
|
148
|
-
throw new Error("No modifier.");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lfo.js
|
|
3
|
-
* purpose: low frequency triangel oscillator
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Calculates a triangular wave value for the given time
|
|
8
|
-
* @param startTime {number} seconds
|
|
9
|
-
* @param frequency {number} Hz
|
|
10
|
-
* @param currentTime {number} seconds
|
|
11
|
-
* @return {number} the value from -1 to 1
|
|
12
|
-
*/
|
|
13
|
-
export function getLFOValue(startTime, frequency, currentTime)
|
|
14
|
-
{
|
|
15
|
-
if (currentTime < startTime)
|
|
16
|
-
{
|
|
17
|
-
return 0;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const xVal = (currentTime - startTime) / (1 / frequency) + 0.25;
|
|
21
|
-
// offset by -0.25, otherwise we start at -1 and can have unexpected jump in pitch or low-pass
|
|
22
|
-
// (happened with Synth Strings 2)
|
|
23
|
-
|
|
24
|
-
// triangle, not sine
|
|
25
|
-
return Math.abs(xVal - (~~(xVal + 0.5))) * 4 - 1;
|
|
26
|
-
}
|