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
package/index.js CHANGED
@@ -18,12 +18,12 @@ import {
18
18
  import { SynthesizerSnapshot } from "./src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js";
19
19
  import { ChannelSnapshot } from "./src/synthetizer/audio_engine/snapshot/channel_snapshot.js";
20
20
 
21
- import { BasicSoundBank } from "./src/soundfont/basic_soundfont/basic_soundfont.js";
21
+ import { BasicSoundBank } from "./src/soundfont/basic_soundfont/basic_soundbank.js";
22
22
  import { BasicSample } from "./src/soundfont/basic_soundfont/basic_sample.js";
23
- import { BasicInstrumentZone, BasicPresetZone } from "./src/soundfont/basic_soundfont/basic_zones.js";
23
+ import { BasicPresetZone } from "./src/soundfont/basic_soundfont/basic_preset_zone.js";
24
24
  import { BasicInstrument } from "./src/soundfont/basic_soundfont/basic_instrument.js";
25
25
  import { BasicPreset } from "./src/soundfont/basic_soundfont/basic_preset.js";
26
- import { Generator, generatorTypes } from "./src/soundfont/basic_soundfont/generator.js";
26
+ import { Generator } from "./src/soundfont/basic_soundfont/generator.js";
27
27
  import { Modulator, modulatorCurveTypes, modulatorSources } from "./src/soundfont/basic_soundfont/modulator.js";
28
28
  import { loadSoundFont } from "./src/soundfont/load_soundfont.js";
29
29
 
@@ -51,6 +51,8 @@ import { consoleColors } from "./src/utils/other.js";
51
51
  import { inflateSync } from "./src/externals/fflate/fflate.min.js";
52
52
  import { DLSDestinations } from "./src/soundfont/dls/dls_destinations.js";
53
53
  import { DLSSources } from "./src/soundfont/dls/dls_sources.js";
54
+ import { generatorTypes } from "./src/soundfont/basic_soundfont/generator_types.js";
55
+ import { BasicInstrumentZone } from "./src/soundfont/basic_soundfont/basic_instrument_zone.js";
54
56
  // you shouldn't use these...
55
57
  const SpessaSynthCoreUtils = {
56
58
  consoleColors,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spessasynth_core",
3
- "version": "3.26.16",
3
+ "version": "3.26.18",
4
4
  "description": "MIDI and SoundFont2/DLS library with no compromises",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -0,0 +1,6 @@
1
+ ## This is the external dependencies' folder.
2
+
3
+ The code here contains third-party libraries used by SpessaSynth.
4
+
5
+ - `stbvorbis_sync` - Vorbis audio decoder for SF3 soundfonts
6
+ - `fflate` - Used for decompressing XMF files. It is also used to compress the reverb buffer in spessasynth_lib
@@ -2,4 +2,8 @@
2
2
 
3
3
  The code here is responsible for playing back the parsed MIDI sequence with the synthesizer.
4
4
 
5
- - `sequencer_engine` - the core sequencer engine
5
+ - `sequencer_engine.js` - the core sequencer engine
6
+ - `play.js` - handles playback control and timing
7
+ - `song_control.js` - manages song state and control
8
+ - `process_event.js` - processes MIDI events during playback
9
+ - `process_tick.js` - processes a single MIDI tick (think of it like a rendering quantum of the sequencer)
@@ -1,13 +1,11 @@
1
- ## This is the SoundFont2 parsing library.
1
+ ## This is the SoundFont and DLS parsing library.
2
2
 
3
- The code here is responsible for parsing the SoundFont2 file and
3
+ The code here is responsible for parsing the SoundFont2/DLS file and
4
4
  providing an easy way to get the data out.
5
- Default modulators are also stored here (in `modulators.js`)
6
5
 
7
- `basic_soundfont` folder contains the classes that represent the soundfont file.
6
+ - `basic_soundfont` folder contains the classes that represent a sound bank file.
7
+ It also contains the code for writing the files.
8
8
 
9
- `read_sf2` folder contains the code for reading an `.sf2` file.
9
+ - `read_sf2` folder contains the code for reading a `.sf2` file.
10
10
 
11
- `write` folder contains the code for writing out an `.sf2` file.
12
-
13
- `dls` folder contains the code for reading a `.dls` file (and converting in into a soundfont representation).
11
+ - `dls` folder contains the code for reading a `.dls` file (and converting in into a soundfont representation).
@@ -0,0 +1,16 @@
1
+ import { BasicZone } from "./basic_zone.js";
2
+
3
+ export class BasicGlobalZone extends BasicZone
4
+ {
5
+
6
+ /**
7
+ * @param zone {BasicZone}
8
+ */
9
+ copyFrom(zone)
10
+ {
11
+ this.keyRange = { ...zone.keyRange };
12
+ this.velRange = { ...zone.velRange };
13
+ this.generators = [...zone.generators];
14
+ this.modulators = [...zone.modulators];
15
+ }
16
+ }
@@ -1,3 +1,5 @@
1
+ import { BasicGlobalZone } from "./basic_global_zone.js";
2
+
1
3
  export class BasicInstrument
2
4
  {
3
5
  /**
@@ -9,9 +11,16 @@ export class BasicInstrument
9
11
  /**
10
12
  * The instrument's zones
11
13
  * @type {BasicInstrumentZone[]}
14
+ * @readonly
12
15
  */
13
16
  instrumentZones = [];
14
17
 
18
+ /**
19
+ * Instrument's global zone
20
+ * @type {BasicGlobalZone}
21
+ */
22
+ globalZone = new BasicGlobalZone();
23
+
15
24
  /**
16
25
  * Instrument's use count, used for trimming
17
26
  * @type {number}
@@ -27,6 +36,15 @@ export class BasicInstrument
27
36
  return this._useCount;
28
37
  }
29
38
 
39
+ /**
40
+ * @param zone {BasicInstrumentZone}
41
+ */
42
+ addZone(zone)
43
+ {
44
+ zone.useCount++;
45
+ this.instrumentZones.push(zone);
46
+ }
47
+
30
48
  addUseCount()
31
49
  {
32
50
  this._useCount++;
@@ -36,16 +54,10 @@ export class BasicInstrument
36
54
  removeUseCount()
37
55
  {
38
56
  this._useCount--;
39
- for (let i = 0; i < this.instrumentZones.length; i++)
40
- {
41
- if (this.safeDeleteZone(i))
42
- {
43
- i--;
44
- }
45
- }
57
+ this.instrumentZones.forEach(z => z.useCount--);
46
58
  }
47
59
 
48
- deleteInstrument()
60
+ deleteZones()
49
61
  {
50
62
  this.instrumentZones.forEach(z => z.deleteZone());
51
63
  this.instrumentZones.length = 0;
@@ -53,25 +65,17 @@ export class BasicInstrument
53
65
 
54
66
  /**
55
67
  * @param index {number}
56
- * @returns {boolean} is the zone has been deleted
68
+ * @returns {boolean} if deleted
57
69
  */
58
- safeDeleteZone(index)
70
+ deleteZone(index)
59
71
  {
60
- this.instrumentZones[index].useCount--;
61
- if (this.instrumentZones[index].useCount < 1)
72
+ const zone = this.instrumentZones[index];
73
+ if (zone.useCount < 1)
62
74
  {
63
- this.deleteZone(index);
75
+ zone.deleteZone();
76
+ this.instrumentZones.splice(index, 1);
64
77
  return true;
65
78
  }
66
79
  return false;
67
80
  }
68
-
69
- /**
70
- * @param index {number}
71
- */
72
- deleteZone(index)
73
- {
74
- this.instrumentZones[index].deleteZone();
75
- this.instrumentZones.splice(index, 1);
76
- }
77
81
  }
@@ -0,0 +1,35 @@
1
+ import { BasicZone } from "./basic_zone.js";
2
+
3
+ export class BasicInstrumentZone extends BasicZone
4
+ {
5
+ /**
6
+ * Zone's sample.
7
+ * @type {BasicSample}
8
+ */
9
+ sample;
10
+
11
+ /**
12
+ * For tracking on the individual zone level, since multiple presets can refer to the same instrument
13
+ * @type {number}
14
+ */
15
+ useCount = 0;
16
+
17
+ /**
18
+ * @param sample {BasicSample}
19
+ */
20
+ setSample(sample)
21
+ {
22
+ this.sample = sample;
23
+ this.sample.useCount++;
24
+ }
25
+
26
+ deleteZone()
27
+ {
28
+ this.sample.useCount--;
29
+ }
30
+
31
+ hasSample()
32
+ {
33
+ return !!this.sample;
34
+ }
35
+ }
@@ -4,13 +4,13 @@
4
4
  * presetGenerators: Generator[],
5
5
  * modulators: Modulator[],
6
6
  * sample: BasicSample,
7
- * sampleID: number,
8
7
  * }} SampleAndGenerators
9
8
  */
10
- import { generatorTypes } from "./generator.js";
11
9
  import { Modulator } from "./modulator.js";
12
10
  import { isXGDrums } from "../../utils/xg_hacks.js";
13
11
 
12
+ import { BasicGlobalZone } from "./basic_global_zone.js";
13
+
14
14
  export class BasicPreset
15
15
  {
16
16
  /**
@@ -44,6 +44,12 @@ export class BasicPreset
44
44
  */
45
45
  presetZones = [];
46
46
 
47
+ /**
48
+ * Preset's global zone
49
+ * @type {BasicGlobalZone}
50
+ */
51
+ globalZone = new BasicGlobalZone();
52
+
47
53
  /**
48
54
  * unused metadata
49
55
  * @type {number}
@@ -171,62 +177,60 @@ export class BasicPreset
171
177
  * global zone is always first, so it or nothing
172
178
  * @type {Generator[]}
173
179
  */
174
- let globalPresetGenerators = this.presetZones[0].isGlobal ? [...this.presetZones[0].generators] : [];
180
+ let globalPresetGenerators = [...this.globalZone.generators];
175
181
 
176
182
  /**
177
183
  * @type {Modulator[]}
178
184
  */
179
- let globalPresetModulators = this.presetZones[0].isGlobal ? [...this.presetZones[0].modulators] : [];
180
- const globalKeyRange = this.presetZones[0].isGlobal ? this.presetZones[0].keyRange : { min: 0, max: 127 };
181
- const globalVelRange = this.presetZones[0].isGlobal ? this.presetZones[0].velRange : { min: 0, max: 127 };
185
+ let globalPresetModulators = [...this.globalZone.modulators];
186
+ const globalKeyRange = this.globalZone.keyRange;
187
+ const globalVelRange = this.globalZone.velRange;
182
188
 
183
189
  // find the preset zones in range
184
190
  let presetZonesInRange = this.presetZones.filter(currentZone =>
185
- (
186
- isInRange(
187
- currentZone.hasKeyRange ? currentZone.keyRange : globalKeyRange,
188
- midiNote
189
- )
190
- &&
191
- isInRange(
192
- currentZone.hasVelRange ? currentZone.velRange : globalVelRange,
193
- velocity
194
- )
195
- ) && !currentZone.isGlobal);
191
+ isInRange(
192
+ currentZone.hasKeyRange ? currentZone.keyRange : globalKeyRange,
193
+ midiNote
194
+ )
195
+ &&
196
+ isInRange(
197
+ currentZone.hasVelRange ? currentZone.velRange : globalVelRange,
198
+ velocity
199
+ )
200
+ );
196
201
 
197
- presetZonesInRange.forEach(zone =>
202
+ presetZonesInRange.forEach(presetZone =>
198
203
  {
204
+ const instrument = presetZone.instrument;
199
205
  // the global zone is already taken into account earlier
200
- if (zone.instrument.instrumentZones.length < 1)
206
+ if (instrument.instrumentZones.length < 1)
201
207
  {
202
208
  return;
203
209
  }
204
- let presetGenerators = zone.generators;
205
- let presetModulators = zone.modulators;
206
- const firstZone = zone.instrument.instrumentZones[0];
210
+ let presetGenerators = presetZone.generators;
211
+ let presetModulators = presetZone.modulators;
207
212
  /**
208
213
  * global zone is always first, so it or nothing
209
214
  * @type {Generator[]}
210
215
  */
211
- let globalInstrumentGenerators = firstZone.isGlobal ? [...firstZone.generators] : [];
212
- let globalInstrumentModulators = firstZone.isGlobal ? [...firstZone.modulators] : [];
213
- const globalKeyRange = firstZone.isGlobal ? firstZone.keyRange : { min: 0, max: 127 };
214
- const globalVelRange = firstZone.isGlobal ? firstZone.velRange : { min: 0, max: 127 };
216
+ let globalInstrumentGenerators = [...instrument.globalZone.generators];
217
+ let globalInstrumentModulators = [...instrument.globalZone.modulators];
218
+ const globalKeyRange = instrument.globalZone.keyRange;
219
+ const globalVelRange = instrument.globalZone.velRange;
215
220
 
216
221
 
217
- let instrumentZonesInRange = zone.instrument.instrumentZones
222
+ let instrumentZonesInRange = instrument.instrumentZones
218
223
  .filter(currentZone =>
219
- (
220
- isInRange(
221
- currentZone.hasKeyRange ? currentZone.keyRange : globalKeyRange,
222
- midiNote
223
- )
224
- &&
225
- isInRange(
226
- currentZone.hasVelRange ? currentZone.velRange : globalVelRange,
227
- velocity
228
- )
229
- ) && !currentZone.isGlobal
224
+
225
+ isInRange(
226
+ currentZone.hasKeyRange ? currentZone.keyRange : globalKeyRange,
227
+ midiNote
228
+ )
229
+ &&
230
+ isInRange(
231
+ currentZone.hasVelRange ? currentZone.velRange : globalVelRange,
232
+ velocity
233
+ )
230
234
  );
231
235
 
232
236
  instrumentZonesInRange.forEach(instrumentZone =>
@@ -275,7 +279,8 @@ export class BasicPreset
275
279
  if (identicalInstrumentModulator !== -1)
276
280
  {
277
281
  // sum the amounts
278
- // (this makes a new modulator because otherwise it would overwrite the one in the soundfont!
282
+ // this makes a new modulator
283
+ // because otherwise it would overwrite the one in the soundfont!
279
284
  finalModulatorList[identicalInstrumentModulator] = finalModulatorList[identicalInstrumentModulator].sumTransform(
280
285
  mod);
281
286
  }
@@ -291,9 +296,7 @@ export class BasicPreset
291
296
  instrumentGenerators: instrumentGenerators,
292
297
  presetGenerators: presetGenerators,
293
298
  modulators: finalModulatorList,
294
- sample: instrumentZone.sample,
295
- sampleID: instrumentZone.generators.find(
296
- g => g.generatorType === generatorTypes.sampleID).generatorValue
299
+ sample: instrumentZone.sample
297
300
  });
298
301
  });
299
302
  });
