spessasynth_core 3.26.16 → 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.
Files changed (61) hide show
  1. package/index.js +5 -3
  2. package/package.json +1 -1
  3. package/src/externals/README.md +6 -0
  4. package/src/sequencer/README.md +5 -1
  5. package/src/soundfont/README.md +6 -8
  6. package/src/soundfont/basic_soundfont/basic_global_zone.js +16 -0
  7. package/src/soundfont/basic_soundfont/basic_instrument.js +26 -22
  8. package/src/soundfont/basic_soundfont/basic_instrument_zone.js +35 -0
  9. package/src/soundfont/basic_soundfont/basic_preset.js +45 -42
  10. package/src/soundfont/basic_soundfont/basic_preset_zone.js +30 -0
  11. package/src/soundfont/basic_soundfont/{basic_soundfont.js → basic_soundbank.js} +22 -44
  12. package/src/soundfont/basic_soundfont/basic_zone.js +1 -5
  13. package/src/soundfont/basic_soundfont/generator.js +2 -152
  14. package/src/soundfont/basic_soundfont/generator_types.js +151 -0
  15. package/src/soundfont/basic_soundfont/modulator.js +251 -79
  16. package/src/soundfont/basic_soundfont/write_dls/art2.js +3 -2
  17. package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +25 -42
  18. package/src/soundfont/basic_soundfont/write_dls/ins.js +11 -27
  19. package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +2 -2
  20. package/src/soundfont/basic_soundfont/write_dls/rgn2.js +2 -2
  21. package/src/soundfont/basic_soundfont/write_sf2/ibag.js +21 -10
  22. package/src/soundfont/basic_soundfont/write_sf2/igen.js +31 -27
  23. package/src/soundfont/basic_soundfont/write_sf2/imod.js +24 -14
  24. package/src/soundfont/basic_soundfont/write_sf2/inst.js +4 -5
  25. package/src/soundfont/basic_soundfont/write_sf2/pbag.js +20 -9
  26. package/src/soundfont/basic_soundfont/write_sf2/pgen.js +32 -29
  27. package/src/soundfont/basic_soundfont/write_sf2/phdr.js +4 -2
  28. package/src/soundfont/basic_soundfont/write_sf2/pmod.js +25 -15
  29. package/src/soundfont/basic_soundfont/write_sf2/write.js +2 -2
  30. package/src/soundfont/dls/articulator_converter.js +9 -3
  31. package/src/soundfont/dls/dls_preset.js +2 -3
  32. package/src/soundfont/dls/dls_soundfont.js +1 -1
  33. package/src/soundfont/dls/dls_sources.js +7 -6
  34. package/src/soundfont/dls/dls_zone.js +4 -5
  35. package/src/soundfont/dls/read_articulation.js +2 -1
  36. package/src/soundfont/dls/read_instrument.js +3 -6
  37. package/src/soundfont/dls/read_lart.js +1 -1
  38. package/src/soundfont/dls/read_region.js +2 -1
  39. package/src/soundfont/read_sf2/instruments.js +10 -1
  40. package/src/soundfont/read_sf2/modulators.js +10 -23
  41. package/src/soundfont/read_sf2/presets.js +10 -1
  42. package/src/soundfont/read_sf2/soundfont.js +1 -2
  43. package/src/soundfont/read_sf2/zones.js +30 -14
  44. package/src/synthetizer/README.md +3 -3
  45. package/src/synthetizer/audio_engine/README.md +1 -1
  46. package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +1 -1
  47. package/src/synthetizer/audio_engine/engine_components/dynamic_modulator_system.js +11 -3
  48. package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +1 -1
  49. package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +1 -1
  50. package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +1 -1
  51. package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +1 -1
  52. package/src/synthetizer/audio_engine/engine_components/voice.js +7 -10
  53. package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +2 -1
  54. package/src/synthetizer/audio_engine/engine_methods/data_entry/awe32.js +1 -1
  55. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +7 -0
  56. package/src/synthetizer/audio_engine/engine_methods/note_on.js +1 -1
  57. package/src/synthetizer/audio_engine/engine_methods/render_voice.js +1 -1
  58. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +1 -1
  59. package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +2 -1
  60. package/src/utils/README.md +5 -2
  61. package/src/soundfont/basic_soundfont/basic_zones.js +0 -43
