spessasynth_core 3.26.17 → 3.26.18
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/index.js +5 -3
- package/package.json +1 -1
- package/src/externals/README.md +6 -0
- package/src/sequencer/README.md +5 -1
- package/src/soundfont/README.md +6 -8
- package/src/soundfont/basic_soundfont/basic_global_zone.js +16 -0
- package/src/soundfont/basic_soundfont/basic_instrument.js +26 -22
- package/src/soundfont/basic_soundfont/basic_instrument_zone.js +35 -0
- package/src/soundfont/basic_soundfont/basic_preset.js +45 -42
- package/src/soundfont/basic_soundfont/basic_preset_zone.js +30 -0
- package/src/soundfont/basic_soundfont/{basic_soundfont.js → basic_soundbank.js} +22 -44
- package/src/soundfont/basic_soundfont/basic_zone.js +1 -5
- package/src/soundfont/basic_soundfont/generator.js +2 -152
- package/src/soundfont/basic_soundfont/generator_types.js +151 -0
- package/src/soundfont/basic_soundfont/modulator.js +217 -65
- package/src/soundfont/basic_soundfont/write_dls/art2.js +3 -2
- package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +25 -42
- package/src/soundfont/basic_soundfont/write_dls/ins.js +11 -27
- package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +2 -2
- package/src/soundfont/basic_soundfont/write_dls/rgn2.js +2 -2
- package/src/soundfont/basic_soundfont/write_sf2/ibag.js +22 -19
- package/src/soundfont/basic_soundfont/write_sf2/igen.js +29 -25
- package/src/soundfont/basic_soundfont/write_sf2/imod.js +24 -14
- package/src/soundfont/basic_soundfont/write_sf2/inst.js +4 -5
- package/src/soundfont/basic_soundfont/write_sf2/pbag.js +21 -18
- package/src/soundfont/basic_soundfont/write_sf2/pgen.js +30 -27
- package/src/soundfont/basic_soundfont/write_sf2/phdr.js +4 -2
- package/src/soundfont/basic_soundfont/write_sf2/pmod.js +25 -15
- package/src/soundfont/dls/articulator_converter.js +9 -3
- package/src/soundfont/dls/dls_preset.js +2 -3
- package/src/soundfont/dls/dls_soundfont.js +1 -1
- package/src/soundfont/dls/dls_sources.js +7 -6
- package/src/soundfont/dls/dls_zone.js +4 -5
- package/src/soundfont/dls/read_articulation.js +2 -1
- package/src/soundfont/dls/read_instrument.js +3 -6
- package/src/soundfont/dls/read_lart.js +1 -1
- package/src/soundfont/dls/read_region.js +2 -1
- package/src/soundfont/read_sf2/instruments.js +10 -1
- package/src/soundfont/read_sf2/modulators.js +10 -23
- package/src/soundfont/read_sf2/presets.js +10 -1
- package/src/soundfont/read_sf2/soundfont.js +1 -2
- package/src/soundfont/read_sf2/zones.js +30 -14
- package/src/synthetizer/README.md +3 -3
- package/src/synthetizer/audio_engine/README.md +1 -1
- package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +1 -1
- package/src/synthetizer/audio_engine/engine_components/dynamic_modulator_system.js +11 -3
- package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +1 -1
- package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +1 -1
- package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +1 -1
- package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +1 -1
- package/src/synthetizer/audio_engine/engine_components/voice.js +7 -10
- package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +2 -1
- package/src/synthetizer/audio_engine/engine_methods/data_entry/awe32.js +1 -1
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +7 -0
- package/src/synthetizer/audio_engine/engine_methods/note_on.js +1 -1
- package/src/synthetizer/audio_engine/engine_methods/render_voice.js +1 -1
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +1 -1
- package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +2 -1
- package/src/utils/README.md +5 -2
- package/src/soundfont/basic_soundfont/basic_zones.js +0 -43
|
@@ -2,6 +2,8 @@ import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
|
2
2
|
import { writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
3
|
import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
4
4
|
|
|
5
|
+
const BAG_SIZE = 4;
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* @this {BasicSoundBank}
|
|
7
9
|
* @returns {IndexedByteArray}
|
|
@@ -9,36 +11,37 @@ import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
|
9
11
|
export function getIBAG()
|
|
10
12
|
{
|
|
11
13
|
// write all ibag with their start indexes as they were changed in getIGEN() and getIMOD()
|
|
12
|
-
const ibagsize = this.instruments.reduce(
|
|
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
|
+
);
|
|
13
20
|
const ibagdata = new IndexedByteArray(ibagsize);
|
|
14
|
-
let zoneID = 0;
|
|
15
21
|
let generatorIndex = 0;
|
|
16
22
|
let modulatorIndex = 0;
|
|
23
|
+
/**
|
|
24
|
+
* @param z {BasicZone}
|
|
25
|
+
*/
|
|
26
|
+
const writeZone = z =>
|
|
27
|
+
{
|
|
28
|
+
writeWord(ibagdata, generatorIndex);
|
|
29
|
+
writeWord(ibagdata, modulatorIndex);
|
|
30
|
+
generatorIndex += z.generators.length;
|
|
31
|
+
modulatorIndex += z.modulators.length;
|
|
32
|
+
};
|
|
33
|
+
|
|
17
34
|
for (const inst of this.instruments)
|
|
18
35
|
{
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const global = inst.instrumentZones.filter(z => z.isGlobal);
|
|
22
|
-
// only take the first one
|
|
23
|
-
if (global?.[0])
|
|
36
|
+
writeZone(inst.globalZone);
|
|
37
|
+
for (const ibag of inst.instrumentZones)
|
|
24
38
|
{
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
inst.instrumentZoneIndex = zoneID;
|
|
28
|
-
for (const ibag of zones)
|
|
29
|
-
{
|
|
30
|
-
ibag.zoneID = zoneID;
|
|
31
|
-
writeWord(ibagdata, generatorIndex);
|
|
32
|
-
writeWord(ibagdata, modulatorIndex);
|
|
33
|
-
generatorIndex += ibag.generators.length;
|
|
34
|
-
modulatorIndex += ibag.modulators.length;
|
|
35
|
-
zoneID++;
|
|
39
|
+
writeZone(ibag);
|
|
36
40
|
}
|
|
37
41
|
}
|
|
38
42
|
// write the terminal IBAG
|
|
39
43
|
writeWord(ibagdata, generatorIndex);
|
|
40
44
|
writeWord(ibagdata, modulatorIndex);
|
|
41
|
-
|
|
42
45
|
return writeRIFFChunk(new RiffChunk(
|
|
43
46
|
"ibag",
|
|
44
47
|
ibagdata.length,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
2
2
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
3
3
|
import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
4
|
-
|
|
5
|
-
import {
|
|
4
|
+
import { GEN_BYTE_SIZE, Generator } from "../generator.js";
|
|
5
|
+
import { generatorTypes } from "../generator_types.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @this {BasicSoundBank}
|
|
@@ -11,9 +11,10 @@ import { Generator, generatorTypes } from "../generator.js";
|
|
|
11
11
|
export function getIGEN()
|
|
12
12
|
{
|
|
13
13
|
// go through all instruments -> zones and write generators sequentially (add 4 for terminal)
|
|
14
|
-
let igensize =
|
|
14
|
+
let igensize = GEN_BYTE_SIZE;
|
|
15
15
|
for (const inst of this.instruments)
|
|
16
16
|
{
|
|
17
|
+
igensize += inst.globalZone.generators.length * GEN_BYTE_SIZE;
|
|
17
18
|
igensize += inst.instrumentZones.reduce((sum, z) =>
|
|
18
19
|
{
|
|
19
20
|
// clear sample and range generators before determining the size
|
|
@@ -23,7 +24,7 @@ export function getIGEN()
|
|
|
23
24
|
g.generatorType !== generatorTypes.velRange
|
|
24
25
|
);
|
|
25
26
|
// add sample and ranges if necessary
|
|
26
|
-
// unshift vel then key (to make key first) and the
|
|
27
|
+
// unshift vel then key (to make key first) and the sample is last
|
|
27
28
|
if (z.hasVelRange)
|
|
28
29
|
{
|
|
29
30
|
z.generators.unshift(new Generator(
|
|
@@ -40,38 +41,41 @@ export function getIGEN()
|
|
|
40
41
|
false
|
|
41
42
|
));
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
));
|
|
51
|
-
}
|
|
52
|
-
return z.generators.length * 4 + sum;
|
|
44
|
+
// add sample id
|
|
45
|
+
z.generators.push(new Generator(
|
|
46
|
+
generatorTypes.sampleID,
|
|
47
|
+
this.samples.indexOf(z.sample),
|
|
48
|
+
false
|
|
49
|
+
));
|
|
50
|
+
return z.generators.length * GEN_BYTE_SIZE + sum;
|
|
53
51
|
}, 0);
|
|
54
52
|
}
|
|
55
53
|
const igendata = new IndexedByteArray(igensize);
|
|
56
|
-
|
|
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
|
+
|
|
57
68
|
for (const instrument of this.instruments)
|
|
58
69
|
{
|
|
70
|
+
// global zone
|
|
71
|
+
writeZone(instrument.globalZone);
|
|
59
72
|
for (const instrumentZone of instrument.instrumentZones)
|
|
60
73
|
{
|
|
61
|
-
|
|
62
|
-
instrumentZone.generatorZoneStartIndex = igenIndex;
|
|
63
|
-
for (const gen of instrumentZone.generators)
|
|
64
|
-
{
|
|
65
|
-
// name is deceptive, it works on negatives
|
|
66
|
-
writeWord(igendata, gen.generatorType);
|
|
67
|
-
writeWord(igendata, gen.generatorValue);
|
|
68
|
-
igenIndex++;
|
|
69
|
-
}
|
|
74
|
+
writeZone(instrumentZone);
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
// terminal generator, is zero
|
|
73
78
|
writeDword(igendata, 0);
|
|
74
|
-
|
|
75
79
|
return writeRIFFChunk(new RiffChunk(
|
|
76
80
|
"igen",
|
|
77
81
|
igendata.length,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeLittleEndian, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
3
|
import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
4
|
+
import { MOD_BYTE_SIZE } from "../modulator.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @this {BasicSoundBank}
|
|
@@ -10,28 +11,37 @@ export function getIMOD()
|
|
|
10
11
|
{
|
|
11
12
|
// very similar to igen,
|
|
12
13
|
// go through all instruments -> zones and write modulators sequentially
|
|
13
|
-
let imodsize =
|
|
14
|
+
let imodsize = MOD_BYTE_SIZE; // terminal
|
|
14
15
|
for (const inst of this.instruments)
|
|
15
16
|
{
|
|
17
|
+
imodsize += inst.globalZone.modulators.length * MOD_BYTE_SIZE;
|
|
18
|
+
// start with one mod for global
|
|
16
19
|
imodsize += inst.instrumentZones.reduce((sum, z) => z.modulators.length * 10 + sum, 0);
|
|
17
20
|
}
|
|
18
21
|
const imoddata = new IndexedByteArray(imodsize);
|
|
19
|
-
|
|
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
|
+
|
|
20
38
|
for (const inst of this.instruments)
|
|
21
39
|
{
|
|
22
|
-
|
|
40
|
+
// global
|
|
41
|
+
writeZone(inst.globalZone);
|
|
42
|
+
for (const instrumentZone of inst.instrumentZones)
|
|
23
43
|
{
|
|
24
|
-
|
|
25
|
-
ibag.modulatorZoneStartIndex = imodIndex;
|
|
26
|
-
for (const mod of ibag.modulators)
|
|
27
|
-
{
|
|
28
|
-
writeWord(imoddata, mod.getSourceEnum());
|
|
29
|
-
writeWord(imoddata, mod.modulatorDestination);
|
|
30
|
-
writeWord(imoddata, mod.transformAmount);
|
|
31
|
-
writeWord(imoddata, mod.getSecSrcEnum());
|
|
32
|
-
writeWord(imoddata, mod.transformType);
|
|
33
|
-
imodIndex++;
|
|
34
|
-
}
|
|
44
|
+
writeZone(instrumentZone);
|
|
35
45
|
}
|
|
36
46
|
}
|
|
37
47
|
|
|
@@ -3,24 +3,23 @@ import { writeStringAsBytes } from "../../../utils/byte_functions/string.js";
|
|
|
3
3
|
import { writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
4
4
|
import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
5
5
|
|
|
6
|
+
const INST_SIZE = 22;
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* @this {BasicSoundBank}
|
|
8
10
|
* @returns {IndexedByteArray}
|
|
9
11
|
*/
|
|
10
12
|
export function getINST()
|
|
11
13
|
{
|
|
12
|
-
const instsize = this.instruments.length *
|
|
14
|
+
const instsize = this.instruments.length * INST_SIZE + INST_SIZE;
|
|
13
15
|
const instdata = new IndexedByteArray(instsize);
|
|
14
16
|
// the instrument start index is adjusted in ibag, write it here
|
|
15
17
|
let instrumentStart = 0;
|
|
16
|
-
let instrumentID = 0;
|
|
17
18
|
for (const inst of this.instruments)
|
|
18
19
|
{
|
|
19
20
|
writeStringAsBytes(instdata, inst.instrumentName, 20);
|
|
20
21
|
writeWord(instdata, instrumentStart);
|
|
21
|
-
instrumentStart += inst.instrumentZones.length;
|
|
22
|
-
inst.instrumentID = instrumentID;
|
|
23
|
-
instrumentID++;
|
|
22
|
+
instrumentStart += inst.instrumentZones.length + 1; // global
|
|
24
23
|
}
|
|
25
24
|
// write EOI
|
|
26
25
|
writeStringAsBytes(instdata, "EOI", 20);
|
|
@@ -2,6 +2,8 @@ import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
|
2
2
|
import { writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
3
|
import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
4
4
|
|
|
5
|
+
const BAG_SIZE = 4;
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* @this {BasicSoundBank}
|
|
7
9
|
* @returns {IndexedByteArray}
|
|
@@ -9,30 +11,31 @@ import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
|
9
11
|
export function getPBAG()
|
|
10
12
|
{
|
|
11
13
|
// write all pbag with their start indexes as they were changed in getPGEN() and getPMOD()
|
|
12
|
-
const pbagsize = this.presets.reduce((sum, i) =>
|
|
14
|
+
const pbagsize = this.presets.reduce((sum, i) =>
|
|
15
|
+
// +1 because global zone
|
|
16
|
+
(i.presetZones.length + 1) * BAG_SIZE + sum, BAG_SIZE);
|
|
13
17
|
const pbagdata = new IndexedByteArray(pbagsize);
|
|
14
|
-
let zoneID = 0;
|
|
15
18
|
let generatorIndex = 0;
|
|
16
19
|
let modulatorIndex = 0;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param z {BasicZone}
|
|
23
|
+
*/
|
|
24
|
+
const writeZone = z =>
|
|
25
|
+
{
|
|
26
|
+
writeWord(pbagdata, generatorIndex);
|
|
27
|
+
writeWord(pbagdata, modulatorIndex);
|
|
28
|
+
generatorIndex += z.generators.length;
|
|
29
|
+
modulatorIndex += z.modulators.length;
|
|
30
|
+
};
|
|
31
|
+
|
|
17
32
|
for (const preset of this.presets)
|
|
18
33
|
{
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
// only take the first one
|
|
23
|
-
if (global?.[0])
|
|
24
|
-
{
|
|
25
|
-
zones.unshift(global?.[0]);
|
|
26
|
-
}
|
|
27
|
-
preset.presetZoneStartIndex = zoneID;
|
|
28
|
-
for (const pbag of zones)
|
|
34
|
+
// global
|
|
35
|
+
writeZone(preset.globalZone);
|
|
36
|
+
for (const pbag of preset.presetZones)
|
|
29
37
|
{
|
|
30
|
-
pbag
|
|
31
|
-
writeWord(pbagdata, generatorIndex);
|
|
32
|
-
writeWord(pbagdata, modulatorIndex);
|
|
33
|
-
generatorIndex += pbag.generators.length;
|
|
34
|
-
modulatorIndex += pbag.modulators.length;
|
|
35
|
-
zoneID++;
|
|
38
|
+
writeZone(pbag);
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
41
|
// write the terminal PBAG
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
1
|
+
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
2
2
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
3
3
|
import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { GEN_BYTE_SIZE, Generator } from "../generator.js";
|
|
6
|
+
import { generatorTypes } from "../generator_types.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @this {BasicSoundBank}
|
|
@@ -12,9 +13,10 @@ export function getPGEN()
|
|
|
12
13
|
{
|
|
13
14
|
// almost identical to igen, except the correct instrument instead of sample gen
|
|
14
15
|
// goes through all preset zones and writes generators sequentially (add 4 for terminal)
|
|
15
|
-
let pgensize =
|
|
16
|
+
let pgensize = GEN_BYTE_SIZE;
|
|
16
17
|
for (const preset of this.presets)
|
|
17
18
|
{
|
|
19
|
+
pgensize += preset.globalZone.generators.length * GEN_BYTE_SIZE;
|
|
18
20
|
pgensize += preset.presetZones.reduce((size, z) =>
|
|
19
21
|
{
|
|
20
22
|
// clear instrument and range generators before determining the size
|
|
@@ -40,39 +42,40 @@ export function getPGEN()
|
|
|
40
42
|
false
|
|
41
43
|
));
|
|
42
44
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
));
|
|
51
|
-
}
|
|
52
|
-
return z.generators.length * 4 + size;
|
|
45
|
+
// write the instrument id
|
|
46
|
+
z.generators.push(new Generator(
|
|
47
|
+
generatorTypes.instrument,
|
|
48
|
+
this.instruments.indexOf(z.instrument),
|
|
49
|
+
false
|
|
50
|
+
));
|
|
51
|
+
return z.generators.length * GEN_BYTE_SIZE + size;
|
|
53
52
|
}, 0);
|
|
54
53
|
}
|
|
55
54
|
const pgendata = new IndexedByteArray(pgensize);
|
|
56
|
-
|
|
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
|
+
};
|
|
57
68
|
for (const preset of this.presets)
|
|
58
69
|
{
|
|
59
|
-
|
|
70
|
+
// global zone
|
|
71
|
+
writeZone(preset.globalZone);
|
|
72
|
+
for (const zone of preset.presetZones)
|
|
60
73
|
{
|
|
61
|
-
|
|
62
|
-
presetZone.generatorZoneStartIndex = pgenIndex;
|
|
63
|
-
// write generators
|
|
64
|
-
for (const gen of presetZone.generators)
|
|
65
|
-
{
|
|
66
|
-
// name is deceptive, it works on negatives
|
|
67
|
-
writeWord(pgendata, gen.generatorType);
|
|
68
|
-
writeWord(pgendata, gen.generatorValue);
|
|
69
|
-
}
|
|
70
|
-
pgenIndex += presetZone.generators.length;
|
|
74
|
+
writeZone(zone);
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
// terminal generator, is zero
|
|
74
|
-
|
|
75
|
-
writeWord(pgendata, 0);
|
|
78
|
+
writeDword(pgendata, 0);
|
|
76
79
|
|
|
77
80
|
return writeRIFFChunk(new RiffChunk(
|
|
78
81
|
"pgen",
|
|
@@ -3,13 +3,15 @@ import { writeStringAsBytes } from "../../../utils/byte_functions/string.js";
|
|
|
3
3
|
import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
4
4
|
import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
5
5
|
|
|
6
|
+
const PHDR_SIZE = 38;
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* @this {BasicSoundBank}
|
|
8
10
|
* @returns {IndexedByteArray}
|
|
9
11
|
*/
|
|
10
12
|
export function getPHDR()
|
|
11
13
|
{
|
|
12
|
-
const phdrsize = this.presets.length *
|
|
14
|
+
const phdrsize = this.presets.length * PHDR_SIZE + PHDR_SIZE;
|
|
13
15
|
const phdrdata = new IndexedByteArray(phdrsize);
|
|
14
16
|
// the preset start is adjusted in pbag, this is only for the terminal preset index
|
|
15
17
|
let presetStart = 0;
|
|
@@ -23,7 +25,7 @@ export function getPHDR()
|
|
|
23
25
|
writeDword(phdrdata, preset.library);
|
|
24
26
|
writeDword(phdrdata, preset.genre);
|
|
25
27
|
writeDword(phdrdata, preset.morphology);
|
|
26
|
-
presetStart += preset.presetZones.length;
|
|
28
|
+
presetStart += preset.presetZones.length + 1; // global
|
|
27
29
|
}
|
|
28
30
|
// write EOP
|
|
29
31
|
writeStringAsBytes(phdrdata, "EOP", 20);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IndexedByteArray } from "../../../utils/indexed_array.js";
|
|
2
2
|
import { writeLittleEndian, writeWord } from "../../../utils/byte_functions/little_endian.js";
|
|
3
3
|
import { RiffChunk, writeRIFFChunk } from "../riff_chunk.js";
|
|
4
|
+
import { MOD_BYTE_SIZE } from "../modulator.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @this {BasicSoundBank}
|
|
@@ -10,28 +11,37 @@ export function getPMOD()
|
|
|
10
11
|
{
|
|
11
12
|
// very similar to imod,
|
|
12
13
|
// go through all presets -> zones and write modulators sequentially
|
|
13
|
-
let pmodsize =
|
|
14
|
+
let pmodsize = MOD_BYTE_SIZE;
|
|
14
15
|
for (const preset of this.presets)
|
|
15
16
|
{
|
|
16
|
-
pmodsize += preset.
|
|
17
|
+
pmodsize += preset.globalZone.modulators.length * MOD_BYTE_SIZE;
|
|
18
|
+
pmodsize += preset.presetZones.reduce((sum, z) => z.modulators.length * MOD_BYTE_SIZE + sum, 0);
|
|
17
19
|
}
|
|
18
20
|
const pmoddata = new IndexedByteArray(pmodsize);
|
|
19
|
-
|
|
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
|
+
|
|
20
38
|
for (const preset of this.presets)
|
|
21
39
|
{
|
|
22
|
-
|
|
40
|
+
// global
|
|
41
|
+
writeZone(preset.globalZone);
|
|
42
|
+
for (const zone of preset.presetZones)
|
|
23
43
|
{
|
|
24
|
-
|
|
25
|
-
pbag.modulatorZoneStartIndex = pmodIndex;
|
|
26
|
-
for (const mod of pbag.modulators)
|
|
27
|
-
{
|
|
28
|
-
writeWord(pmoddata, mod.getSourceEnum());
|
|
29
|
-
writeWord(pmoddata, mod.modulatorDestination);
|
|
30
|
-
writeWord(pmoddata, mod.transformAmount);
|
|
31
|
-
writeWord(pmoddata, mod.getSecSrcEnum());
|
|
32
|
-
writeWord(pmoddata, mod.transformType);
|
|
33
|
-
pmodIndex++;
|
|
34
|
-
}
|
|
44
|
+
writeZone(zone);
|
|
35
45
|
}
|
|
36
46
|
}
|
|
37
47
|
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { DLSSources } from "./dls_sources.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
DecodedModulator,
|
|
4
|
+
getModSourceEnum,
|
|
5
|
+
Modulator,
|
|
6
|
+
modulatorCurveTypes,
|
|
7
|
+
modulatorSources
|
|
8
|
+
} from "../basic_soundfont/modulator.js";
|
|
3
9
|
import { midiControllers } from "../../midi/midi_message.js";
|
|
4
10
|
import { DLSDestinations } from "./dls_destinations.js";
|
|
5
11
|
|
|
6
|
-
import { generatorTypes } from "../basic_soundfont/generator.js";
|
|
7
12
|
import { consoleColors } from "../../utils/other.js";
|
|
8
13
|
import { SpessaSynthWarn } from "../../utils/loggin.js";
|
|
14
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* @param source {number}
|
|
@@ -385,7 +391,7 @@ export function getSF2ModulatorFromArticulator(
|
|
|
385
391
|
}
|
|
386
392
|
|
|
387
393
|
// return the modulator!
|
|
388
|
-
return new
|
|
394
|
+
return new DecodedModulator(
|
|
389
395
|
sourceEnumFinal,
|
|
390
396
|
secSourceEnumFinal,
|
|
391
397
|
destinationGenerator,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BasicPreset } from "../basic_soundfont/basic_preset.js";
|
|
2
|
-
import { BasicPresetZone } from "../basic_soundfont/
|
|
2
|
+
import { BasicPresetZone } from "../basic_soundfont/basic_preset_zone.js";
|
|
3
3
|
import { BasicInstrument } from "../basic_soundfont/basic_instrument.js";
|
|
4
4
|
|
|
5
5
|
export class DLSPreset extends BasicPreset
|
|
@@ -34,10 +34,9 @@ export class DLSPreset extends BasicPreset
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
this.DLSInstrument = new BasicInstrument();
|
|
37
|
-
this.DLSInstrument.addUseCount();
|
|
38
37
|
|
|
39
38
|
const zone = new BasicPresetZone();
|
|
40
|
-
zone.
|
|
39
|
+
zone.setInstrument(this.DLSInstrument);
|
|
41
40
|
|
|
42
41
|
this.presetZones = [zone];
|
|
43
42
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BasicSoundBank } from "../basic_soundfont/
|
|
1
|
+
import { BasicSoundBank } from "../basic_soundfont/basic_soundbank.js";
|
|
2
2
|
import { IndexedByteArray } from "../../utils/indexed_array.js";
|
|
3
3
|
import { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo } from "../../utils/loggin.js";
|
|
4
4
|
import { consoleColors } from "../../utils/other.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { DecodedModulator } from "../basic_soundfont/modulator.js";
|
|
2
|
+
|
|
3
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* @enum {number}
|
|
@@ -29,7 +30,7 @@ export const DLSSources = {
|
|
|
29
30
|
coarseTune: 0x102
|
|
30
31
|
};
|
|
31
32
|
|
|
32
|
-
export const DEFAULT_DLS_REVERB = new
|
|
33
|
+
export const DEFAULT_DLS_REVERB = new DecodedModulator(
|
|
33
34
|
0x00DB,
|
|
34
35
|
0x0,
|
|
35
36
|
generatorTypes.reverbEffectsSend,
|
|
@@ -37,7 +38,7 @@ export const DEFAULT_DLS_REVERB = new Modulator(
|
|
|
37
38
|
0
|
|
38
39
|
);
|
|
39
40
|
|
|
40
|
-
export const DEFAULT_DLS_CHORUS = new
|
|
41
|
+
export const DEFAULT_DLS_CHORUS = new DecodedModulator(
|
|
41
42
|
0x00DD,
|
|
42
43
|
0x0,
|
|
43
44
|
generatorTypes.chorusEffectsSend,
|
|
@@ -45,7 +46,7 @@ export const DEFAULT_DLS_CHORUS = new Modulator(
|
|
|
45
46
|
0
|
|
46
47
|
);
|
|
47
48
|
|
|
48
|
-
export const DLS_1_NO_VIBRATO_MOD = new
|
|
49
|
+
export const DLS_1_NO_VIBRATO_MOD = new DecodedModulator(
|
|
49
50
|
0x0081,
|
|
50
51
|
0x0,
|
|
51
52
|
generatorTypes.vibLfoToPitch,
|
|
@@ -53,7 +54,7 @@ export const DLS_1_NO_VIBRATO_MOD = new Modulator(
|
|
|
53
54
|
0
|
|
54
55
|
);
|
|
55
56
|
|
|
56
|
-
export const DLS_1_NO_VIBRATO_PRESSURE = new
|
|
57
|
+
export const DLS_1_NO_VIBRATO_PRESSURE = new DecodedModulator(
|
|
57
58
|
0x000D,
|
|
58
59
|
0x0,
|
|
59
60
|
generatorTypes.vibLfoToPitch,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Generator } from "../basic_soundfont/generator.js";
|
|
2
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
3
|
+
import { BasicInstrumentZone } from "../basic_soundfont/basic_instrument_zone.js";
|
|
3
4
|
|
|
4
5
|
export class DLSZone extends BasicInstrumentZone
|
|
5
6
|
{
|
|
@@ -12,7 +13,6 @@ export class DLSZone extends BasicInstrumentZone
|
|
|
12
13
|
super();
|
|
13
14
|
this.keyRange = keyRange;
|
|
14
15
|
this.velRange = velRange;
|
|
15
|
-
this.isGlobal = true;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -89,7 +89,6 @@ export class DLSZone extends BasicInstrumentZone
|
|
|
89
89
|
}
|
|
90
90
|
// add sample ID
|
|
91
91
|
this.generators.push(new Generator(generatorTypes.sampleID, sampleID));
|
|
92
|
-
this.sample
|
|
93
|
-
sample.useCount++;
|
|
92
|
+
this.setSample(sample);
|
|
94
93
|
}
|
|
95
94
|
}
|
|
@@ -4,8 +4,9 @@ import { DLS_1_NO_VIBRATO_MOD, DLS_1_NO_VIBRATO_PRESSURE, DLSSources } from "./d
|
|
|
4
4
|
import { getSF2ModulatorFromArticulator } from "./articulator_converter.js";
|
|
5
5
|
import { SpessaSynthInfo, SpessaSynthWarn } from "../../utils/loggin.js";
|
|
6
6
|
import { consoleColors } from "../../utils/other.js";
|
|
7
|
-
import { Generator
|
|
7
|
+
import { Generator } from "../basic_soundfont/generator.js";
|
|
8
8
|
import { Modulator } from "../basic_soundfont/modulator.js";
|
|
9
|
+
import { generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -3,11 +3,10 @@ import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
|
|
|
3
3
|
import { DLSPreset } from "./dls_preset.js";
|
|
4
4
|
import { findRIFFListType, readRIFFChunk } from "../basic_soundfont/riff_chunk.js";
|
|
5
5
|
import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd } from "../../utils/loggin.js";
|
|
6
|
-
import { BasicInstrumentZone } from "../basic_soundfont/basic_zones.js";
|
|
7
6
|
import { consoleColors } from "../../utils/other.js";
|
|
8
|
-
import { generatorLimits, generatorTypes } from "../basic_soundfont/generator.js";
|
|
9
7
|
import { Modulator } from "../basic_soundfont/modulator.js";
|
|
10
8
|
import { DEFAULT_DLS_CHORUS, DEFAULT_DLS_REVERB } from "./dls_sources.js";
|
|
9
|
+
import { generatorLimits, generatorTypes } from "../basic_soundfont/generator_types.js";
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* @this {DLSSoundFont}
|
|
@@ -70,8 +69,7 @@ export function readDLSInstrument(chunk)
|
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
// global articulation: essentially global zone
|
|
73
|
-
const globalZone =
|
|
74
|
-
globalZone.isGlobal = true;
|
|
72
|
+
const globalZone = preset.DLSInstrument.globalZone;
|
|
75
73
|
|
|
76
74
|
// read articulators
|
|
77
75
|
const globalLart = findRIFFListType(chunks, "lart");
|
|
@@ -93,7 +91,6 @@ export function readDLSInstrument(chunk)
|
|
|
93
91
|
{
|
|
94
92
|
globalZone.modulators.push(Modulator.copy(DEFAULT_DLS_CHORUS));
|
|
95
93
|
}
|
|
96
|
-
preset.DLSInstrument.instrumentZones.push(globalZone);
|
|
97
94
|
|
|
98
95
|
// read regions
|
|
99
96
|
for (let i = 0; i < regions; i++)
|
|
@@ -111,7 +108,7 @@ export function readDLSInstrument(chunk)
|
|
|
111
108
|
const zone = this.readRegion(chunk);
|
|
112
109
|
if (zone)
|
|
113
110
|
{
|
|
114
|
-
preset.DLSInstrument.
|
|
111
|
+
preset.DLSInstrument.addZone(zone);
|
|
115
112
|
}
|
|
116
113
|
}
|
|
117
114
|
|
|
@@ -4,7 +4,7 @@ import { readArticulation } from "./read_articulation.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* @param lartChunk {RiffChunk|undefined}
|
|
6
6
|
* @param lar2Chunk {RiffChunk|undefined}
|
|
7
|
-
* @param zone {
|
|
7
|
+
* @param zone {BasicZone}
|
|
8
8
|
* @this {DLSSoundFont}
|
|
9
9
|
*/
|
|
10
10
|
export function readLart(lartChunk, lar2Chunk, zone)
|