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,300 +0,0 @@
|
|
|
1
|
-
import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
|
|
2
|
-
import { DLSDestinations } from "./dls_destinations.js";
|
|
3
|
-
import { DLS_1_NO_VIBRATO_MOD, DLS_1_NO_VIBRATO_PRESSURE, DLSSources } from "./dls_sources.js";
|
|
4
|
-
import { getSF2ModulatorFromArticulator } from "./articulator_converter.js";
|
|
5
|
-
import { SpessaSynthInfo, SpessaSynthWarn } from "../../utils/loggin.js";
|
|
6
|
-
import { consoleColors } from "../../utils/other.js";
|
|
7
|
-
import { Generator } from "../basic_soundfont/generator.js";
|
|
8
|
-
import { Modulator } from "../basic_soundfont/modulator.js";
|
|
9
|
-
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Reads the articulator chunk
|
|
14
|
-
* @param chunk {RiffChunk}
|
|
15
|
-
* @param disableVibrato {boolean} it seems that dls 1 does not have vibrato lfo, so we shall disable it
|
|
16
|
-
* @returns {{modulators: Modulator[], generators: Generator[]}}
|
|
17
|
-
*/
|
|
18
|
-
export function readArticulation(chunk, disableVibrato)
|
|
19
|
-
{
|
|
20
|
-
const artData = chunk.chunkData;
|
|
21
|
-
/**
|
|
22
|
-
* @type {Generator[]}
|
|
23
|
-
*/
|
|
24
|
-
const generators = [];
|
|
25
|
-
/**
|
|
26
|
-
* @type {Modulator[]}
|
|
27
|
-
*/
|
|
28
|
-
const modulators = [];
|
|
29
|
-
|
|
30
|
-
// cbSize (ignore)
|
|
31
|
-
readLittleEndian(artData, 4);
|
|
32
|
-
const connectionsAmount = readLittleEndian(artData, 4);
|
|
33
|
-
for (let i = 0; i < connectionsAmount; i++)
|
|
34
|
-
{
|
|
35
|
-
// read the block
|
|
36
|
-
const source = readLittleEndian(artData, 2);
|
|
37
|
-
const control = readLittleEndian(artData, 2);
|
|
38
|
-
const destination = readLittleEndian(artData, 2);
|
|
39
|
-
const transform = readLittleEndian(artData, 2);
|
|
40
|
-
const scale = readLittleEndian(artData, 4) | 0;
|
|
41
|
-
const value = scale >> 16; // convert it to 16 bit as soundfont uses that
|
|
42
|
-
|
|
43
|
-
// modulatorConverterDebug(
|
|
44
|
-
// source,
|
|
45
|
-
// control,
|
|
46
|
-
// destination,
|
|
47
|
-
// value,
|
|
48
|
-
// transform
|
|
49
|
-
// );
|
|
50
|
-
|
|
51
|
-
// interpret this somehow...
|
|
52
|
-
// if source and control are both zero, it's a generator
|
|
53
|
-
if (source === 0 && control === 0 && transform === 0)
|
|
54
|
-
{
|
|
55
|
-
/**
|
|
56
|
-
* @type {Generator}
|
|
57
|
-
*/
|
|
58
|
-
let generator;
|
|
59
|
-
switch (destination)
|
|
60
|
-
{
|
|
61
|
-
case DLSDestinations.pan:
|
|
62
|
-
generator = new Generator(generatorTypes.pan, value); // turn percent into tenths of percent
|
|
63
|
-
break;
|
|
64
|
-
case DLSDestinations.gain:
|
|
65
|
-
generator = new Generator(generatorTypes.initialAttenuation, -value * 10 / 0.4); // turn to centibels and apply emu correction
|
|
66
|
-
break;
|
|
67
|
-
case DLSDestinations.filterCutoff:
|
|
68
|
-
generator = new Generator(generatorTypes.initialFilterFc, value);
|
|
69
|
-
break;
|
|
70
|
-
case DLSDestinations.filterQ:
|
|
71
|
-
generator = new Generator(generatorTypes.initialFilterQ, value);
|
|
72
|
-
break;
|
|
73
|
-
|
|
74
|
-
// mod lfo raw values it seems
|
|
75
|
-
case DLSDestinations.modLfoFreq:
|
|
76
|
-
generator = new Generator(generatorTypes.freqModLFO, value);
|
|
77
|
-
break;
|
|
78
|
-
case DLSDestinations.modLfoDelay:
|
|
79
|
-
generator = new Generator(generatorTypes.delayModLFO, value);
|
|
80
|
-
break;
|
|
81
|
-
case DLSDestinations.vibLfoFreq:
|
|
82
|
-
generator = new Generator(generatorTypes.freqVibLFO, value);
|
|
83
|
-
break;
|
|
84
|
-
case DLSDestinations.vibLfoDelay:
|
|
85
|
-
generator = new Generator(generatorTypes.delayVibLFO, value);
|
|
86
|
-
break;
|
|
87
|
-
|
|
88
|
-
// vol. env: all times are timecents like sf2
|
|
89
|
-
case DLSDestinations.volEnvDelay:
|
|
90
|
-
generator = new Generator(generatorTypes.delayVolEnv, value);
|
|
91
|
-
break;
|
|
92
|
-
case DLSDestinations.volEnvAttack:
|
|
93
|
-
generator = new Generator(generatorTypes.attackVolEnv, value);
|
|
94
|
-
break;
|
|
95
|
-
case DLSDestinations.volEnvHold:
|
|
96
|
-
// do not validate because keyNumToSomething
|
|
97
|
-
generator = new Generator(generatorTypes.holdVolEnv, value, false);
|
|
98
|
-
break;
|
|
99
|
-
case DLSDestinations.volEnvDecay:
|
|
100
|
-
// do not validate because keyNumToSomething
|
|
101
|
-
generator = new Generator(generatorTypes.decayVolEnv, value, false);
|
|
102
|
-
break;
|
|
103
|
-
case DLSDestinations.volEnvRelease:
|
|
104
|
-
generator = new Generator(generatorTypes.releaseVolEnv, value);
|
|
105
|
-
break;
|
|
106
|
-
case DLSDestinations.volEnvSustain:
|
|
107
|
-
// gain seems to be (1000 - value) / 10 = sustain dB
|
|
108
|
-
const sustainCb = 1000 - value;
|
|
109
|
-
generator = new Generator(generatorTypes.sustainVolEnv, sustainCb);
|
|
110
|
-
break;
|
|
111
|
-
|
|
112
|
-
// mod env
|
|
113
|
-
case DLSDestinations.modEnvDelay:
|
|
114
|
-
generator = new Generator(generatorTypes.delayModEnv, value);
|
|
115
|
-
break;
|
|
116
|
-
case DLSDestinations.modEnvAttack:
|
|
117
|
-
generator = new Generator(generatorTypes.attackModEnv, value);
|
|
118
|
-
break;
|
|
119
|
-
case DLSDestinations.modEnvHold:
|
|
120
|
-
// do not validate because keyNumToSomething
|
|
121
|
-
generator = new Generator(generatorTypes.holdModEnv, value, false);
|
|
122
|
-
break;
|
|
123
|
-
case DLSDestinations.modEnvDecay:
|
|
124
|
-
// do not validate because keyNumToSomething
|
|
125
|
-
generator = new Generator(generatorTypes.decayModEnv, value, false);
|
|
126
|
-
break;
|
|
127
|
-
case DLSDestinations.modEnvRelease:
|
|
128
|
-
generator = new Generator(generatorTypes.releaseModEnv, value);
|
|
129
|
-
break;
|
|
130
|
-
case DLSDestinations.modEnvSustain:
|
|
131
|
-
// dls uses 1%, desfont uses 0.1%
|
|
132
|
-
const percentageSustain = 1000 - value;
|
|
133
|
-
generator = new Generator(generatorTypes.sustainModEnv, percentageSustain);
|
|
134
|
-
break;
|
|
135
|
-
|
|
136
|
-
case DLSDestinations.reverbSend:
|
|
137
|
-
generator = new Generator(generatorTypes.reverbEffectsSend, value);
|
|
138
|
-
break;
|
|
139
|
-
case DLSDestinations.chorusSend:
|
|
140
|
-
generator = new Generator(generatorTypes.chorusEffectsSend, value);
|
|
141
|
-
break;
|
|
142
|
-
case DLSDestinations.pitch:
|
|
143
|
-
// split it up
|
|
144
|
-
const semi = Math.floor(value / 100);
|
|
145
|
-
const cents = Math.floor(value - semi * 100);
|
|
146
|
-
generator = new Generator(generatorTypes.fineTune, cents);
|
|
147
|
-
generators.push(new Generator(generatorTypes.coarseTune, semi));
|
|
148
|
-
break;
|
|
149
|
-
}
|
|
150
|
-
if (generator)
|
|
151
|
-
{
|
|
152
|
-
generators.push(generator);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
else
|
|
156
|
-
// if not, modulator?
|
|
157
|
-
{
|
|
158
|
-
let isGenerator = true;
|
|
159
|
-
|
|
160
|
-
const applyKeyToCorrection = (value, keyToGen, realGen) =>
|
|
161
|
-
{
|
|
162
|
-
// according to viena and another strange (with modulators) rendition of gm.dls in sf2,
|
|
163
|
-
// it shall be divided by -128
|
|
164
|
-
// and a strange correction needs to be applied to the real value:
|
|
165
|
-
// real + (60 / 128) * scale
|
|
166
|
-
const keyToGenValue = value / -128;
|
|
167
|
-
generators.push(new Generator(keyToGen, keyToGenValue));
|
|
168
|
-
// airfont 340 fix
|
|
169
|
-
if (keyToGenValue <= 120)
|
|
170
|
-
{
|
|
171
|
-
const correction = Math.round((60 / 128) * value);
|
|
172
|
-
generators.forEach(g =>
|
|
173
|
-
{
|
|
174
|
-
if (g.generatorType === realGen)
|
|
175
|
-
{
|
|
176
|
-
g.generatorValue += correction;
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
// a few special cases which are generators:
|
|
183
|
-
if (control === DLSSources.none)
|
|
184
|
-
{
|
|
185
|
-
// mod lfo to pitch
|
|
186
|
-
if (source === DLSSources.modLfo && destination === DLSDestinations.pitch)
|
|
187
|
-
{
|
|
188
|
-
generators.push(new Generator(generatorTypes.modLfoToPitch, value));
|
|
189
|
-
}
|
|
190
|
-
else
|
|
191
|
-
// mod lfo to volume
|
|
192
|
-
if (source === DLSSources.modLfo && destination === DLSDestinations.gain)
|
|
193
|
-
{
|
|
194
|
-
generators.push(new Generator(generatorTypes.modLfoToVolume, value));
|
|
195
|
-
}
|
|
196
|
-
else
|
|
197
|
-
// mod lfo to filter
|
|
198
|
-
if (source === DLSSources.modLfo && destination === DLSDestinations.filterCutoff)
|
|
199
|
-
{
|
|
200
|
-
generators.push(new Generator(generatorTypes.modLfoToFilterFc, value));
|
|
201
|
-
}
|
|
202
|
-
else
|
|
203
|
-
// vib lfo to pitch
|
|
204
|
-
if (source === DLSSources.vibratoLfo && destination === DLSDestinations.pitch)
|
|
205
|
-
{
|
|
206
|
-
generators.push(new Generator(generatorTypes.vibLfoToPitch, value));
|
|
207
|
-
}
|
|
208
|
-
else
|
|
209
|
-
// mod env to pitch
|
|
210
|
-
if (source === DLSSources.modEnv && destination === DLSDestinations.pitch)
|
|
211
|
-
{
|
|
212
|
-
generators.push(new Generator(generatorTypes.modEnvToPitch, value));
|
|
213
|
-
}
|
|
214
|
-
else
|
|
215
|
-
// mod env to filter
|
|
216
|
-
if (source === DLSSources.modEnv && destination === DLSDestinations.filterCutoff)
|
|
217
|
-
{
|
|
218
|
-
generators.push(new Generator(generatorTypes.modEnvToFilterFc, value));
|
|
219
|
-
}
|
|
220
|
-
else
|
|
221
|
-
// scale tuning (key number to pitch)
|
|
222
|
-
if (source === DLSSources.keyNum && destination === DLSDestinations.pitch)
|
|
223
|
-
{
|
|
224
|
-
// this is just a soundfont generator, but the amount must be changed
|
|
225
|
-
// 12,800 means the regular scale (100)
|
|
226
|
-
generators.push(new Generator(generatorTypes.scaleTuning, value / 128));
|
|
227
|
-
}
|
|
228
|
-
else
|
|
229
|
-
// key to vol env hold
|
|
230
|
-
if (source === DLSSources.keyNum && destination === DLSDestinations.volEnvHold)
|
|
231
|
-
{
|
|
232
|
-
applyKeyToCorrection(value, generatorTypes.keyNumToVolEnvHold, generatorTypes.holdVolEnv);
|
|
233
|
-
}
|
|
234
|
-
else
|
|
235
|
-
// key to vol env decay
|
|
236
|
-
if (source === DLSSources.keyNum && destination === DLSDestinations.volEnvDecay)
|
|
237
|
-
{
|
|
238
|
-
applyKeyToCorrection(value, generatorTypes.keyNumToVolEnvDecay, generatorTypes.decayVolEnv);
|
|
239
|
-
}
|
|
240
|
-
else
|
|
241
|
-
// key to mod env hold
|
|
242
|
-
if (source === DLSSources.keyNum && destination === DLSDestinations.modEnvHold)
|
|
243
|
-
{
|
|
244
|
-
applyKeyToCorrection(value, generatorTypes.keyNumToModEnvHold, generatorTypes.holdModEnv);
|
|
245
|
-
}
|
|
246
|
-
else
|
|
247
|
-
// key to mod env decay
|
|
248
|
-
if (source === DLSSources.keyNum && destination === DLSDestinations.modEnvDecay)
|
|
249
|
-
{
|
|
250
|
-
applyKeyToCorrection(value, generatorTypes.keyNumToModEnvDecay, generatorTypes.decayModEnv);
|
|
251
|
-
}
|
|
252
|
-
else
|
|
253
|
-
{
|
|
254
|
-
isGenerator = false;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
else
|
|
259
|
-
{
|
|
260
|
-
isGenerator = false;
|
|
261
|
-
}
|
|
262
|
-
if (isGenerator === false)
|
|
263
|
-
{
|
|
264
|
-
// UNCOMMENT TO ENABLE DEBUG
|
|
265
|
-
// modulatorConverterDebug(source, control, destination, value, transform)
|
|
266
|
-
// convert it to modulator
|
|
267
|
-
const mod = getSF2ModulatorFromArticulator(
|
|
268
|
-
source,
|
|
269
|
-
control,
|
|
270
|
-
destination,
|
|
271
|
-
transform,
|
|
272
|
-
value
|
|
273
|
-
);
|
|
274
|
-
if (mod)
|
|
275
|
-
{
|
|
276
|
-
// some articulators cannot be turned into modulators, that's why this check is a thing
|
|
277
|
-
modulators.push(mod);
|
|
278
|
-
SpessaSynthInfo("%cSucceeded converting to SF2 Modulator!", consoleColors.recognized);
|
|
279
|
-
}
|
|
280
|
-
else
|
|
281
|
-
{
|
|
282
|
-
SpessaSynthWarn("Failed converting to SF2 Modulator!");
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// it seems that dls 1 does not have vibrato lfo, so we shall disable it
|
|
289
|
-
if (disableVibrato)
|
|
290
|
-
{
|
|
291
|
-
modulators.push(
|
|
292
|
-
// mod to vib
|
|
293
|
-
Modulator.copy(DLS_1_NO_VIBRATO_MOD),
|
|
294
|
-
// press to vib
|
|
295
|
-
Modulator.copy(DLS_1_NO_VIBRATO_PRESSURE)
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return { modulators: modulators, generators: generators };
|
|
300
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { readBytesAsString } from "../../utils/byte_functions/string.js";
|
|
2
|
-
import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import { DLSPreset } from "./dls_preset.js";
|
|
4
|
-
import { findRIFFListType, readRIFFChunk } from "../basic_soundfont/riff_chunk.js";
|
|
5
|
-
import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd } from "../../utils/loggin.js";
|
|
6
|
-
import { consoleColors } from "../../utils/other.js";
|
|
7
|
-
import { Modulator } from "../basic_soundfont/modulator.js";
|
|
8
|
-
import { DEFAULT_DLS_CHORUS, DEFAULT_DLS_REVERB } from "./dls_sources.js";
|
|
9
|
-
import { generatorLimits, generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
10
|
-
import { readRegion } from "./read_region.js";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @this {DLSSoundFont}
|
|
14
|
-
* @param chunk {RiffChunk}
|
|
15
|
-
*/
|
|
16
|
-
export function readDLSInstrument(chunk)
|
|
17
|
-
{
|
|
18
|
-
this.verifyHeader(chunk, "LIST");
|
|
19
|
-
this.verifyText(readBytesAsString(chunk.chunkData, 4), "ins ");
|
|
20
|
-
/**
|
|
21
|
-
* @type {RiffChunk[]}
|
|
22
|
-
*/
|
|
23
|
-
const chunks = [];
|
|
24
|
-
while (chunk.chunkData.length > chunk.chunkData.currentIndex)
|
|
25
|
-
{
|
|
26
|
-
chunks.push(readRIFFChunk(chunk.chunkData));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const instrumentHeader = chunks.find(c => c.header === "insh");
|
|
31
|
-
if (!instrumentHeader)
|
|
32
|
-
{
|
|
33
|
-
SpessaSynthGroupEnd();
|
|
34
|
-
throw new Error("No instrument header!");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// read instrument header
|
|
38
|
-
const regions = readLittleEndian(instrumentHeader.chunkData, 4);
|
|
39
|
-
const ulBank = readLittleEndian(instrumentHeader.chunkData, 4);
|
|
40
|
-
const ulInstrument = readLittleEndian(instrumentHeader.chunkData, 4);
|
|
41
|
-
const preset = new DLSPreset(this, ulBank, ulInstrument);
|
|
42
|
-
|
|
43
|
-
// read preset name in INFO
|
|
44
|
-
let presetName = ``;
|
|
45
|
-
const infoChunk = findRIFFListType(chunks, "INFO");
|
|
46
|
-
if (infoChunk)
|
|
47
|
-
{
|
|
48
|
-
let info = readRIFFChunk(infoChunk.chunkData);
|
|
49
|
-
while (info.header !== "INAM")
|
|
50
|
-
{
|
|
51
|
-
info = readRIFFChunk(infoChunk.chunkData);
|
|
52
|
-
}
|
|
53
|
-
presetName = readBytesAsString(info.chunkData, info.chunkData.length).trim();
|
|
54
|
-
}
|
|
55
|
-
if (presetName.length < 1)
|
|
56
|
-
{
|
|
57
|
-
presetName = `unnamed ${(ulBank >> 8) & 127}:${ulInstrument & 127}`;
|
|
58
|
-
}
|
|
59
|
-
preset.presetName = presetName;
|
|
60
|
-
preset.dlsInstrument.instrumentName = presetName;
|
|
61
|
-
SpessaSynthGroupCollapsed(
|
|
62
|
-
`%cParsing %c"${presetName}"%c...`,
|
|
63
|
-
consoleColors.info,
|
|
64
|
-
consoleColors.recognized,
|
|
65
|
-
consoleColors.info
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
// list of regions
|
|
69
|
-
const regionListChunk = findRIFFListType(chunks, "lrgn");
|
|
70
|
-
if (!regionListChunk)
|
|
71
|
-
{
|
|
72
|
-
SpessaSynthGroupEnd();
|
|
73
|
-
throw new Error("No region list!");
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// global articulation: essentially global zone
|
|
77
|
-
const globalZone = preset.dlsInstrument.globalZone;
|
|
78
|
-
|
|
79
|
-
// read articulators
|
|
80
|
-
const globalLart = findRIFFListType(chunks, "lart");
|
|
81
|
-
const globalLar2 = findRIFFListType(chunks, "lar2");
|
|
82
|
-
if (globalLar2 !== undefined || globalLart !== undefined)
|
|
83
|
-
{
|
|
84
|
-
this.readLart(globalLart, globalLar2, globalZone);
|
|
85
|
-
}
|
|
86
|
-
// remove generators with default values
|
|
87
|
-
globalZone.generators = globalZone.generators.filter(g => g.generatorValue !== generatorLimits[g.generatorType].def);
|
|
88
|
-
// override reverb and chorus with 1000 instead of 200 (if not override)
|
|
89
|
-
// reverb
|
|
90
|
-
if (globalZone.modulators.find(m => m.modulatorDestination === generatorTypes.reverbEffectsSend) === undefined)
|
|
91
|
-
{
|
|
92
|
-
globalZone.addModulators(Modulator.copy(DEFAULT_DLS_REVERB));
|
|
93
|
-
}
|
|
94
|
-
// chorus
|
|
95
|
-
if (globalZone.modulators.find(m => m.modulatorDestination === generatorTypes.chorusEffectsSend) === undefined)
|
|
96
|
-
{
|
|
97
|
-
globalZone.addModulators(Modulator.copy(DEFAULT_DLS_CHORUS));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// read regions
|
|
101
|
-
for (let i = 0; i < regions; i++)
|
|
102
|
-
{
|
|
103
|
-
const chunk = readRIFFChunk(regionListChunk.chunkData);
|
|
104
|
-
this.verifyHeader(chunk, "LIST");
|
|
105
|
-
const type = readBytesAsString(chunk.chunkData, 4);
|
|
106
|
-
if (type !== "rgn " && type !== "rgn2")
|
|
107
|
-
{
|
|
108
|
-
SpessaSynthGroupEnd();
|
|
109
|
-
this.parsingError(`Invalid DLS region! Expected "rgn " or "rgn2" got "${type}"`);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
readRegion.call(this, chunk, preset.dlsInstrument);
|
|
114
|
-
}
|
|
115
|
-
this.addPresets(preset);
|
|
116
|
-
this.addInstruments(preset.dlsInstrument);
|
|
117
|
-
SpessaSynthGroupEnd();
|
|
118
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { readRIFFChunk } from "../basic_soundfont/riff_chunk.js";
|
|
2
|
-
import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd } from "../../utils/loggin.js";
|
|
3
|
-
import { consoleColors } from "../../utils/other.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @this {DLSSoundFont}
|
|
7
|
-
* @param instrumentListChunk {RiffChunk}
|
|
8
|
-
*/
|
|
9
|
-
export function readDLSInstrumentList(instrumentListChunk)
|
|
10
|
-
{
|
|
11
|
-
SpessaSynthGroupCollapsed("%cLoading instruments...", consoleColors.info);
|
|
12
|
-
for (let i = 0; i < this.instrumentAmount; i++)
|
|
13
|
-
{
|
|
14
|
-
this.readDLSInstrument(readRIFFChunk(instrumentListChunk.chunkData));
|
|
15
|
-
}
|
|
16
|
-
SpessaSynthGroupEnd();
|
|
17
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { readRIFFChunk } from "../basic_soundfont/riff_chunk.js";
|
|
2
|
-
import { readArticulation } from "./read_articulation.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @param lartChunk {RiffChunk|undefined}
|
|
6
|
-
* @param lar2Chunk {RiffChunk|undefined}
|
|
7
|
-
* @param zone {BasicZone}
|
|
8
|
-
* @this {DLSSoundFont}
|
|
9
|
-
*/
|
|
10
|
-
export function readLart(lartChunk, lar2Chunk, zone)
|
|
11
|
-
{
|
|
12
|
-
if (lartChunk)
|
|
13
|
-
{
|
|
14
|
-
while (lartChunk.chunkData.currentIndex < lartChunk.chunkData.length)
|
|
15
|
-
{
|
|
16
|
-
const art1 = readRIFFChunk(lartChunk.chunkData);
|
|
17
|
-
this.verifyHeader(art1, "art1", "art2");
|
|
18
|
-
const modsAndGens = readArticulation(art1, true);
|
|
19
|
-
zone.addGenerators(...modsAndGens.generators);
|
|
20
|
-
zone.addModulators(...modsAndGens.modulators);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (lar2Chunk)
|
|
25
|
-
{
|
|
26
|
-
while (lar2Chunk.chunkData.currentIndex < lar2Chunk.chunkData.length)
|
|
27
|
-
{
|
|
28
|
-
const art2 = readRIFFChunk(lar2Chunk.chunkData);
|
|
29
|
-
this.verifyHeader(art2, "art2", "art1");
|
|
30
|
-
const modsAndGens = readArticulation(art2, false);
|
|
31
|
-
zone.addGenerators(...modsAndGens.generators);
|
|
32
|
-
zone.addModulators(...modsAndGens.modulators);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { readLittleEndian, signedInt16 } from "../../utils/byte_functions/little_endian.js";
|
|
2
|
-
import { findRIFFListType, readRIFFChunk } from "../basic_soundfont/riff_chunk.js";
|
|
3
|
-
import { Generator } from "../basic_soundfont/generator.js";
|
|
4
|
-
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
5
|
-
import { SpessaSynthWarn } from "../../utils/loggin.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @this {DLSSoundFont}
|
|
9
|
-
* @param chunk {RiffChunk}
|
|
10
|
-
* @param instrument {DLSInstrument}
|
|
11
|
-
*/
|
|
12
|
-
export function readRegion(chunk, instrument)
|
|
13
|
-
{
|
|
14
|
-
// regions are essentially instrument zones
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* read chunks in the region
|
|
18
|
-
* @type {RiffChunk[]}
|
|
19
|
-
*/
|
|
20
|
-
const regionChunks = [];
|
|
21
|
-
while (chunk.chunkData.length > chunk.chunkData.currentIndex)
|
|
22
|
-
{
|
|
23
|
-
regionChunks.push(readRIFFChunk(chunk.chunkData));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// region header
|
|
27
|
-
const regionHeader = regionChunks.find(c => c.header === "rgnh");
|
|
28
|
-
|
|
29
|
-
if (!regionHeader)
|
|
30
|
-
{
|
|
31
|
-
SpessaSynthWarn("Invalid DLS region: missing 'rgnh' chunk! Discarding...");
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
// key range
|
|
35
|
-
let keyMin = readLittleEndian(regionHeader.chunkData, 2);
|
|
36
|
-
let keyMax = readLittleEndian(regionHeader.chunkData, 2);
|
|
37
|
-
// vel range
|
|
38
|
-
let velMin = readLittleEndian(regionHeader.chunkData, 2);
|
|
39
|
-
let velMax = readLittleEndian(regionHeader.chunkData, 2);
|
|
40
|
-
|
|
41
|
-
// a fix for not cool files
|
|
42
|
-
if (velMin === 0 && velMax === 0)
|
|
43
|
-
{
|
|
44
|
-
velMax = 127;
|
|
45
|
-
velMin = 0;
|
|
46
|
-
}
|
|
47
|
-
// cannot do the same to key zones sadly
|
|
48
|
-
// create zone
|
|
49
|
-
const zone = instrument.createZone();
|
|
50
|
-
// apply ranges
|
|
51
|
-
zone.keyRange = { min: keyMin, max: keyMax };
|
|
52
|
-
zone.velRange = { min: velMin, max: velMax };
|
|
53
|
-
|
|
54
|
-
// fusOptions: no idea about that one???
|
|
55
|
-
readLittleEndian(regionHeader.chunkData, 2);
|
|
56
|
-
|
|
57
|
-
// keyGroup: essentially exclusive class
|
|
58
|
-
const exclusive = readLittleEndian(regionHeader.chunkData, 2);
|
|
59
|
-
if (exclusive !== 0)
|
|
60
|
-
{
|
|
61
|
-
zone.addGenerators(new Generator(generatorTypes.exclusiveClass, exclusive));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// lart
|
|
65
|
-
const lart = findRIFFListType(regionChunks, "lart");
|
|
66
|
-
const lar2 = findRIFFListType(regionChunks, "lar2");
|
|
67
|
-
this.readLart(lart, lar2, zone);
|
|
68
|
-
|
|
69
|
-
// wsmp: wave sample chunk
|
|
70
|
-
const waveSampleChunk = regionChunks.find(c => c.header === "wsmp");
|
|
71
|
-
// cbSize
|
|
72
|
-
readLittleEndian(waveSampleChunk.chunkData, 4);
|
|
73
|
-
let originalKey = readLittleEndian(waveSampleChunk.chunkData, 2);
|
|
74
|
-
|
|
75
|
-
// sFineTune
|
|
76
|
-
let pitchCorrection = signedInt16(
|
|
77
|
-
waveSampleChunk.chunkData[waveSampleChunk.chunkData.currentIndex++],
|
|
78
|
-
waveSampleChunk.chunkData[waveSampleChunk.chunkData.currentIndex++]
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
// gain correction: Each unit of gain represents 1/655360 dB
|
|
82
|
-
// it is set after linking the sample
|
|
83
|
-
const gainCorrection = readLittleEndian(waveSampleChunk.chunkData, 4);
|
|
84
|
-
// convert to signed and turn into attenuation (invert)
|
|
85
|
-
const dbCorrection = (gainCorrection | 0) / -655360;
|
|
86
|
-
|
|
87
|
-
// skip options
|
|
88
|
-
readLittleEndian(waveSampleChunk.chunkData, 4);
|
|
89
|
-
|
|
90
|
-
// read loop count (always one or zero)
|
|
91
|
-
const loopsAmount = readLittleEndian(waveSampleChunk.chunkData, 4);
|
|
92
|
-
let loopingMode;
|
|
93
|
-
const loop = { start: 0, end: 0 };
|
|
94
|
-
if (loopsAmount === 0)
|
|
95
|
-
{
|
|
96
|
-
// no loop
|
|
97
|
-
loopingMode = 0;
|
|
98
|
-
}
|
|
99
|
-
else
|
|
100
|
-
{
|
|
101
|
-
// ignore cbSize
|
|
102
|
-
readLittleEndian(waveSampleChunk.chunkData, 4);
|
|
103
|
-
// loop type: loop normally or loop until release (like soundfont)
|
|
104
|
-
const loopType = readLittleEndian(waveSampleChunk.chunkData, 4); // why is it long?
|
|
105
|
-
if (loopType === 0)
|
|
106
|
-
{
|
|
107
|
-
loopingMode = 1;
|
|
108
|
-
}
|
|
109
|
-
else
|
|
110
|
-
{
|
|
111
|
-
loopingMode = 3;
|
|
112
|
-
}
|
|
113
|
-
loop.start = readLittleEndian(waveSampleChunk.chunkData, 4);
|
|
114
|
-
const loopLength = readLittleEndian(waveSampleChunk.chunkData, 4);
|
|
115
|
-
loop.end = loop.start + loopLength;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// wave link
|
|
119
|
-
const waveLinkChunk = regionChunks.find(c => c.header === "wlnk");
|
|
120
|
-
if (waveLinkChunk === undefined)
|
|
121
|
-
{
|
|
122
|
-
// No wave link means no sample. What? Why is it even here then?
|
|
123
|
-
return undefined;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// flags
|
|
127
|
-
readLittleEndian(waveLinkChunk.chunkData, 2);
|
|
128
|
-
// phase group
|
|
129
|
-
readLittleEndian(waveLinkChunk.chunkData, 2);
|
|
130
|
-
// channel
|
|
131
|
-
readLittleEndian(waveLinkChunk.chunkData, 4);
|
|
132
|
-
// sampleID
|
|
133
|
-
const sampleID = readLittleEndian(waveLinkChunk.chunkData, 4);
|
|
134
|
-
// noinspection JSValidateTypes
|
|
135
|
-
/**
|
|
136
|
-
* @type {DLSSample}
|
|
137
|
-
*/
|
|
138
|
-
const sample = this.samples[sampleID];
|
|
139
|
-
if (sample === undefined)
|
|
140
|
-
{
|
|
141
|
-
throw new Error("Invalid sample ID!");
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// this correction overrides the sample gain correction
|
|
145
|
-
const actualDbCorrection = dbCorrection || sample.sampleDbAttenuation;
|
|
146
|
-
// convert to centibels
|
|
147
|
-
const attenuation = (actualDbCorrection * 10) / 0.4; // make sure to apply EMU correction
|
|
148
|
-
|
|
149
|
-
zone.setWavesample(
|
|
150
|
-
attenuation, loopingMode,
|
|
151
|
-
loop,
|
|
152
|
-
originalKey,
|
|
153
|
-
sample,
|
|
154
|
-
sampleID,
|
|
155
|
-
pitchCorrection
|
|
156
|
-
);
|
|
157
|
-
}
|