spessasynth_core 3.27.8 → 4.0.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 +85 -51
- package/dist/index.d.ts +4057 -0
- package/dist/index.js +17178 -0
- package/dist/index.js.map +1 -0
- package/package.json +24 -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 -53
- 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 -220
- 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 -26
- 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 -817
- 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,330 +0,0 @@
|
|
|
1
|
-
import { midiControllers } from "../../../midi/midi_message.js";
|
|
2
|
-
import { DLSSources } from "../../dls/dls_sources.js";
|
|
3
|
-
import { modulatorCurveTypes, modulatorSources } from "../modulator.js";
|
|
4
|
-
import { DLSDestinations } from "../../dls/dls_destinations.js";
|
|
5
|
-
import { Articulator } from "./articulator.js";
|
|
6
|
-
import { SpessaSynthWarn } from "../../../utils/loggin.js";
|
|
7
|
-
import { generatorTypes } from "../generator_types.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @param cc {0|1}
|
|
12
|
-
* @param index {number}
|
|
13
|
-
* @returns {number|undefined}
|
|
14
|
-
*/
|
|
15
|
-
function getDLSSourceFromSf2Source(cc, index)
|
|
16
|
-
{
|
|
17
|
-
if (cc)
|
|
18
|
-
{
|
|
19
|
-
switch (index)
|
|
20
|
-
{
|
|
21
|
-
default:
|
|
22
|
-
// DLS supports limited controllers
|
|
23
|
-
return undefined;
|
|
24
|
-
|
|
25
|
-
case midiControllers.modulationWheel:
|
|
26
|
-
return DLSSources.modulationWheel;
|
|
27
|
-
case midiControllers.mainVolume:
|
|
28
|
-
return DLSSources.volume;
|
|
29
|
-
case midiControllers.pan:
|
|
30
|
-
return DLSSources.pan;
|
|
31
|
-
case midiControllers.expressionController:
|
|
32
|
-
return DLSSources.expression;
|
|
33
|
-
case midiControllers.chorusDepth:
|
|
34
|
-
return DLSSources.chorus;
|
|
35
|
-
case midiControllers.reverbDepth:
|
|
36
|
-
return DLSSources.reverb;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
else
|
|
40
|
-
{
|
|
41
|
-
switch (index)
|
|
42
|
-
{
|
|
43
|
-
default:
|
|
44
|
-
// cannot be a DLS articulator
|
|
45
|
-
return undefined;
|
|
46
|
-
|
|
47
|
-
case modulatorSources.noteOnKeyNum:
|
|
48
|
-
return DLSSources.keyNum;
|
|
49
|
-
case modulatorSources.noteOnVelocity:
|
|
50
|
-
return DLSSources.velocity;
|
|
51
|
-
case modulatorSources.noController:
|
|
52
|
-
return DLSSources.none;
|
|
53
|
-
case modulatorSources.polyPressure:
|
|
54
|
-
return DLSSources.polyPressure;
|
|
55
|
-
case modulatorSources.channelPressure:
|
|
56
|
-
return DLSSources.channelPressure;
|
|
57
|
-
case modulatorSources.pitchWheel:
|
|
58
|
-
return DLSSources.pitchWheel;
|
|
59
|
-
case modulatorSources.pitchWheelRange:
|
|
60
|
-
return DLSSources.pitchWheelRange;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @param dest {number}
|
|
67
|
-
* @param amount {number}
|
|
68
|
-
* @returns {number|undefined|{dest: number, amount: number}}
|
|
69
|
-
*/
|
|
70
|
-
function getDLSDestinationFromSf2(dest, amount)
|
|
71
|
-
{
|
|
72
|
-
switch (dest)
|
|
73
|
-
{
|
|
74
|
-
default:
|
|
75
|
-
return undefined;
|
|
76
|
-
|
|
77
|
-
case generatorTypes.initialAttenuation:
|
|
78
|
-
// the amount does not get EMU corrected here, as this only applies to modulator attenuation
|
|
79
|
-
// the generator (affected) attenuation is handled in wsmp.
|
|
80
|
-
return { dest: DLSDestinations.gain, amount: -amount };
|
|
81
|
-
case generatorTypes.fineTune:
|
|
82
|
-
return DLSDestinations.pitch;
|
|
83
|
-
case generatorTypes.pan:
|
|
84
|
-
return DLSDestinations.pan;
|
|
85
|
-
case generatorTypes.keyNum:
|
|
86
|
-
return DLSDestinations.keyNum;
|
|
87
|
-
|
|
88
|
-
case generatorTypes.reverbEffectsSend:
|
|
89
|
-
return DLSDestinations.reverbSend;
|
|
90
|
-
case generatorTypes.chorusEffectsSend:
|
|
91
|
-
return DLSDestinations.chorusSend;
|
|
92
|
-
|
|
93
|
-
case generatorTypes.freqModLFO:
|
|
94
|
-
return DLSDestinations.modLfoFreq;
|
|
95
|
-
case generatorTypes.delayModLFO:
|
|
96
|
-
return DLSDestinations.modLfoDelay;
|
|
97
|
-
|
|
98
|
-
case generatorTypes.delayVibLFO:
|
|
99
|
-
return DLSDestinations.vibLfoDelay;
|
|
100
|
-
case generatorTypes.freqVibLFO:
|
|
101
|
-
return DLSDestinations.vibLfoFreq;
|
|
102
|
-
|
|
103
|
-
case generatorTypes.delayVolEnv:
|
|
104
|
-
return DLSDestinations.volEnvDelay;
|
|
105
|
-
case generatorTypes.attackVolEnv:
|
|
106
|
-
return DLSDestinations.volEnvAttack;
|
|
107
|
-
case generatorTypes.holdVolEnv:
|
|
108
|
-
return DLSDestinations.volEnvHold;
|
|
109
|
-
case generatorTypes.decayVolEnv:
|
|
110
|
-
return DLSDestinations.volEnvDecay;
|
|
111
|
-
case generatorTypes.sustainVolEnv:
|
|
112
|
-
return { dest: DLSDestinations.volEnvSustain, amount: 1000 - amount };
|
|
113
|
-
case generatorTypes.releaseVolEnv:
|
|
114
|
-
return DLSDestinations.volEnvRelease;
|
|
115
|
-
|
|
116
|
-
case generatorTypes.delayModEnv:
|
|
117
|
-
return DLSDestinations.modEnvDelay;
|
|
118
|
-
case generatorTypes.attackModEnv:
|
|
119
|
-
return DLSDestinations.modEnvAttack;
|
|
120
|
-
case generatorTypes.holdModEnv:
|
|
121
|
-
return DLSDestinations.modEnvHold;
|
|
122
|
-
case generatorTypes.decayModEnv:
|
|
123
|
-
return DLSDestinations.modEnvDecay;
|
|
124
|
-
case generatorTypes.sustainModEnv:
|
|
125
|
-
return { dest: DLSDestinations.modEnvSustain, amount: 1000 - amount };
|
|
126
|
-
case generatorTypes.releaseModEnv:
|
|
127
|
-
return DLSDestinations.modEnvRelease;
|
|
128
|
-
|
|
129
|
-
case generatorTypes.initialFilterFc:
|
|
130
|
-
return DLSDestinations.filterCutoff;
|
|
131
|
-
case generatorTypes.initialFilterQ:
|
|
132
|
-
return DLSDestinations.filterQ;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* @param dest {number}
|
|
138
|
-
* @param amt {number}
|
|
139
|
-
* @returns {{source: DLSSources, dest: DLSDestinations, amt: number, isBipolar: boolean}|undefined}
|
|
140
|
-
*/
|
|
141
|
-
function checkSF2SpecialCombos(dest, amt)
|
|
142
|
-
{
|
|
143
|
-
|
|
144
|
-
switch (dest)
|
|
145
|
-
{
|
|
146
|
-
default:
|
|
147
|
-
return undefined;
|
|
148
|
-
// mod env
|
|
149
|
-
case generatorTypes.modEnvToFilterFc:
|
|
150
|
-
return { source: DLSSources.modEnv, dest: DLSDestinations.filterCutoff, amt: amt, isBipolar: false };
|
|
151
|
-
case generatorTypes.modEnvToPitch:
|
|
152
|
-
return { source: DLSSources.modEnv, dest: DLSDestinations.pitch, amt: amt, isBipolar: false };
|
|
153
|
-
|
|
154
|
-
// mod lfo
|
|
155
|
-
case generatorTypes.modLfoToFilterFc:
|
|
156
|
-
return { source: DLSSources.modLfo, dest: DLSDestinations.filterCutoff, amt: amt, isBipolar: true };
|
|
157
|
-
case generatorTypes.modLfoToVolume:
|
|
158
|
-
return { source: DLSSources.modLfo, dest: DLSDestinations.gain, amt: amt, isBipolar: true };
|
|
159
|
-
case generatorTypes.modLfoToPitch:
|
|
160
|
-
return { source: DLSSources.modLfo, dest: DLSDestinations.pitch, amt: amt, isBipolar: true };
|
|
161
|
-
|
|
162
|
-
// vib lfo
|
|
163
|
-
case generatorTypes.vibLfoToPitch:
|
|
164
|
-
return { source: DLSSources.vibratoLfo, dest: DLSDestinations.pitch, amt: amt, isBipolar: true };
|
|
165
|
-
|
|
166
|
-
// key to something
|
|
167
|
-
case generatorTypes.keyNumToVolEnvHold:
|
|
168
|
-
return {
|
|
169
|
-
source: DLSSources.keyNum,
|
|
170
|
-
dest: DLSDestinations.volEnvHold,
|
|
171
|
-
amt: amt,
|
|
172
|
-
isBipolar: true
|
|
173
|
-
};
|
|
174
|
-
case generatorTypes.keyNumToVolEnvDecay:
|
|
175
|
-
return {
|
|
176
|
-
source: DLSSources.keyNum,
|
|
177
|
-
dest: DLSDestinations.volEnvDecay,
|
|
178
|
-
amt: amt,
|
|
179
|
-
isBipolar: true
|
|
180
|
-
};
|
|
181
|
-
case generatorTypes.keyNumToModEnvHold:
|
|
182
|
-
return {
|
|
183
|
-
source: DLSSources.keyNum,
|
|
184
|
-
dest: DLSDestinations.modEnvHold,
|
|
185
|
-
amt: amt,
|
|
186
|
-
isBipolar: true
|
|
187
|
-
};
|
|
188
|
-
case generatorTypes.keyNumToModEnvDecay:
|
|
189
|
-
return {
|
|
190
|
-
source: DLSSources.keyNum,
|
|
191
|
-
dest: DLSDestinations.modEnvDecay,
|
|
192
|
-
amt: amt,
|
|
193
|
-
isBipolar: true
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
// Scale tuning is implemented in DLS via an articulator:
|
|
197
|
-
// keyNum to relative pitch at 12,800 cents.
|
|
198
|
-
// Change that to scale tuning * 128.
|
|
199
|
-
// Therefore, a regular scale is still 12,800, half is 6400, etc.
|
|
200
|
-
case generatorTypes.scaleTuning:
|
|
201
|
-
return {
|
|
202
|
-
source: DLSSources.keyNum,
|
|
203
|
-
dest: DLSDestinations.pitch,
|
|
204
|
-
amt: amt * 128,
|
|
205
|
-
isBipolar: false // according to table 4, this should be false.
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* @param gen {Generator}
|
|
212
|
-
* @returns {Articulator|undefined}
|
|
213
|
-
*/
|
|
214
|
-
export function getDLSArticulatorFromSf2Generator(gen)
|
|
215
|
-
{
|
|
216
|
-
const dest = getDLSDestinationFromSf2(gen.generatorType, gen.generatorValue);
|
|
217
|
-
let destination = dest;
|
|
218
|
-
let source = 0;
|
|
219
|
-
let amount = gen.generatorValue;
|
|
220
|
-
if (dest?.amount !== undefined)
|
|
221
|
-
{
|
|
222
|
-
amount = dest.amount;
|
|
223
|
-
destination = dest.dest;
|
|
224
|
-
}
|
|
225
|
-
// check for special combo
|
|
226
|
-
const combo = checkSF2SpecialCombos(gen.generatorType, gen.generatorValue);
|
|
227
|
-
if (combo !== undefined)
|
|
228
|
-
{
|
|
229
|
-
amount = combo.amt;
|
|
230
|
-
destination = combo.dest;
|
|
231
|
-
source = combo.source;
|
|
232
|
-
}
|
|
233
|
-
else if (destination === undefined)
|
|
234
|
-
{
|
|
235
|
-
SpessaSynthWarn(`Invalid generator type: ${gen.generatorType}`);
|
|
236
|
-
return undefined;
|
|
237
|
-
}
|
|
238
|
-
return new Articulator(
|
|
239
|
-
source,
|
|
240
|
-
0,
|
|
241
|
-
destination,
|
|
242
|
-
amount,
|
|
243
|
-
0
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* @param mod {Modulator}
|
|
250
|
-
* @returns {Articulator|undefined}
|
|
251
|
-
*/
|
|
252
|
-
export function getDLSArticulatorFromSf2Modulator(mod)
|
|
253
|
-
{
|
|
254
|
-
if (mod.transformType !== 0)
|
|
255
|
-
{
|
|
256
|
-
SpessaSynthWarn("Other transform types are not supported.");
|
|
257
|
-
return undefined;
|
|
258
|
-
}
|
|
259
|
-
let source = getDLSSourceFromSf2Source(mod.sourceUsesCC, mod.sourceIndex);
|
|
260
|
-
let sourceTransformType = mod.sourceCurveType;
|
|
261
|
-
let sourceBipolar = mod.sourcePolarity;
|
|
262
|
-
let sourceDirection = mod.sourceDirection;
|
|
263
|
-
if (source === undefined)
|
|
264
|
-
{
|
|
265
|
-
SpessaSynthWarn(`Invalid source: ${mod.sourceIndex}, CC: ${mod.sourceUsesCC}`);
|
|
266
|
-
return undefined;
|
|
267
|
-
}
|
|
268
|
-
// Attenuation is the opposite of gain. Invert.
|
|
269
|
-
if (mod.modulatorDestination === generatorTypes.initialAttenuation)
|
|
270
|
-
{
|
|
271
|
-
sourceDirection = sourceDirection === 1 ? 0 : 1;
|
|
272
|
-
}
|
|
273
|
-
let control = getDLSSourceFromSf2Source(mod.secSrcUsesCC, mod.secSrcIndex);
|
|
274
|
-
let controlTransformType = mod.secSrcCurveType;
|
|
275
|
-
let controlBipolar = mod.secSrcPolarity;
|
|
276
|
-
let controlDirection = mod.secSrcDirection;
|
|
277
|
-
if (control === undefined)
|
|
278
|
-
{
|
|
279
|
-
SpessaSynthWarn(`Invalid secondary source: ${mod.secSrcIndex}, CC: ${mod.secSrcUsesCC}`);
|
|
280
|
-
return undefined;
|
|
281
|
-
}
|
|
282
|
-
let dlsDestinationFromSf2 = getDLSDestinationFromSf2(mod.modulatorDestination, mod.transformAmount);
|
|
283
|
-
let destination = dlsDestinationFromSf2;
|
|
284
|
-
let amt = mod.transformAmount;
|
|
285
|
-
if (dlsDestinationFromSf2?.dest !== undefined)
|
|
286
|
-
{
|
|
287
|
-
destination = dlsDestinationFromSf2.dest;
|
|
288
|
-
amt = dlsDestinationFromSf2.amount;
|
|
289
|
-
}
|
|
290
|
-
const specialCombo = checkSF2SpecialCombos(mod.modulatorDestination, mod.transformAmount);
|
|
291
|
-
if (specialCombo !== undefined)
|
|
292
|
-
{
|
|
293
|
-
amt = specialCombo.amt;
|
|
294
|
-
// move the source to control
|
|
295
|
-
control = source;
|
|
296
|
-
controlTransformType = sourceTransformType;
|
|
297
|
-
controlBipolar = sourceBipolar;
|
|
298
|
-
controlDirection = sourceDirection;
|
|
299
|
-
|
|
300
|
-
// set source as static as it's either: env, lfo or key num
|
|
301
|
-
sourceTransformType = modulatorCurveTypes.linear;
|
|
302
|
-
sourceBipolar = specialCombo.isBipolar ? 1 : 0;
|
|
303
|
-
sourceDirection = 0;
|
|
304
|
-
source = specialCombo.source;
|
|
305
|
-
destination = specialCombo.dest;
|
|
306
|
-
}
|
|
307
|
-
else if (destination === undefined)
|
|
308
|
-
{
|
|
309
|
-
SpessaSynthWarn(`Invalid destination: ${mod.modulatorDestination}`);
|
|
310
|
-
return undefined;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// source curve type maps to a desfont curve type in section 2.10, table 9
|
|
314
|
-
let transform = 0;
|
|
315
|
-
transform |= controlTransformType << 4;
|
|
316
|
-
transform |= controlBipolar << 8;
|
|
317
|
-
transform |= controlDirection << 9;
|
|
318
|
-
|
|
319
|
-
// use the source curve in output transform
|
|
320
|
-
transform |= sourceTransformType;
|
|
321
|
-
transform |= sourceBipolar << 14;
|
|
322
|
-
transform |= sourceDirection << 15;
|
|
323
|
-
return new Articulator(
|
|
324
|
-
source,
|
|
325
|
-
control,
|
|
326
|
-
destination,
|
|
327
|
-
amt,
|
|
328
|
-
transform
|
|
329
|
-
);
|
|
330
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
|
-
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import { writeRIFFChunkParts, writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
|
-
import { writeWavesample } from "./wsmp.js";
|
|
5
|
-
import { writeArticulator } from "./art2.js";
|
|
6
|
-
import { generatorTypes } from "../generator_types.js";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @param zone {BasicInstrumentZone}
|
|
10
|
-
* @param globalZone {BasicGlobalZone}
|
|
11
|
-
* @this {BasicSoundBank}
|
|
12
|
-
* @returns {IndexedByteArray}
|
|
13
|
-
*/
|
|
14
|
-
export function writeDLSRegion(zone, globalZone)
|
|
15
|
-
{
|
|
16
|
-
// region header
|
|
17
|
-
const rgnhData = new IndexedByteArray(12);
|
|
18
|
-
// keyRange
|
|
19
|
-
writeWord(rgnhData, Math.max(zone.keyRange.min, 0));
|
|
20
|
-
writeWord(rgnhData, zone.keyRange.max);
|
|
21
|
-
// velRange
|
|
22
|
-
writeWord(rgnhData, Math.max(zone.velRange.min, 0));
|
|
23
|
-
writeWord(rgnhData, zone.velRange.max);
|
|
24
|
-
// fusOptions: 0 it seems
|
|
25
|
-
writeWord(rgnhData, 0);
|
|
26
|
-
// keyGroup (exclusive class)
|
|
27
|
-
const exclusive = zone.getGeneratorValue(generatorTypes.exclusiveClass, 0);
|
|
28
|
-
writeWord(rgnhData, exclusive);
|
|
29
|
-
// usLayer
|
|
30
|
-
writeWord(rgnhData, 0);
|
|
31
|
-
const rgnh = writeRIFFChunkRaw(
|
|
32
|
-
"rgnh",
|
|
33
|
-
rgnhData
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
let rootKey = zone.getGeneratorValue(generatorTypes.overridingRootKey, zone.sample.samplePitch);
|
|
37
|
-
|
|
38
|
-
// a lot of soundfonts like to set scale tuning to 0 in drums and keep the key at 60
|
|
39
|
-
// since we implement scale tuning via a dls articulator and fluid doesn't support these,
|
|
40
|
-
// change the root key here
|
|
41
|
-
const scaleTuning = zone.getGeneratorValue(
|
|
42
|
-
generatorTypes.scaleTuning,
|
|
43
|
-
globalZone.getGeneratorValue(generatorTypes.scaleTuning, 100)
|
|
44
|
-
);
|
|
45
|
-
if (scaleTuning === 0 && zone.keyRange.max - zone.keyRange.min === 0)
|
|
46
|
-
{
|
|
47
|
-
rootKey = zone.keyRange.min;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// wave sample (Wsmp)
|
|
51
|
-
const wsmp = writeWavesample(
|
|
52
|
-
zone.sample,
|
|
53
|
-
rootKey,
|
|
54
|
-
zone.getGeneratorValue(
|
|
55
|
-
generatorTypes.fineTune,
|
|
56
|
-
0
|
|
57
|
-
) + zone.getGeneratorValue(generatorTypes.coarseTune, 0) * 100
|
|
58
|
-
+ zone.sample.samplePitchCorrection,
|
|
59
|
-
zone.getGeneratorValue(generatorTypes.initialAttenuation, 0),
|
|
60
|
-
// calculate loop with offsets
|
|
61
|
-
zone.sample.sampleLoopStartIndex
|
|
62
|
-
+ zone.getGeneratorValue(generatorTypes.startloopAddrsOffset, 0)
|
|
63
|
-
+ zone.getGeneratorValue(generatorTypes.startloopAddrsCoarseOffset, 0) * 32768,
|
|
64
|
-
zone.sample.sampleLoopEndIndex
|
|
65
|
-
+ zone.getGeneratorValue(generatorTypes.endloopAddrsOffset, 0)
|
|
66
|
-
+ zone.getGeneratorValue(generatorTypes.endloopAddrsCoarseOffset, 0) * 32768,
|
|
67
|
-
zone.getGeneratorValue(generatorTypes.sampleModes, 0)
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
// wave link (wlnk)
|
|
71
|
-
const wlnkData = new IndexedByteArray(12);
|
|
72
|
-
writeWord(wlnkData, 0); // fusOptions
|
|
73
|
-
writeWord(wlnkData, 0); // usPhaseGroup
|
|
74
|
-
// let sampleType = 0;
|
|
75
|
-
// switch (zone.sample.sampleType)
|
|
76
|
-
// {
|
|
77
|
-
// default:
|
|
78
|
-
// case 1:
|
|
79
|
-
// case 4:
|
|
80
|
-
// // mono/left
|
|
81
|
-
// sampleType = 0;
|
|
82
|
-
// break;
|
|
83
|
-
//
|
|
84
|
-
// case 2:
|
|
85
|
-
// // right
|
|
86
|
-
// sampleType = 1;
|
|
87
|
-
// }
|
|
88
|
-
// 1 means that the first bit is on so mono/left
|
|
89
|
-
writeDword(wlnkData, 1); // ulChannel
|
|
90
|
-
writeDword(wlnkData, this.samples.indexOf(zone.sample)); // ulTableIndex
|
|
91
|
-
const wlnk = writeRIFFChunkRaw(
|
|
92
|
-
"wlnk",
|
|
93
|
-
wlnkData
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// art
|
|
97
|
-
let lar2 = new IndexedByteArray(0);
|
|
98
|
-
if (zone.modulators.length + zone.generators.length > 0)
|
|
99
|
-
{
|
|
100
|
-
const art2 = writeArticulator(zone);
|
|
101
|
-
|
|
102
|
-
lar2 = writeRIFFChunkRaw(
|
|
103
|
-
"lar2",
|
|
104
|
-
art2,
|
|
105
|
-
false,
|
|
106
|
-
true
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return writeRIFFChunkParts(
|
|
111
|
-
"rgn2",
|
|
112
|
-
[
|
|
113
|
-
rgnh,
|
|
114
|
-
wsmp,
|
|
115
|
-
wlnk,
|
|
116
|
-
lar2
|
|
117
|
-
],
|
|
118
|
-
true
|
|
119
|
-
);
|
|
120
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
|
-
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import { writeRIFFChunkParts, writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
|
-
import { writeWavesample } from "./wsmp.js";
|
|
5
|
-
import { SpessaSynthInfo } from "../../../utils/loggin.js";
|
|
6
|
-
import { consoleColors } from "../../../utils/other.js";
|
|
7
|
-
import { getStringBytes } from "../../../utils/byte_functions/string.js";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @param sample {BasicSample}
|
|
11
|
-
* @returns {IndexedByteArray}
|
|
12
|
-
*/
|
|
13
|
-
export function writeDLSSample(sample)
|
|
14
|
-
{
|
|
15
|
-
const fmtData = new IndexedByteArray(18);
|
|
16
|
-
writeWord(fmtData, 1); // wFormatTag
|
|
17
|
-
writeWord(fmtData, 1); // wChannels
|
|
18
|
-
writeDword(fmtData, sample.sampleRate);
|
|
19
|
-
writeDword(fmtData, sample.sampleRate * 2); // 16-bit samples
|
|
20
|
-
writeWord(fmtData, 2); // wBlockAlign
|
|
21
|
-
writeWord(fmtData, 16); // wBitsPerSample
|
|
22
|
-
const fmt = writeRIFFChunkRaw(
|
|
23
|
-
"fmt ",
|
|
24
|
-
fmtData
|
|
25
|
-
);
|
|
26
|
-
let loop = 1;
|
|
27
|
-
if (sample.sampleLoopStartIndex + Math.abs(sample.getAudioData().length - sample.sampleLoopEndIndex) < 2)
|
|
28
|
-
{
|
|
29
|
-
loop = 0;
|
|
30
|
-
}
|
|
31
|
-
const wsmp = writeWavesample(
|
|
32
|
-
sample,
|
|
33
|
-
sample.samplePitch,
|
|
34
|
-
sample.samplePitchCorrection,
|
|
35
|
-
0,
|
|
36
|
-
sample.sampleLoopStartIndex,
|
|
37
|
-
sample.sampleLoopEndIndex,
|
|
38
|
-
loop
|
|
39
|
-
);
|
|
40
|
-
let data = writeRIFFChunkRaw(
|
|
41
|
-
"data",
|
|
42
|
-
sample.getRawData(false) // no vorbis allowed
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
const inam = writeRIFFChunkRaw(
|
|
46
|
-
"INAM",
|
|
47
|
-
getStringBytes(sample.sampleName, true)
|
|
48
|
-
);
|
|
49
|
-
const info = writeRIFFChunkRaw(
|
|
50
|
-
"INFO",
|
|
51
|
-
inam,
|
|
52
|
-
false,
|
|
53
|
-
true
|
|
54
|
-
);
|
|
55
|
-
SpessaSynthInfo(
|
|
56
|
-
`%cSaved %c${sample.sampleName}%c succesfully!`,
|
|
57
|
-
consoleColors.recognized,
|
|
58
|
-
consoleColors.value,
|
|
59
|
-
consoleColors.recognized
|
|
60
|
-
);
|
|
61
|
-
return writeRIFFChunkParts(
|
|
62
|
-
"wave",
|
|
63
|
-
[
|
|
64
|
-
fmt,
|
|
65
|
-
wsmp,
|
|
66
|
-
data,
|
|
67
|
-
info
|
|
68
|
-
],
|
|
69
|
-
true
|
|
70
|
-
);
|
|
71
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { writeRIFFChunkParts, writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
2
|
-
import { writeDword } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
4
|
-
import { writeLins } from "./lins.js";
|
|
5
|
-
import { getStringBytes } from "../../../utils/byte_functions/string.js";
|
|
6
|
-
import { writeWavePool } from "./wvpl.js";
|
|
7
|
-
import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo } from "../../../utils/loggin.js";
|
|
8
|
-
import { consoleColors } from "../../../utils/other.js";
|
|
9
|
-
import { fillWithDefaults } from "../../../utils/fill_with_defaults.js";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @typedef {Object} DLSWriteOptions
|
|
13
|
-
* @property {ProgressFunction} progressFunction - a function to show progress for writing large banks. It can be undefined.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @type {DLSWriteOptions}
|
|
19
|
-
*/
|
|
20
|
-
const DEFAULT_DLS_OPTIONS = {
|
|
21
|
-
progressFunction: undefined
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Write the soundfont as a .dls file. Experimental
|
|
26
|
-
* @this {BasicSoundBank}
|
|
27
|
-
* @param {Partial<DLSWriteOptions>} options - options for writing the file.
|
|
28
|
-
* @returns {Uint8Array}
|
|
29
|
-
*/
|
|
30
|
-
export async function writeDLS(options = DEFAULT_DLS_OPTIONS)
|
|
31
|
-
{
|
|
32
|
-
options = fillWithDefaults(options, DEFAULT_DLS_OPTIONS);
|
|
33
|
-
SpessaSynthGroupCollapsed(
|
|
34
|
-
"%cSaving DLS...",
|
|
35
|
-
consoleColors.info
|
|
36
|
-
);
|
|
37
|
-
// write colh
|
|
38
|
-
const colhNum = new IndexedByteArray(4);
|
|
39
|
-
writeDword(colhNum, this.presets.length);
|
|
40
|
-
const colh = writeRIFFChunkRaw(
|
|
41
|
-
"colh",
|
|
42
|
-
colhNum
|
|
43
|
-
);
|
|
44
|
-
SpessaSynthGroupCollapsed(
|
|
45
|
-
"%cWriting instruments...",
|
|
46
|
-
consoleColors.info
|
|
47
|
-
);
|
|
48
|
-
const lins = writeLins.apply(this);
|
|
49
|
-
SpessaSynthInfo(
|
|
50
|
-
"%cSuccess!",
|
|
51
|
-
consoleColors.recognized
|
|
52
|
-
);
|
|
53
|
-
SpessaSynthGroupEnd();
|
|
54
|
-
|
|
55
|
-
SpessaSynthGroupCollapsed(
|
|
56
|
-
"%cWriting WAVE samples...",
|
|
57
|
-
consoleColors.info
|
|
58
|
-
);
|
|
59
|
-
const wavepool = await writeWavePool.call(this, options.progressFunction);
|
|
60
|
-
const wvpl = wavepool.data;
|
|
61
|
-
const ptblOffsets = wavepool.indexes;
|
|
62
|
-
SpessaSynthInfo("%cSucceeded!", consoleColors.recognized);
|
|
63
|
-
SpessaSynthGroupEnd();
|
|
64
|
-
|
|
65
|
-
// write ptbl
|
|
66
|
-
const ptblData = new IndexedByteArray(8 + 4 * ptblOffsets.length);
|
|
67
|
-
writeDword(ptblData, 8);
|
|
68
|
-
writeDword(ptblData, ptblOffsets.length);
|
|
69
|
-
for (const offset of ptblOffsets)
|
|
70
|
-
{
|
|
71
|
-
writeDword(ptblData, offset);
|
|
72
|
-
}
|
|
73
|
-
const ptbl = writeRIFFChunkRaw(
|
|
74
|
-
"ptbl",
|
|
75
|
-
ptblData
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
this.soundFontInfo["ICMT"] = (this.soundFontInfo["ICMT"] || "Soundfont") + "\nConverted from SF2 to DLS using SpessaSynth";
|
|
79
|
-
this.soundFontInfo["ISFT"] = "SpessaSynth";
|
|
80
|
-
// write INFO
|
|
81
|
-
const infos = [];
|
|
82
|
-
for (const [info, data] of Object.entries(this.soundFontInfo))
|
|
83
|
-
{
|
|
84
|
-
if (
|
|
85
|
-
info !== "ICMT" &&
|
|
86
|
-
info !== "INAM" &&
|
|
87
|
-
info !== "ICRD" &&
|
|
88
|
-
info !== "IENG" &&
|
|
89
|
-
info !== "ICOP" &&
|
|
90
|
-
info !== "ISFT" &&
|
|
91
|
-
info !== "ISBJ"
|
|
92
|
-
)
|
|
93
|
-
{
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
infos.push(
|
|
97
|
-
writeRIFFChunkRaw(
|
|
98
|
-
info,
|
|
99
|
-
getStringBytes(data, true)
|
|
100
|
-
)
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
const info = writeRIFFChunkParts(
|
|
104
|
-
"INFO",
|
|
105
|
-
infos,
|
|
106
|
-
true
|
|
107
|
-
);
|
|
108
|
-
SpessaSynthInfo(
|
|
109
|
-
"%cSaved succesfully!",
|
|
110
|
-
consoleColors.recognized
|
|
111
|
-
);
|
|
112
|
-
SpessaSynthGroupEnd();
|
|
113
|
-
return writeRIFFChunkParts(
|
|
114
|
-
"RIFF",
|
|
115
|
-
[
|
|
116
|
-
getStringBytes("DLS "),
|
|
117
|
-
colh,
|
|
118
|
-
lins,
|
|
119
|
-
ptbl,
|
|
120
|
-
wvpl,
|
|
121
|
-
info
|
|
122
|
-
]
|
|
123
|
-
);
|
|
124
|
-
}
|