@@ -0,0 +1,30 @@
1
+ import { BasicZone } from "./basic_zone.js";
2
+
3
+ export class BasicPresetZone extends BasicZone
4
+ {
5
+ /**
6
+ * Zone's instrument
7
+ * @type {BasicInstrument}
8
+ */
9
+ instrument;
10
+
11
+ deleteZone()
12
+ {
13
+ this.instrument.removeUseCount();
14
+ }
15
+
16
+ /**
17
+ * @param instrument {BasicInstrument}
18
+ */
19
+ setInstrument(instrument)
20
+ {
21
+ this.instrument = instrument;
22
+ this.instrument.addUseCount();
23
+ }
24
+
25
+
26
+ hasInstrument()
27
+ {
28
+ return !!this.instrument;
29
+ }
30
+ }
@@ -10,15 +10,20 @@ import { write } from "./write_sf2/write.js";
10
10
  import { defaultModulators, Modulator } from "./modulator.js";
11
11
  import { writeDLS } from "./write_dls/write_dls.js";
12
12
  import { BasicSample } from "./basic_sample.js";
13
- import { BasicInstrumentZone, BasicPresetZone } from "./basic_zones.js";
14
- import { Generator, generatorTypes } from "./generator.js";
13
+ import { BasicPresetZone } from "./basic_preset_zone.js";
14
+ import { Generator } from "./generator.js";
15
15
  import { BasicInstrument } from "./basic_instrument.js";