@@ -22,20 +22,12 @@ export function writeIns(preset)
22
22
  consoleColors.info
23
23
  );
24
24
  // combine preset and instrument zones into a single instrument zone (region) list
25
- const combined = combineZones(preset);
25
+ const { global, zones } = combineZones(preset);
26
26
 
27
- const nonGlobalRegionsCount = combined.reduce((sum, z) =>
28
- {
29
- if (!z.isGlobal)
30
- {
31
- return sum + 1;
32
- }
33
- return sum;
34
- }, 0);
35
27
 
36
28
  // insh: instrument header
37
29
  const inshData = new IndexedByteArray(12);
38
- writeDword(inshData, nonGlobalRegionsCount); // cRegions
30
+ writeDword(inshData, zones.length); // cRegions
39
31
  // bank MSB is in bits 8-14
40
32
  let ulBank = (preset.bank & 127) << 8;
41
33
  // bit 32 means drums
@@ -52,26 +44,18 @@ export function writeIns(preset)
52
44
  );
53
45
 
54
46
  // write global zone
55
- let lar2 = new IndexedByteArray(0);
56
- const globalZone = combined.find(z => z.isGlobal === true);
57
- if (globalZone)
58
- {
59
- const art2 = writeArticulator(globalZone);
60
- lar2 = writeRIFFOddSize(
61
- "lar2",
62
- art2,
63
- false,
64
- true
65
- );
66
- }
47
+ const art2 = writeArticulator(global);
48
+ let lar2 = writeRIFFOddSize(
49
+ "lar2",
50
+ art2,
51
+ false,
52
+ true
53
+ );
67
54
 
68
55
  // write the region list
