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,78 +0,0 @@
|
|
|
1
|
-
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
2
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
3
|
-
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
|
-
|
|
5
|
-
const WSMP_SIZE = 20;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @param sample {BasicSample}
|
|
9
|
-
* @param rootKey {number}
|
|
10
|
-
* @param tuning {number}
|
|
11
|
-
* @param attenuationCentibels {number} CENTIBELS, NO CORRECTION
|
|
12
|
-
* @param loopStart {number}
|
|
13
|
-
* @param loopEnd {number}
|
|
14
|
-
* @param loopingMode {number}
|
|
15
|
-
* @returns {IndexedByteArray}
|
|
16
|
-
*/
|
|
17
|
-
export function writeWavesample(
|
|
18
|
-
sample,
|
|
19
|
-
rootKey,
|
|
20
|
-
tuning,
|
|
21
|
-
attenuationCentibels,
|
|
22
|
-
loopStart,
|
|
23
|
-
loopEnd,
|
|
24
|
-
loopingMode)
|
|
25
|
-
{
|
|
26
|
-
let loopCount = loopingMode === 0 ? 0 : 1;
|
|
27
|
-
const wsmpData = new IndexedByteArray(WSMP_SIZE + loopCount * 16);
|
|
28
|
-
writeDword(wsmpData, WSMP_SIZE); // cbSize
|
|
29
|
-
// usUnityNote (apply root pitch here)
|
|
30
|
-
writeWord(wsmpData, rootKey);
|
|
31
|
-
// sFineTune
|
|
32
|
-
writeWord(wsmpData, tuning);
|
|
33
|
-
|
|
34
|
-
// gain correction, use InitialAttenuation, apply attenuation correction
|
|
35
|
-
const attenuationCb = attenuationCentibels * 0.4;
|
|
36
|
-
|
|
37
|
-
// gain correction: Each unit of gain represents 1/655360 dB
|
|
38
|
-
const lGain = Math.floor(attenuationCb * -65536);
|
|
39
|
-
writeDword(wsmpData, lGain);
|
|
40
|
-
// fulOptions: has to be 2, according to all DLS files I have
|
|
41
|
-
writeDword(wsmpData, 2);
|
|
42
|
-
|
|
43
|
-
const loopSize = loopEnd - loopStart;
|
|
44
|
-
let ulLoopType = 0;
|
|
45
|
-
switch (loopingMode)
|
|
46
|
-
{
|
|
47
|
-
default:
|
|
48
|
-
case 0:
|
|
49
|
-
// no loop
|
|
50
|
-
loopCount = 0;
|
|
51
|
-
break;
|
|
52
|
-
|
|
53
|
-
case 1:
|
|
54
|
-
// loop
|
|
55
|
-
ulLoopType = 0;
|
|
56
|
-
loopCount = 1;
|
|
57
|
-
break;
|
|
58
|
-
|
|
59
|
-
case 3:
|
|
60
|
-
// loop and release
|
|
61
|
-
ulLoopType = 1;
|
|
62
|
-
loopCount = 1;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// cSampleLoops
|
|
66
|
-
writeDword(wsmpData, loopCount);
|
|
67
|
-
if (loopCount === 1)
|
|
68
|
-
{
|
|
69
|
-
writeDword(wsmpData, 16); // cbSize
|
|
70
|
-
writeDword(wsmpData, ulLoopType);
|
|
71
|
-
writeDword(wsmpData, loopStart);
|
|
72
|
-
writeDword(wsmpData, loopSize);
|
|
73
|
-
}
|
|
74
|
-
return writeRIFFChunkRaw(
|
|
75
|
-
"wsmp",
|
|
76
|
-
wsmpData
|
|
77
|
-
);
|
|
78
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { writeDLSSample } from "./wave.js";
|
|
2
|
-
import { writeRIFFChunkParts } from "../riff_chunk.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @this {BasicSoundBank}
|
|
6
|
-
* @param {ProgressFunction|undefined} progressFunction
|
|
7
|
-
* @returns {Promise<{data: IndexedByteArray, indexes: number[] }>}
|
|
8
|
-
*/
|
|
9
|
-
export async function writeWavePool(progressFunction)
|
|
10
|
-
{
|
|
11
|
-
let currentIndex = 0;
|
|
12
|
-
const offsets = [];
|
|
13
|
-
/**
|
|
14
|
-
* @type {IndexedByteArray[]}
|
|
15
|
-
*/
|
|
16
|
-
const samples = [];
|
|
17
|
-
let written = 0;
|
|
18
|
-
for (const s of this.samples)
|
|
19
|
-
{
|
|
20
|
-
const out = writeDLSSample(s);
|
|
21
|
-
await progressFunction?.(s.sampleName, written, this.samples.length);
|
|
22
|
-
offsets.push(currentIndex);
|
|
23
|
-
currentIndex += out.length;
|
|
24
|
-
samples.push(out);
|
|
25
|
-
written++;
|
|
26
|
-
}
|
|
27
|
-
return {
|
|
28
|
-
data: writeRIFFChunkParts(
|
|
29
|
-
"wvpl",
|
|
30
|
-
samples,
|
|
31
|
-
true
|
|
32
|
-
),
|
|
33
|
-
indexes: offsets
|
|
34
|
-
};
|
|
35
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
|
-
import { writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
|
-
|
|
5
|
-
const BAG_SIZE = 4;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @this {BasicSoundBank}
|
|
9
|
-
* @returns {ReturnedExtendedSf2Chunks}
|
|
10
|
-
*/
|
|
11
|
-
export function getIBAG()
|
|
12
|
-
{
|
|
13
|
-
// write all ibag with their start indexes as they were changed in getIGEN() and getIMOD()
|
|
14
|
-
const ibagSize = this.instruments.reduce(
|
|
15
|
-
(sum, i) =>
|
|
16
|
-
// +1 because global zone
|
|
17
|
-
(i.instrumentZones.length + 1) * BAG_SIZE + sum,
|
|
18
|
-
BAG_SIZE
|
|
19
|
-
);
|
|
20
|
-
const ibagData = new IndexedByteArray(ibagSize);
|
|
21
|
-
// https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md
|
|
22
|
-
const xibagData = new IndexedByteArray(ibagSize);
|
|
23
|
-
let generatorIndex = 0;
|
|
24
|
-
let modulatorIndex = 0;
|
|
25
|
-
/**
|
|
26
|
-
* @param z {BasicZone}
|
|
27
|
-
*/
|
|
28
|
-
const writeZone = z =>
|
|
29
|
-
{
|
|
30
|
-
// bottom WORD: regular ibag
|
|
31
|
-
writeWord(ibagData, generatorIndex & 0xFFFF);
|
|
32
|
-
writeWord(ibagData, modulatorIndex & 0xFFFF);
|
|
33
|
-
// top WORD: extended ibag
|
|
34
|
-
writeWord(xibagData, generatorIndex >> 16);
|
|
35
|
-
writeWord(xibagData, modulatorIndex >> 16);
|
|
36
|
-
generatorIndex += z.generators.length;
|
|
37
|
-
modulatorIndex += z.modulators.length;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
for (const inst of this.instruments)
|
|
41
|
-
{
|
|
42
|
-
writeZone(inst.globalZone);
|
|
43
|
-
for (const ibag of inst.instrumentZones)
|
|
44
|
-
{
|
|
45
|
-
writeZone(ibag);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
// write the terminal IBAG
|
|
49
|
-
writeWord(ibagData, generatorIndex & 0xFFFF);
|
|
50
|
-
writeWord(ibagData, modulatorIndex & 0xFFFF);
|
|
51
|
-
writeWord(xibagData, generatorIndex >> 16);
|
|
52
|
-
writeWord(xibagData, modulatorIndex >> 16);
|
|
53
|
-
const ibag = writeRIFFChunkRaw("ibag", ibagData);
|
|
54
|
-
const xibag = writeRIFFChunkRaw("ibag", xibagData);
|
|
55
|
-
return {
|
|
56
|
-
pdta: ibag,
|
|
57
|
-
xdta: xibag,
|
|
58
|
-
highestIndex: Math.max(generatorIndex, modulatorIndex)
|
|
59
|
-
};
|
|
60
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
2
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
3
|
-
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
|
-
import { GEN_BYTE_SIZE, Generator } from "../generator.js";
|
|
5
|
-
import { generatorTypes } from "../generator_types.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @this {BasicSoundBank}
|
|
9
|
-
* @returns {ReturnedExtendedSf2Chunks}
|
|
10
|
-
*/
|
|
11
|
-
export function getIGEN()
|
|
12
|
-
{
|
|
13
|
-
// go through all instruments -> zones and write generators sequentially (add 4 for terminal)
|
|
14
|
-
let igenSize = GEN_BYTE_SIZE;
|
|
15
|
-
for (const inst of this.instruments)
|
|
16
|
-
{
|
|
17
|
-
igenSize += inst.globalZone.generators.length * GEN_BYTE_SIZE;
|
|
18
|
-
igenSize += inst.instrumentZones.reduce((sum, z) =>
|
|
19
|
-
{
|
|
20
|
-
// clear sample and range generators before determining the size
|
|
21
|
-
z.generators = (z.generators.filter(g =>
|
|
22
|
-
g.generatorType !== generatorTypes.sampleID &&
|
|
23
|
-
g.generatorType !== generatorTypes.keyRange &&
|
|
24
|
-
g.generatorType !== generatorTypes.velRange
|
|
25
|
-
));
|
|
26
|
-
// add sample and ranges if necessary
|
|
27
|
-
// unshift vel then key (to make key first) and the sample is last
|
|
28
|
-
if (z.hasVelRange)
|
|
29
|
-
{
|
|
30
|
-
z.prependGenerator(new Generator(
|
|
31
|
-
generatorTypes.velRange,
|
|
32
|
-
z.velRange.max << 8 | Math.max(z.velRange.min, 0),
|
|
33
|
-
false
|
|
34
|
-
));
|
|
35
|
-
}
|
|
36
|
-
if (z.hasKeyRange)
|
|
37
|
-
{
|
|
38
|
-
z.prependGenerator(new Generator(
|
|
39
|
-
generatorTypes.keyRange,
|
|
40
|
-
z.keyRange.max << 8 | Math.max(z.keyRange.min, 0),
|
|
41
|
-
false
|
|
42
|
-
));
|
|
43
|
-
}
|
|
44
|
-
// add sample id
|
|
45
|
-
z.addGenerators(new Generator(
|
|
46
|
-
generatorTypes.sampleID,
|
|
47
|
-
this.samples.indexOf(z.sample),
|
|
48
|
-
false
|
|
49
|
-
));
|
|
50
|
-
return z.generators.length * GEN_BYTE_SIZE + sum;
|
|
51
|
-
}, 0);
|
|
52
|
-
}
|
|
53
|
-
const igenData = new IndexedByteArray(igenSize);
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @param z {BasicZone}
|
|
57
|
-
*/
|
|
58
|
-
const writeZone = z =>
|
|
59
|
-
{
|
|
60
|
-
for (const gen of z.generators)
|
|
61
|
-
{
|
|
62
|
-
// name is deceptive, it works on negatives
|
|
63
|
-
writeWord(igenData, gen.generatorType);
|
|
64
|
-
writeWord(igenData, gen.generatorValue);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
for (const instrument of this.instruments)
|
|
69
|
-
{
|
|
70
|
-
// global zone
|
|
71
|
-
writeZone(instrument.globalZone);
|
|
72
|
-
for (const instrumentZone of instrument.instrumentZones)
|
|
73
|
-
{
|
|
74
|
-
writeZone(instrumentZone);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
// terminal generator, is zero
|
|
78
|
-
writeDword(igenData, 0);
|
|
79
|
-
|
|
80
|
-
// https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md
|
|
81
|
-
const xigenData = new IndexedByteArray(GEN_BYTE_SIZE);
|
|
82
|
-
writeDword(xigenData, 0);
|
|
83
|
-
|
|
84
|
-
const igen = writeRIFFChunkRaw("igen", igenData);
|
|
85
|
-
const xigen = writeRIFFChunkRaw("igen", xigenData);
|
|
86
|
-
return {
|
|
87
|
-
pdta: igen,
|
|
88
|
-
xdta: xigen,
|
|
89
|
-
highestIndex: 0 // not applicable
|
|
90
|
-
};
|
|
91
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
|
-
import { writeLittleEndian, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
|
-
import { MOD_BYTE_SIZE } from "../modulator.js";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @this {BasicSoundBank}
|
|
8
|
-
* @returns {ReturnedExtendedSf2Chunks}
|
|
9
|
-
*/
|
|
10
|
-
export function getIMOD()
|
|
11
|
-
{
|
|
12
|
-
// very similar to igen,
|
|
13
|
-
// go through all instruments -> zones and write modulators sequentially
|
|
14
|
-
let imodSize = MOD_BYTE_SIZE; // terminal
|
|
15
|
-
for (const inst of this.instruments)
|
|
16
|
-
{
|
|
17
|
-
imodSize += inst.globalZone.modulators.length * MOD_BYTE_SIZE;
|
|
18
|
-
// start with one mod for global
|
|
19
|
-
imodSize += inst.instrumentZones.reduce((sum, z) => z.modulators.length * MOD_BYTE_SIZE + sum, 0);
|
|
20
|
-
}
|
|
21
|
-
const imodData = new IndexedByteArray(imodSize);
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @param z {BasicZone}
|
|
25
|
-
*/
|
|
26
|
-
const writeZone = z =>
|
|
27
|
-
{
|
|
28
|
-
for (const mod of z.modulators)
|
|
29
|
-
{
|
|
30
|
-
writeWord(imodData, mod.getSourceEnum());
|
|
31
|
-
writeWord(imodData, mod.modulatorDestination);
|
|
32
|
-
writeWord(imodData, mod.transformAmount);
|
|
33
|
-
writeWord(imodData, mod.getSecSrcEnum());
|
|
34
|
-
writeWord(imodData, mod.transformType);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
for (const inst of this.instruments)
|
|
39
|
-
{
|
|
40
|
-
// global
|
|
41
|
-
writeZone(inst.globalZone);
|
|
42
|
-
for (const instrumentZone of inst.instrumentZones)
|
|
43
|
-
{
|
|
44
|
-
writeZone(instrumentZone);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// terminal modulator, is zero
|
|
49
|
-
writeLittleEndian(imodData, 0, MOD_BYTE_SIZE);
|
|
50
|
-
|
|
51
|
-
// https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md
|
|
52
|
-
const ximodData = new IndexedByteArray(MOD_BYTE_SIZE);
|
|
53
|
-
writeLittleEndian(ximodData, 0, MOD_BYTE_SIZE);
|
|
54
|
-
|
|
55
|
-
const imod = writeRIFFChunkRaw("imod", imodData);
|
|
56
|
-
const ximod = writeRIFFChunkRaw("imod", ximodData);
|
|
57
|
-
return {
|
|
58
|
-
pdta: imod,
|
|
59
|
-
xdta: ximod,
|
|
60
|
-
highestIndex: 0 // not applicable
|
|
61
|
-
};
|
|
62
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
|
-
import { writeStringAsBytes } from "../../../utils/byte_functions/string.js";
|
|
3
|
-
import { writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
4
|
-
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
5
|
-
|
|
6
|
-
const INST_SIZE = 22;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @this {BasicSoundBank}
|
|
10
|
-
* @returns {ReturnedExtendedSf2Chunks}
|
|
11
|
-
*/
|
|
12
|
-
export function getINST()
|
|
13
|
-
{
|
|
14
|
-
const instSize = this.instruments.length * INST_SIZE + INST_SIZE;
|
|
15
|
-
const instData = new IndexedByteArray(instSize);
|
|
16
|
-
// https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md
|
|
17
|
-
const xinstData = new IndexedByteArray(instSize);
|
|
18
|
-
// the instrument start index is adjusted in ibag, write it here
|
|
19
|
-
let instrumentStart = 0;
|
|
20
|
-
for (const inst of this.instruments)
|
|
21
|
-
{
|
|
22
|
-
writeStringAsBytes(instData, inst.instrumentName.substring(0, 20), 20);
|
|
23
|
-
writeStringAsBytes(xinstData, inst.instrumentName.substring(20), 20);
|
|
24
|
-
writeWord(instData, instrumentStart & 0xFFFF);
|
|
25
|
-
writeWord(xinstData, instrumentStart >> 16);
|
|
26
|
-
instrumentStart += inst.instrumentZones.length + 1; // global
|
|
27
|
-
}
|
|
28
|
-
// write EOI
|
|
29
|
-
writeStringAsBytes(instData, "EOI", 20);
|
|
30
|
-
writeStringAsBytes(xinstData, "EOI", 20);
|
|
31
|
-
writeWord(instData, instrumentStart & 0xFFFF);
|
|
32
|
-
writeWord(xinstData, instrumentStart >> 16);
|
|
33
|
-
|
|
34
|
-
const inst = writeRIFFChunkRaw("inst", instData);
|
|
35
|
-
const xinst = writeRIFFChunkRaw("inst", xinstData);
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
pdta: inst,
|
|
39
|
-
xdta: xinst,
|
|
40
|
-
highestIndex: instrumentStart
|
|
41
|
-
};
|
|
42
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
|
-
import { writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
|
-
|
|
5
|
-
const BAG_SIZE = 4;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @this {BasicSoundBank}
|
|
9
|
-
* @returns {ReturnedExtendedSf2Chunks}
|
|
10
|
-
*/
|
|
11
|
-
export function getPBAG()
|
|
12
|
-
{
|
|
13
|
-
// write all pbag with their start indexes as they were changed in getPGEN() and getPMOD()
|
|
14
|
-
const pbagSize = this.presets.reduce((sum, i) =>
|
|
15
|
-
// +1 because global zone
|
|
16
|
-
(i.presetZones.length + 1) * BAG_SIZE + sum, BAG_SIZE);
|
|
17
|
-
const pbagData = new IndexedByteArray(pbagSize);
|
|
18
|
-
// https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md
|
|
19
|
-
const xpbagData = new IndexedByteArray(pbagSize);
|
|
20
|
-
let generatorIndex = 0;
|
|
21
|
-
let modulatorIndex = 0;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* @param z {BasicZone}
|
|
25
|
-
*/
|
|
26
|
-
const writeZone = z =>
|
|
27
|
-
{
|
|
28
|
-
writeWord(pbagData, generatorIndex & 0xFFFF);
|
|
29
|
-
writeWord(pbagData, modulatorIndex & 0xFFFF);
|
|
30
|
-
writeWord(xpbagData, generatorIndex >> 16);
|
|
31
|
-
writeWord(xpbagData, modulatorIndex >> 16);
|
|
32
|
-
generatorIndex += z.generators.length;
|
|
33
|
-
modulatorIndex += z.modulators.length;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
for (const preset of this.presets)
|
|
37
|
-
{
|
|
38
|
-
// global
|
|
39
|
-
writeZone(preset.globalZone);
|
|
40
|
-
for (const pbag of preset.presetZones)
|
|
41
|
-
{
|
|
42
|
-
writeZone(pbag);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
// write the terminal PBAG
|
|
46
|
-
writeWord(pbagData, generatorIndex);
|
|
47
|
-
writeWord(pbagData, modulatorIndex);
|
|
48
|
-
writeWord(xpbagData, generatorIndex);
|
|
49
|
-
writeWord(xpbagData, modulatorIndex);
|
|
50
|
-
const pbag = writeRIFFChunkRaw("pbag", pbagData);
|
|
51
|
-
const xbag = writeRIFFChunkRaw("pbag", xpbagData);
|
|
52
|
-
return {
|
|
53
|
-
pdta: pbag,
|
|
54
|
-
xdta: xbag,
|
|
55
|
-
highestIndex: Math.max(generatorIndex, modulatorIndex)
|
|
56
|
-
};
|
|
57
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
2
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
3
|
-
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
|
-
|
|
5
|
-
import { GEN_BYTE_SIZE, Generator } from "../generator.js";
|
|
6
|
-
import { generatorTypes } from "../generator_types.js";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @this {BasicSoundBank}
|
|
10
|
-
* @returns {ReturnedExtendedSf2Chunks}
|
|
11
|
-
*/
|
|
12
|
-
export function getPGEN()
|
|
13
|
-
{
|
|
14
|
-
// almost identical to igen, except the correct instrument instead of sample gen
|
|
15
|
-
// goes through all preset zones and writes generators sequentially (add 4 for terminal)
|
|
16
|
-
let pgenSize = GEN_BYTE_SIZE;
|
|
17
|
-
for (const preset of this.presets)
|
|
18
|
-
{
|
|
19
|
-
pgenSize += preset.globalZone.generators.length * GEN_BYTE_SIZE;
|
|
20
|
-
pgenSize += preset.presetZones.reduce((size, z) =>
|
|
21
|
-
{
|
|
22
|
-
// clear instrument and range generators before determining the size
|
|
23
|
-
z.generators = z.generators.filter(g =>
|
|
24
|
-
g.generatorType !== generatorTypes.instrument &&
|
|
25
|
-
g.generatorType !== generatorTypes.keyRange &&
|
|
26
|
-
g.generatorType !== generatorTypes.velRange
|
|
27
|
-
);
|
|
28
|
-
// unshift vel then key and instrument is last
|
|
29
|
-
if (z.hasVelRange)
|
|
30
|
-
{
|
|
31
|
-
z.prependGenerator(new Generator(
|
|
32
|
-
generatorTypes.velRange,
|
|
33
|
-
z.velRange.max << 8 | Math.max(z.velRange.min, 0),
|
|
34
|
-
false
|
|
35
|
-
));
|
|
36
|
-
}
|
|
37
|
-
if (z.hasKeyRange)
|
|
38
|
-
{
|
|
39
|
-
z.prependGenerator(new Generator(
|
|
40
|
-
generatorTypes.keyRange,
|
|
41
|
-
z.keyRange.max << 8 | Math.max(z.keyRange.min, 0),
|
|
42
|
-
false
|
|
43
|
-
));
|
|
44
|
-
}
|
|
45
|
-
// write the instrument id
|
|
46
|
-
z.addGenerators(new Generator(
|
|
47
|
-
generatorTypes.instrument,
|
|
48
|
-
this.instruments.indexOf(z.instrument),
|
|
49
|
-
false
|
|
50
|
-
));
|
|
51
|
-
return z.generators.length * GEN_BYTE_SIZE + size;
|
|
52
|
-
}, 0);
|
|
53
|
-
}
|
|
54
|
-
const pgenData = new IndexedByteArray(pgenSize);
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @param z {BasicZone}
|
|
58
|
-
*/
|
|
59
|
-
const writeZone = z =>
|
|
60
|
-
{
|
|
61
|
-
for (const gen of z.generators)
|
|
62
|
-
{
|
|
63
|
-
// name is deceptive, it works on negatives
|
|
64
|
-
writeWord(pgenData, gen.generatorType);
|
|
65
|
-
writeWord(pgenData, gen.generatorValue);
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
for (const preset of this.presets)
|
|
69
|
-
{
|
|
70
|
-
// global zone
|
|
71
|
-
writeZone(preset.globalZone);
|
|
72
|
-
for (const zone of preset.presetZones)
|
|
73
|
-
{
|
|
74
|
-
writeZone(zone);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
// terminal generator, is zero
|
|
78
|
-
writeDword(pgenData, 0);
|
|
79
|
-
|
|
80
|
-
// https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md
|
|
81
|
-
const xpgenData = new IndexedByteArray(GEN_BYTE_SIZE);
|
|
82
|
-
writeDword(xpgenData, 0);
|
|
83
|
-
|
|
84
|
-
const pgen = writeRIFFChunkRaw("pgen", pgenData);
|
|
85
|
-
|
|
86
|
-
const xpgen = writeRIFFChunkRaw("pgen", xpgenData);
|
|
87
|
-
return {
|
|
88
|
-
pdta: pgen,
|
|
89
|
-
xdta: xpgen,
|
|
90
|
-
highestIndex: 0 // not applicable
|
|
91
|
-
};
|
|
92
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
|
-
import { writeStringAsBytes } from "../../../utils/byte_functions/string.js";
|
|
3
|
-
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
4
|
-
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
5
|
-
|
|
6
|
-
const PHDR_SIZE = 38;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @this {BasicSoundBank}
|
|
10
|
-
* @returns {ReturnedExtendedSf2Chunks}
|
|
11
|
-
*/
|
|
12
|
-
export function getPHDR()
|
|
13
|
-
{
|
|
14
|
-
const phdrSize = this.presets.length * PHDR_SIZE + PHDR_SIZE;
|
|
15
|
-
const phdrData = new IndexedByteArray(phdrSize);
|
|
16
|
-
// https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md
|
|
17
|
-
const xphdrData = new IndexedByteArray(phdrSize);
|
|
18
|
-
// the preset start is adjusted in pbag, this is only for the terminal preset index
|
|
19
|
-
let presetStart = 0;
|
|
20
|
-
for (const preset of this.presets)
|
|
21
|
-
{
|
|
22
|
-
writeStringAsBytes(phdrData, preset.presetName.substring(0, 20), 20);
|
|
23
|
-
writeStringAsBytes(xphdrData, preset.presetName.substring(20), 20);
|
|
24
|
-
|
|
25
|
-
writeWord(phdrData, preset.program);
|
|
26
|
-
writeWord(phdrData, preset.bank);
|
|
27
|
-
writeWord(phdrData, presetStart & 0xFFFF);
|
|
28
|
-
|
|
29
|
-
xphdrData.currentIndex += 4;
|
|
30
|
-
writeWord(xphdrData, presetStart >> 16);
|
|
31
|
-
|
|
32
|
-
// 3 unused dword, spec says to keep em so we do
|
|
33
|
-
writeDword(phdrData, preset.library);
|
|
34
|
-
writeDword(phdrData, preset.genre);
|
|
35
|
-
writeDword(phdrData, preset.morphology);
|
|
36
|
-
|
|
37
|
-
xphdrData.currentIndex += 12;
|
|
38
|
-
|
|
39
|
-
presetStart += preset.presetZones.length + 1; // global
|
|
40
|
-
}
|
|
41
|
-
// write EOP
|
|
42
|
-
writeStringAsBytes(phdrData, "EOP", 20);
|
|
43
|
-
phdrData.currentIndex += 4; // program, bank
|
|
44
|
-
writeWord(phdrData, presetStart & 0xFFFF);
|
|
45
|
-
phdrData.currentIndex += 12;// library, genre, morphology
|
|
46
|
-
|
|
47
|
-
writeStringAsBytes(xphdrData, "EOP", 20);
|
|
48
|
-
xphdrData.currentIndex += 4; // program, bank
|
|
49
|
-
writeWord(xphdrData, presetStart >> 16);
|
|
50
|
-
xphdrData.currentIndex += 12;// library, genre, morphology
|
|
51
|
-
|
|
52
|
-
const phdr = writeRIFFChunkRaw("phdr", phdrData);
|
|
53
|
-
|
|
54
|
-
const xphdr = writeRIFFChunkRaw("phdr", xphdrData);
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
pdta: phdr,
|
|
58
|
-
xdta: xphdr,
|
|
59
|
-
highestIndex: presetStart
|
|
60
|
-
};
|
|
61
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
|
-
import { writeLittleEndian, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
|
-
import { writeRIFFChunkRaw } from "../riff_chunk.js";
|
|
4
|
-
import { MOD_BYTE_SIZE } from "../modulator.js";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @this {BasicSoundBank}
|
|
8
|
-
* @returns {ReturnedExtendedSf2Chunks}
|
|
9
|
-
*/
|
|
10
|
-
export function getPMOD()
|
|
11
|
-
{
|
|
12
|
-
// very similar to imod,
|
|
13
|
-
// go through all presets -> zones and write modulators sequentially
|
|
14
|
-
let pmodSize = MOD_BYTE_SIZE;
|
|
15
|
-
for (const preset of this.presets)
|
|
16
|
-
{
|
|
17
|
-
pmodSize += preset.globalZone.modulators.length * MOD_BYTE_SIZE;
|
|
18
|
-
pmodSize += preset.presetZones.reduce((sum, z) => z.modulators.length * MOD_BYTE_SIZE + sum, 0);
|
|
19
|
-
}
|
|
20
|
-
const pmodData = new IndexedByteArray(pmodSize);
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @param z {BasicZone}
|
|
24
|
-
*/
|
|
25
|
-
const writeZone = z =>
|
|
26
|
-
{
|
|
27
|
-
for (const mod of z.modulators)
|
|
28
|
-
{
|
|
29
|
-
writeWord(pmodData, mod.getSourceEnum());
|
|
30
|
-
writeWord(pmodData, mod.modulatorDestination);
|
|
31
|
-
writeWord(pmodData, mod.transformAmount);
|
|
32
|
-
writeWord(pmodData, mod.getSecSrcEnum());
|
|
33
|
-
writeWord(pmodData, mod.transformType);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
for (const preset of this.presets)
|
|
39
|
-
{
|
|
40
|
-
// global
|
|
41
|
-
writeZone(preset.globalZone);
|
|
42
|
-
for (const zone of preset.presetZones)
|
|
43
|
-
{
|
|
44
|
-
writeZone(zone);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// terminal modulator, is zero
|
|
49
|
-
writeLittleEndian(pmodData, 0, MOD_BYTE_SIZE);
|
|
50
|
-
|
|
51
|
-
// https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md
|
|
52
|
-
const xpmodData = new IndexedByteArray(MOD_BYTE_SIZE);
|
|
53
|
-
writeLittleEndian(xpmodData, 0, MOD_BYTE_SIZE);
|
|
54
|
-
|
|
55
|
-
const pmod = writeRIFFChunkRaw("pmod", pmodData);
|
|
56
|
-
const xpmod = writeRIFFChunkRaw("pmod", xpmodData);
|
|
57
|
-
return {
|
|
58
|
-
pdta: pmod,
|
|
59
|
-
xdta: xpmod,
|
|
60
|
-
highestIndex: 0 // not applicable
|
|
61
|
-
};
|
|
62
|
-
}
|