16
16
  import { BasicPreset } from "./basic_preset.js";
17
17
  import { isXGDrums } from "../../utils/xg_hacks.js";
18
+ import { generatorTypes } from "./generator_types.js";
19
+ import { BasicInstrumentZone } from "./basic_instrument_zone.js";
20
+ import { BasicGlobalZone } from "./basic_global_zone.js";
18
21
 
22
+ /**
23
+ * Represents a single sound bank, be it DLS or SF2.
24
+ */
19
25
  class BasicSoundBank
20
26
  {
21
-
22
27
  /**
23
28
  * Soundfont's info stored as name: value. ifil and iver are stored as string representation of float (e.g., 2.1)
24
29
  * @type {Object<string, string|IndexedByteArray>}
@@ -124,29 +129,28 @@ class BasicSoundBank
124
129
  }
125
130
  font.samples.push(sample);
126
131
 
127
- const gZone = new BasicInstrumentZone();
128
- gZone.isGlobal = true;
132
+ const gZone = new BasicGlobalZone();
129
133
  gZone.generators.push(new Generator(generatorTypes.initialAttenuation, 375));
130
134
  gZone.generators.push(new Generator(generatorTypes.releaseVolEnv, -1000));
131
135
  gZone.generators.push(new Generator(generatorTypes.sampleModes, 1));
132
136
 
133
137
  const zone1 = new BasicInstrumentZone();
134
- zone1.sample = sample;
138
+ zone1.setSample(sample);
135
139
 
136
140
  const zone2 = new BasicInstrumentZone();
137
- zone2.sample = sample;
141
+ zone2.setSample(sample);
138
142
  zone2.generators.push(new Generator(generatorTypes.fineTune, -9));
139
143
 
140
144
 
141
145
  const inst = new BasicInstrument();
142
146
  inst.instrumentName = "Saw Wave";
143
- inst.instrumentZones.push(gZone);
144
- inst.instrumentZones.push(zone1);
145
- inst.instrumentZones.push(zone2);
147
+ inst.globalZone = gZone;
148
+ inst.addZone(zone1);
149
+ inst.addZone(zone2);
146
150
  font.instruments.push(inst);
147
151
 
148
152
  const pZone = new BasicPresetZone();
149
- pZone.instrument = inst;
153
+ pZone.setInstrument(inst);
150
154
 
151
155
  const preset = new BasicPreset(font);
152
156
  preset.presetName = "Saw Wave";
@@ -209,7 +213,7 @@ class BasicSoundBank
209
213
  const soundfont = this;
210
214
 
211
215
  /**
212
- * @param instrument {Instrument}
216
+ * @param instrument {BasicInstrument}
213
217
  * @param combos {{key: number, velocity: number}[]}
214
218
  * @returns {number}
215
219
  */
@@ -219,10 +223,6 @@ class BasicSoundBank
219
223
  for (let iZoneIndex = 0; iZoneIndex < instrument.instrumentZones.length; iZoneIndex++)
220
224
  {
221
225
  const iZone = instrument.instrumentZones[iZoneIndex];
222
- if (iZone.isGlobal)
223
- {
224
- continue;
225
- }
226
226
  const iKeyRange = iZone.keyRange;
227
227
  const iVelRange = iZone.velRange;
228
228
  let isIZoneUsed = false;
@@ -240,14 +240,13 @@ class BasicSoundBank
240
240
  if (!isIZoneUsed)
241
241
  {
242
242
  SpessaSynthInfo(
243
- `%c${iZone.sample.sampleName} %cremoved from %c${instrument.instrumentName}%c. Use count: %c${iZone.useCount - 1}`,
243
+ `%c${iZone.sample.sampleName} %cremoved from %c${instrument.instrumentName}%c.`,
244
244
  consoleColors.recognized,
245
245
  consoleColors.info,
246
246
  consoleColors.recognized,
247
- consoleColors.info,
248
- consoleColors.recognized
247
+ consoleColors.info
249
248
  );
250
- if (instrument.safeDeleteZone(iZoneIndex))
249
+ if (instrument.deleteZone(iZoneIndex))
251
250
  {
252
251
  trimmedIZones++;
253
252
  iZoneIndex--;
@@ -293,6 +292,7 @@ class BasicSoundBank
293
292
  consoleColors.info
294
293
  );
295
294
  soundfont.deletePreset(p);
295
+ soundfont.removeUnusedElements();
296
296
  presetIndex--;
297
297
  }
298
298
  else
@@ -316,10 +316,6 @@ class BasicSoundBank
316
316
  for (let zoneIndex = 0; zoneIndex < p.presetZones.length; zoneIndex++)
317
317
  {
318
318
  const zone = p.presetZones[zoneIndex];
319
- if (zone.isGlobal)
320
- {
321
- continue;
322
- }
323
319
  const keyRange = zone.keyRange;
324
320
  const velRange = zone.velRange;
325
321
  // check if any of the combos matches the zone
@@ -384,13 +380,7 @@ class BasicSoundBank
384
380
  {
385
381
  if (i.useCount < 1)
386
382
  {
387
- i.instrumentZones.forEach(z =>
388
- {
389
- if (!z.isGlobal)
390
- {
391
- z.sample.useCount--;
392
- }
393
- });
383
+ i.deleteZones();
394
384
  }
395
385
  });
396
386
  this.instruments = this.instruments.filter(i => i.useCount > 0);
@@ -407,8 +397,7 @@ class BasicSoundBank
407
397
  throw new Error(`Cannot delete an instrument that has ${instrument.useCount} usages.`);
408
398
  }
409
399
  this.instruments.splice(this.instruments.indexOf(instrument), 1);
410
- instrument.deleteInstrument();
411
- this.removeUnusedElements();
400
+ instrument.deleteZones();
412
401
  }