69
- const lrgnData = combineArrays(combined.reduce((arrs, z) =>
56
+ const lrgnData = combineArrays(zones.reduce((arrs, z) =>
70
57
  {
71
- if (!z.isGlobal)
72
- {
73
- arrs.push(writeDLSRegion.apply(this, [z, globalZone]));
74
- }
58
+ arrs.push(writeDLSRegion.apply(this, [z, global]));
75
59
  return arrs;
76
60
  }, []));
77
61
  const lrgn = writeRIFFOddSize(
@@ -1,14 +1,14 @@
1
1
  import { midiControllers } from "../../../midi/midi_message.js";
2
2
  import { DLSSources } from "../../dls/dls_sources.js";
3
3
  import { modulatorCurveTypes, modulatorSources } from "../modulator.js";
4
- import { generatorTypes } from "../generator.js";
5
4
  import { DLSDestinations } from "../../dls/dls_destinations.js";
6
5
  import { Articulator } from "./articulator.js";
7
6
  import { SpessaSynthWarn } from "../../../utils/loggin.js";
7
+ import { generatorTypes } from "../generator_types.js";
8
8
 
9
9
 
10
10
  /**
11
- * @param cc {boolean}
11
+ * @param cc {0|1}
12
12
  * @param index {number}
13
13
  * @returns {number|undefined}
14
14
  */
@@ -1,13 +1,13 @@
1
1
  import { combineArrays, IndexedByteArray } from "../../../utils/indexed_array.js";
2
2
  import { writeDword, writeWord } from "../../../utils/byte_functions/little_endian.js";
3
- import { generatorTypes } from "../generator.js";
4
3
  import { writeRIFFOddSize } from "../riff_chunk.js";
5
4
  import { writeWavesample } from "./wsmp.js";
6
5
  import { writeArticulator } from "./art2.js";
6
+ import { generatorTypes } from "../generator_types.js";
7
7
 
8
8
  /**
9
9
  * @param zone {BasicInstrumentZone}
10
- * @param globalZone {BasicInstrumentZone}
10
+ * @param globalZone {BasicGlobalZone}
11
11
  * @this {BasicSoundBank}
12
12
  * @returns {IndexedByteArray}
13
13
  */
@@ -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,28 +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((sum, i) => i.instrumentZones.length * 4 + sum, 4);
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
- inst.instrumentZoneIndex = zoneID;
36
+ writeZone(inst.globalZone);
20
37
  for (const ibag of inst.instrumentZones)
21
38
  {
22
- ibag.zoneID = zoneID;
23
- writeWord(ibagdata, generatorIndex);
24
- writeWord(ibagdata, modulatorIndex);
25
- generatorIndex += ibag.generators.length;
26
- modulatorIndex += ibag.modulators.length;
27
- zoneID++;
39
+ writeZone(ibag);
28
40
  }
29
41
  }
30
42
  // write the terminal IBAG
31
43
  writeWord(ibagdata, generatorIndex);
32
44
  writeWord(ibagdata, modulatorIndex);
33
-
34
45
  return writeRIFFChunk(new RiffChunk(
35
46
  "ibag",
36
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 { Generator, generatorTypes } from "../generator.js";
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 = 4;
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,8 +24,8 @@ 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 instrument is last
27
- if (z.velRange.max !== 127 || z.velRange.min !== 0)
27
+ // unshift vel then key (to make key first) and the sample is last
28
+ if (z.hasVelRange)
28
29
  {
29
30
  z.generators.unshift(new Generator(
30
31
  generatorTypes.velRange,
@@ -32,7 +33,7 @@ export function getIGEN()
32
33
  false
33
34
  ));
34
35
  }
35
- if (z.keyRange.max !== 127 || z.keyRange.min !== 0)
36
+ if (z.hasKeyRange)
36
37
  {
37
38
  z.generators.unshift(new Generator(
38
39
  generatorTypes.keyRange,
@@ -40,38 +41,41 @@ export function getIGEN()
40
41
  false
41
42
  ));
42
43
  }
43
- if (!z.isGlobal)
44
- {
45
- // write sample
46
- z.generators.push(new Generator(
47
- generatorTypes.sampleID,
48
- this.samples.indexOf(z.sample),
49
- false
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
- let igenIndex = 0;
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
- // set the start index here
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 = 10;
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
- let imodIndex = 0;
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
- for (const ibag of inst.instrumentZones)
40
+ // global
41
+ writeZone(inst.globalZone);
42
+ for (const instrumentZone of inst.instrumentZones)
23
43
  {
24
- // set the start index here
25
- ibag.modulatorZoneStartIndex = imodIndex;
26
- for (const mod of ibag.modulators)
27
- {
28
- writeWord(imoddata, mod.sourceEnum);
29
- writeWord(imoddata, mod.modulatorDestination);
30
- writeWord(imoddata, mod.transformAmount);
31
- writeWord(imoddata, mod.secondarySourceEnum);
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 * 22 + 22;
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,22 +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) => i.presetZones.length * 4 + sum, 4);
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
- preset.presetZoneStartIndex = zoneID;
34
+ // global
35
+ writeZone(preset.globalZone);
20
36
  for (const pbag of preset.presetZones)
21
37
  {
22
- pbag.zoneID = zoneID;
23
- writeWord(pbagdata, generatorIndex);
24
- writeWord(pbagdata, modulatorIndex);
25
- generatorIndex += pbag.generators.length;
26
- modulatorIndex += pbag.modulators.length;
27
- zoneID++;
38
+ writeZone(pbag);
28
39
  }
29
40
  }
30
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 { Generator, generatorTypes } from "../generator.js";
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 = 4;
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
@@ -24,7 +26,7 @@ export function getPGEN()
24
26
  g.generatorType !== generatorTypes.velRange
25
27
  );
26
28
  // unshift vel then key and instrument is last
27
- if (z.velRange.max !== 127 || z.velRange.min !== 0)
29
+ if (z.hasVelRange)
28
30
  {
29
31
  z.generators.unshift(new Generator(
30
32
  generatorTypes.velRange,
@@ -32,7 +34,7 @@ export function getPGEN()
32
34
  false
33
35
  ));
34
36
  }
35
- if (z.keyRange.max !== 127 || z.keyRange.min !== 0)
37
+ if (z.hasKeyRange)
36
38
  {
37
39
  z.generators.unshift(new Generator(
38
40
  generatorTypes.keyRange,
@@ -40,39 +42,40 @@ export function getPGEN()
40
42
  false
41
43
  ));
42
44
  }
43
- if (!z.isGlobal)
44
- {
45
- // write the instrument
46
- z.generators.push(new Generator(
47
- generatorTypes.instrument,
48
- this.instruments.indexOf(z.instrument),
49
- false
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
- let pgenIndex = 0;
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
- for (const presetZone of preset.presetZones)
70
+ // global zone
71
+ writeZone(preset.globalZone);
72
+ for (const zone of preset.presetZones)
60
73
  {
61
- // set the start index here
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
- writeWord(pgendata, 0);
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 * 38 + 38;
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 = 10;
14
+ let pmodsize = MOD_BYTE_SIZE;
14
15
  for (const preset of this.presets)
15
16
  {
16
- pmodsize += preset.presetZones.reduce((sum, z) => z.modulators.length * 10 + sum, 0);
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
- let pmodIndex = 0;
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
- for (const pbag of preset.presetZones)
40
+ // global
41
+ writeZone(preset.globalZone);
42
+ for (const zone of preset.presetZones)
23
43
  {
24
- // set the start index here
25
- pbag.modulatorZoneStartIndex = pmodIndex;
26
- for (const mod of pbag.modulators)
27
- {
28
- writeWord(pmoddata, mod.sourceEnum);
29
- writeWord(pmoddata, mod.modulatorDestination);
30
- writeWord(pmoddata, mod.transformAmount);
31
- writeWord(pmoddata, mod.secondarySourceEnum);
32
- writeWord(pmoddata, mod.transformType);
33
- pmodIndex++;
34
- }
44
+ writeZone(zone);
35
45
  }
36
46
  }
37
47
 
@@ -112,10 +112,10 @@ export function write(options = DEFAULT_WRITE_OPTIONS)
112
112
  const dmoddata = new IndexedByteArray(dmodsize);
113
113
  for (const mod of mods)
114
114
  {
115
- writeWord(dmoddata, mod.sourceEnum);
115
+ writeWord(dmoddata, mod.getSourceEnum());
116
116
  writeWord(dmoddata, mod.modulatorDestination);
117
117
  writeWord(dmoddata, mod.transformAmount);
118
- writeWord(dmoddata, mod.secondarySourceEnum);
118
+ writeWord(dmoddata, mod.getSecSrcEnum());
119
119
  writeWord(dmoddata, mod.transformType);
120
120
  }
121
121
 
@@ -1,11 +1,17 @@
1
1
  import { DLSSources } from "./dls_sources.js";
2
- import { getModSourceEnum, Modulator, modulatorCurveTypes, modulatorSources } from "../basic_soundfont/modulator.js";
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 Modulator(
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/basic_zones.js";
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.instrument = this.DLSInstrument;
39
+ zone.setInstrument(this.DLSInstrument);
41
40
 
42
41
  this.presetZones = [zone];
43
42
  }
@@ -1,4 +1,4 @@
1
- import { BasicSoundBank } from "../basic_soundfont/basic_soundfont.js";
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";