413
402
 
414
403
  /**
@@ -418,7 +407,6 @@ class BasicSoundBank
418
407
  {
419
408
  preset.deletePreset();
420
409
  this.presets.splice(this.presets.indexOf(preset), 1);
421
- this.removeUnusedElements();
422
410
  }
423
411
 
424
412
  /**
@@ -431,7 +419,6 @@ class BasicSoundBank
431
419
  throw new Error(`Cannot delete sample that has ${sample.useCount} usages.`);
432
420
  }
433
421
  this.samples.splice(this.samples.indexOf(sample), 1);
434
- this.removeUnusedElements();
435
422
  }
436
423
 
437
424
  /**
@@ -563,15 +550,6 @@ class BasicSoundBank
563
550
  delete this.instruments;
564
551
  delete this.samples;
565
552
  }
566
-
567
- // noinspection JSUnusedGlobalSymbols
568
- /**
569
- * Clears the cache for all the presets
570
- */
571
- clearCache()
572
- {
573
- this.presets.forEach(p => p.clearCache());
574
- }
575
553
  }
576
554
 
577
555
  BasicSoundBank.prototype.write = write;
@@ -19,11 +19,7 @@ export class BasicZone
19
19
  * @type {SoundFontRange}
20
20
  */
21
21
  keyRange = { min: -1, max: 127 };
22
- /**
23
- * Indicates if the zone is global
24
- * @type {boolean}
25
- */
26
- isGlobal = false;
22
+
27
23
  /**
28
24
  * The zone's generators
29
25
  * @type {Generator[]}