spessasynth_lib 3.16.5 → 3.20.0

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 (87) hide show
  1. package/@types/index.d.ts +5 -4
  2. package/@types/midi_parser/basic_midi.d.ts +125 -0
  3. package/@types/midi_parser/midi_builder.d.ts +69 -0
  4. package/@types/midi_parser/midi_data.d.ts +2 -2
  5. package/@types/midi_parser/midi_editor.d.ts +4 -4
  6. package/@types/midi_parser/midi_loader.d.ts +3 -100
  7. package/@types/midi_parser/midi_writer.d.ts +2 -2
  8. package/@types/midi_parser/rmidi_writer.d.ts +3 -3
  9. package/@types/midi_parser/used_keys_loaded.d.ts +2 -2
  10. package/@types/sequencer/sequencer.d.ts +1 -1
  11. package/@types/soundfont/basic_soundfont/basic_sample.d.ts +2 -2
  12. package/@types/soundfont/basic_soundfont/basic_zone.d.ts +12 -12
  13. package/@types/soundfont/basic_soundfont/basic_zones.d.ts +4 -0
  14. package/@types/soundfont/basic_soundfont/riff_chunk.d.ts +6 -0
  15. package/@types/soundfont/basic_soundfont/write_sf2/soundfont_trimmer.d.ts +2 -2
  16. package/@types/soundfont/dls/articulator_converter.d.ts +10 -0
  17. package/@types/soundfont/dls/dls_destinations.d.ts +29 -0
  18. package/@types/soundfont/dls/dls_preset.d.ts +13 -0
  19. package/@types/soundfont/dls/dls_sample.d.ts +18 -0
  20. package/@types/soundfont/dls/dls_soundfont.d.ts +31 -0
  21. package/@types/soundfont/dls/dls_sources.d.ts +22 -0
  22. package/@types/soundfont/dls/dls_zone.d.ts +22 -0
  23. package/@types/soundfont/dls/read_articulation.d.ts +12 -0
  24. package/@types/soundfont/dls/read_instrument.d.ts +5 -0
  25. package/@types/soundfont/dls/read_instrument_list.d.ts +5 -0
  26. package/@types/soundfont/dls/read_lart.d.ts +7 -0
  27. package/@types/soundfont/dls/read_region.d.ts +7 -0
  28. package/@types/soundfont/dls/read_samples.d.ts +5 -0
  29. package/@types/soundfont/load_soundfont.d.ts +6 -0
  30. package/@types/soundfont/read_sf2/generators.d.ts +18 -5
  31. package/@types/soundfont/read_sf2/modulators.d.ts +1 -0
  32. package/@types/soundfont/soundfont.d.ts +2 -1
  33. package/@types/synthetizer/synthetizer.d.ts +2 -2
  34. package/@types/utils/byte_functions/little_endian.d.ts +1 -1
  35. package/README.md +27 -15
  36. package/index.js +6 -4
  37. package/midi_parser/basic_midi.js +146 -0
  38. package/midi_parser/midi_builder.js +281 -0
  39. package/midi_parser/midi_data.js +1 -1
  40. package/midi_parser/midi_editor.js +2 -2
  41. package/midi_parser/midi_loader.js +38 -56
  42. package/midi_parser/midi_writer.js +1 -1
  43. package/midi_parser/rmidi_writer.js +2 -2
  44. package/midi_parser/used_keys_loaded.js +1 -1
  45. package/package.json +1 -1
  46. package/sequencer/sequencer.js +1 -1
  47. package/sequencer/worklet_sequencer/song_control.js +3 -3
  48. package/sequencer/worklet_sequencer/worklet_sequencer.js +1 -1
  49. package/soundfont/README.md +6 -2
  50. package/soundfont/basic_soundfont/basic_sample.js +3 -3
  51. package/soundfont/basic_soundfont/basic_zone.js +28 -28
  52. package/soundfont/basic_soundfont/basic_zones.js +15 -19
  53. package/soundfont/basic_soundfont/riff_chunk.js +20 -4
  54. package/soundfont/basic_soundfont/write_sf2/soundfont_trimmer.js +1 -1
  55. package/soundfont/dls/articulator_converter.js +311 -0
  56. package/soundfont/dls/dls_destinations.js +38 -0
  57. package/soundfont/dls/dls_preset.js +32 -0
  58. package/soundfont/dls/dls_sample.js +58 -0
  59. package/soundfont/dls/dls_soundfont.js +150 -0
  60. package/soundfont/dls/dls_sources.js +26 -0
  61. package/soundfont/dls/dls_zone.js +75 -0
  62. package/soundfont/dls/read_articulation.js +327 -0
  63. package/soundfont/dls/read_instrument.js +100 -0
  64. package/soundfont/dls/read_instrument_list.js +17 -0
  65. package/soundfont/dls/read_lart.js +35 -0
  66. package/soundfont/dls/read_region.js +129 -0
  67. package/soundfont/dls/read_samples.js +174 -0
  68. package/soundfont/load_soundfont.js +21 -0
  69. package/soundfont/read_sf2/generators.js +41 -6
  70. package/soundfont/read_sf2/instruments.js +2 -2
  71. package/soundfont/read_sf2/modulators.js +8 -8
  72. package/soundfont/read_sf2/presets.js +7 -7
  73. package/soundfont/read_sf2/samples.js +8 -8
  74. package/soundfont/read_sf2/zones.js +5 -5
  75. package/soundfont/soundfont.js +8 -3
  76. package/synthetizer/synthetizer.js +1 -1
  77. package/synthetizer/worklet_processor.min.js +10 -7
  78. package/synthetizer/worklet_system/main_processor.js +1 -2
  79. package/synthetizer/worklet_system/worklet_methods/program_control.js +6 -3
  80. package/synthetizer/worklet_system/worklet_methods/worklet_soundfont_manager/worklet_soundfont_manager.js +5 -5
  81. package/utils/buffer_to_wav.js +5 -26
  82. package/utils/byte_functions/little_endian.js +1 -1
  83. /package/@types/{midi_handler → external_midi}/midi_handler.d.ts +0 -0
  84. /package/@types/{midi_handler → external_midi}/web_midi_link.d.ts +0 -0
  85. /package/{midi_handler → external_midi}/README.md +0 -0
  86. /package/{midi_handler → external_midi}/midi_handler.js +0 -0
  87. /package/{midi_handler → external_midi}/web_midi_link.js +0 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @enum {number}
3
+ */
4
+ export const DLSSources = {
5
+ none: 0x0,
6
+ modLfo: 0x1,
7
+ velocity: 0x2,
8
+ keyNum: 0x3,
9
+ volEnv: 0x4,
10
+ modEnv: 0x5,
11
+ pitchWheel: 0x6,
12
+ polyPressure: 0x7,
13
+ channelPressure: 0x8,
14
+ vibratoLfo: 0x9,
15
+
16
+ modulationWheel: 0x81,
17
+ volume: 0x87,
18
+ pan: 0x8a,
19
+ expression: 0x8b,
20
+ chorus: 0xdb,
21
+ reverb: 0xdd,
22
+
23
+ pitchWheelRange: 0x100,
24
+ fineTune: 0x101,
25
+ coarseTune: 0x102
26
+ }
@@ -0,0 +1,75 @@
1
+ import { BasicInstrumentZone } from '../basic_soundfont/basic_zones.js'
2
+ import { Generator, generatorTypes } from '../read_sf2/generators.js'
3
+
4
+ export class DLSZone extends BasicInstrumentZone
5
+ {
6
+ /**
7
+ * @param keyRange {SoundFontRange}
8
+ * @param velRange {SoundFontRange}
9
+ */
10
+ constructor(keyRange, velRange)
11
+ {
12
+ super();
13
+ this.keyRange = keyRange;
14
+ this.velRange = velRange;
15
+ this.isGlobal = true;
16
+ }
17
+
18
+ /**
19
+ * @param attenuationCb {number} with EMU correction
20
+ * @param loopingMode {number} the sfont one
21
+ * @param loop {{start: number, end: number}}
22
+ * @param sampleKey {number}
23
+ * @param sample {BasicSample}
24
+ * @param sampleID {number}
25
+ */
26
+ setWavesample(
27
+ attenuationCb,
28
+ loopingMode,
29
+ loop,
30
+ sampleKey,
31
+ sample,
32
+ sampleID,
33
+ )
34
+ {
35
+ if(loopingMode !== 0)
36
+ {
37
+ this.generators.push(new Generator(generatorTypes.sampleModes, loopingMode));
38
+ }
39
+ this.generators.push(new Generator(generatorTypes.initialAttenuation, attenuationCb));
40
+ this.isGlobal = false;
41
+
42
+ // correct loop if needed
43
+ const diffStart = loop.start - (sample.sampleLoopStartIndex / 2);
44
+ const diffEnd = loop.end - (sample.sampleLoopEndIndex / 2);
45
+ if(diffStart !== 0)
46
+ {
47
+ const fine = diffStart % 32768;
48
+ this.generators.push(new Generator(generatorTypes.startloopAddrsOffset, fine));
49
+ const coarse = Math.round(diffStart / 32768);
50
+ if(coarse !== 0)
51
+ {
52
+ this.generators.push(new Generator(generatorTypes.startloopAddrsCoarseOffset, fine));
53
+ }
54
+ }
55
+ if(diffEnd !== 0)
56
+ {
57
+ const fine = diffEnd % 32768;
58
+ this.generators.push(new Generator(generatorTypes.endloopAddrsOffset, fine));
59
+ const coarse = Math.round(diffEnd / 32768);
60
+ if(coarse !== 0)
61
+ {
62
+ this.generators.push(new Generator(generatorTypes.endloopAddrsCoarseOffset, fine));
63
+ }
64
+ }
65
+ // correct key if needed
66
+ if(sampleKey !== sample.samplePitch)
67
+ {
68
+ this.generators.push(new Generator(generatorTypes.overridingRootKey, sampleKey));
69
+ }
70
+ // add sample ID
71
+ this.generators.push(new Generator(generatorTypes.sampleID, sampleID));
72
+ this.sample = sample;
73
+ sample.useCount++;
74
+ }
75
+ }
@@ -0,0 +1,327 @@
1
+ import { readLittleEndian } from '../../utils/byte_functions/little_endian.js'
2
+ import { DLSDestinations } from './dls_destinations.js'
3
+ import { Generator, generatorTypes } from '../read_sf2/generators.js'
4
+ import { DLSSources } from './dls_sources.js'
5
+ import { Modulator } from '../read_sf2/modulators.js'
6
+ import { getSF2ModulatorFromArticulator } from './articulator_converter.js'
7
+ import { SpessaSynthInfo, SpessaSynthWarn } from '../../utils/loggin.js'
8
+ import { consoleColors } from '../../utils/other.js'
9
+
10
+ /**
11
+ * @param source {number}
12
+ * @param control {number}
13
+ * @param destination {number}
14
+ * @param value {number}
15
+ * @param transform {number}
16
+ */
17
+ function modulatorConverterDebug(
18
+ source,
19
+ control,
20
+ destination,
21
+ value,
22
+ transform
23
+ )
24
+ {
25
+ const type = Object.keys(DLSDestinations).find(k => DLSDestinations[k] === destination);
26
+ const srcType = Object.keys(DLSSources).find(k => DLSSources[k] === source);
27
+ const ctrlType = Object.keys(DLSSources).find(k => DLSSources[k] === control);
28
+ const typeString = type ? type : destination.toString(16);
29
+ const srcString = srcType ? srcType : source.toString(16);
30
+ const ctrlString = ctrlType ? ctrlType : control.toString(16);
31
+ SpessaSynthInfo(
32
+ `%cAttempting to convert the following DLS Articulator to SF2 Modulator:
33
+ Source: %c${srcString}%c
34
+ Control: %c${ctrlString}%c
35
+ Destination: %c${typeString}%c
36
+ Amount: %c${value}%c
37
+ Transform: %c${transform}%c...`,
38
+ consoleColors.info,
39
+ consoleColors.recognized,
40
+ consoleColors.info,
41
+ consoleColors.recognized,
42
+ consoleColors.info,
43
+ consoleColors.recognized,
44
+ consoleColors.info,
45
+ consoleColors.recognized,
46
+ consoleColors.info,
47
+ consoleColors.recognized,
48
+ consoleColors.info);
49
+ }
50
+
51
+ /**
52
+ * Reads the articulator chunk
53
+ * @param chunk {RiffChunk}
54
+ * @param disableVibrato {boolean} it seems that dls 1 does not have vibrato lfo, so we shall disable it
55
+ * @returns {{modulators: Modulator[], generators: Generator[]}}
56
+ */
57
+ export function readArticulation(chunk, disableVibrato)
58
+ {
59
+ const artData = chunk.chunkData;
60
+ /**
61
+ * @type {Generator[]}
62
+ */
63
+ const generators = [];
64
+ /**
65
+ * @type {Modulator[]}
66
+ */
67
+ const modulators = [];
68
+
69
+ // cbSize (ignore)
70
+ readLittleEndian(artData, 4);
71
+ const connectionsAmount = readLittleEndian(artData, 4);
72
+ for (let i = 0; i < connectionsAmount; i++)
73
+ {
74
+ // read the block
75
+ const source = readLittleEndian(artData, 2);
76
+ const control = readLittleEndian(artData, 2);
77
+ const destination = readLittleEndian(artData, 2);
78
+ const transform = readLittleEndian(artData, 2);
79
+ const value = readLittleEndian(artData, 4) >> 16; // convert it to 16 bit as soundfont uses that
80
+
81
+ // interpret this somehow...
82
+ // if source and control are both zero, it's a generator
83
+ if(source === 0 && control === 0 && transform === 0)
84
+ {
85
+ /**
86
+ * @type {Generator}
87
+ */
88
+ let generator;
89
+ switch(destination)
90
+ {
91
+ case DLSDestinations.pan:
92
+ generator = new Generator(generatorTypes.pan, value); // turn percent into tenths of percent
93
+ break;
94
+ case DLSDestinations.gain:
95
+ generator = new Generator(generatorTypes.initialAttenuation, -value * 10 / 0.4); // turn to centibels and apply emu correction
96
+ break;
97
+ case DLSDestinations.filterCutoff:
98
+ generator = new Generator(generatorTypes.initialFilterFc, value);
99
+ break;
100
+ case DLSDestinations.filterQ:
101
+ generator = new Generator(generatorTypes.initialFilterQ, value);
102
+ break;
103
+
104
+ // mod lfo raw values it seems
105
+ case DLSDestinations.modLfoFreq:
106
+ generator = new Generator(generatorTypes.freqModLFO, value);
107
+ break;
108
+ case DLSDestinations.modLfoDelay:
109
+ generator = new Generator(generatorTypes.delayModLFO, value);
110
+ break;
111
+ case DLSDestinations.vibLfoFreq:
112
+ generator = new Generator(generatorTypes.freqVibLFO, value);
113
+ break;
114
+ case DLSDestinations.vibLfoDelay:
115
+ generator = new Generator(generatorTypes.delayVibLFO, value);
116
+ break;
117
+
118
+ // vol env: all times are timecents like sf2
119
+ case DLSDestinations.volEnvDelay:
120
+ generator = new Generator(generatorTypes.delayVolEnv, value);
121
+ break;
122
+ case DLSDestinations.volEnvAttack:
123
+ generator = new Generator(generatorTypes.attackVolEnv, value);
124
+ break;
125
+ case DLSDestinations.volEnvHold:
126
+ generator = new Generator(generatorTypes.holdVolEnv, value);
127
+ break;
128
+ case DLSDestinations.volEnvDecay:
129
+ generator = new Generator(generatorTypes.decayVolEnv, value);
130
+ break;
131
+ case DLSDestinations.volEnvRelease:
132
+ generator = new Generator(generatorTypes.releaseVolEnv, value);
133
+ break;
134
+ case DLSDestinations.volEnvSustain:
135
+ // gain seems to be (1000 - value) / 10 = sustain dB
136
+ const sustainDb = (1000 - value) / 10;
137
+ generator = new Generator(generatorTypes.sustainVolEnv, sustainDb * 10);
138
+ break;
139
+
140
+ // mod env
141
+ case DLSDestinations.modEnvDelay:
142
+ generator = new Generator(generatorTypes.delayModEnv, value);
143
+ break;
144
+ case DLSDestinations.modEnvAttack:
145
+ generator = new Generator(generatorTypes.attackModEnv, value);
146
+ break;
147
+ case DLSDestinations.modEnvHold:
148
+ generator = new Generator(generatorTypes.holdModEnv, value);
149
+ break;
150
+ case DLSDestinations.modEnvDecay:
151
+ generator = new Generator(generatorTypes.decayModEnv, value);
152
+ break;
153
+ case DLSDestinations.modEnvRelease:
154
+ generator = new Generator(generatorTypes.releaseModEnv, value);
155
+ break;
156
+ case DLSDestinations.modEnvSustain:
157
+ // dls uses 1%, desfont uses 0.1%
158
+ const percentageSustain = 1000 - value;
159
+ generator = new Generator(generatorTypes.sustainModEnv, percentageSustain);
160
+ break;
161
+
162
+ case DLSDestinations.reverbSend:
163
+ generator = new Generator(generatorTypes.reverbEffectsSend, value);
164
+ break;
165
+ case DLSDestinations.chorusSend:
166
+ generator = new Generator(generatorTypes.chorusEffectsSend, value);
167
+ break;
168
+ case DLSDestinations.pitch:
169
+ // split it up
170
+ const semi = Math.floor(value / 100);
171
+ const cents = Math.floor(value - semi * 100);
172
+ generator = new Generator(generatorTypes.fineTune, cents);
173
+ generators.push(new Generator(generatorTypes.coarseTune, semi));
174
+ break;
175
+ }
176
+ if(generator)
177
+ {
178
+ generators.push(generator);
179
+ }
180
+ }
181
+ else
182
+ // if not, modulator??
183
+ {
184
+ let isGenerator = true;
185
+ // a few special cases which are generators:
186
+ if(control === DLSSources.none)
187
+ {
188
+ // mod lfo to pitch
189
+ if(source === DLSSources.modLfo && destination === DLSDestinations.pitch)
190
+ {
191
+ generators.push(new Generator(generatorTypes.modLfoToPitch, value));
192
+ }
193
+ else
194
+ // mod lfo to volume
195
+ if(source === DLSSources.modLfo && destination === DLSDestinations.gain)
196
+ {
197
+ generators.push(new Generator(generatorTypes.modLfoToVolume, value));
198
+ }
199
+ else
200
+ // mod lfo to filter
201
+ if(source === DLSSources.modLfo && destination === DLSDestinations.filterCutoff)
202
+ {
203
+ generators.push(new Generator(generatorTypes.modLfoToFilterFc, value));
204
+ }
205
+ else
206
+ // vib lfo to pitch
207
+ if(source === DLSSources.vibratoLfo && destination === DLSDestinations.pitch)
208
+ {
209
+ generators.push(new Generator(generatorTypes.vibLfoToPitch, value));
210
+ }
211
+ else
212
+ // mod env to pitch
213
+ if(source === DLSSources.modEnv && destination === DLSDestinations.pitch)
214
+ {
215
+ generators.push(new Generator(generatorTypes.modEnvToPitch, value));
216
+ }
217
+ else
218
+ // mod env to filter
219
+ if(source === DLSSources.modEnv && destination === DLSDestinations.filterCutoff)
220
+ {
221
+ generators.push(new Generator(generatorTypes.modEnvToFilterFc, value));
222
+ }
223
+ else
224
+ // key to vol env hold
225
+ if(source === DLSSources.keyNum && destination === DLSDestinations.volEnvHold)
226
+ {
227
+ // according to viena and another strange (with modulators) rendition of gm.dls in sf2, this is how it should be done???
228
+ generators.push(new Generator(generatorTypes.keyNumToVolEnvHold, value / -127));
229
+ }
230
+ else
231
+ // key to vol env decay
232
+ if(source === DLSSources.keyNum && destination === DLSDestinations.volEnvDecay)
233
+ {
234
+ generators.push(new Generator(generatorTypes.keyNumToVolEnvDecay, value / -127));
235
+ }
236
+ else
237
+ // key to mod env hold
238
+ if(source === DLSSources.keyNum && destination === DLSDestinations.modEnvHold)
239
+ {
240
+ generators.push(new Generator(generatorTypes.keyNumToModEnvHold, value / -127));
241
+ }
242
+ else
243
+ // key to mod env decay
244
+ if(source === DLSSources.keyNum && destination === DLSDestinations.modEnvDecay)
245
+ {
246
+ generators.push(new Generator(generatorTypes.keyNumToModEnvDecay, value / -127));
247
+ }
248
+ else
249
+ {
250
+ isGenerator = false;
251
+ }
252
+
253
+ }
254
+ else
255
+ {
256
+ isGenerator = false;
257
+ }
258
+ if(isGenerator === false)
259
+ {
260
+ // UNCOMMENT TO ENABLE DEBUG
261
+ // modulatorConverterDebug(source, control, destination, value, transform)
262
+ // convert it to modulator
263
+ const mod = getSF2ModulatorFromArticulator(
264
+ source,
265
+ control,
266
+ destination,
267
+ transform,
268
+ value
269
+ );
270
+ if(mod)
271
+ {
272
+ // some articulators cannot be turned into modulators, that's why this check is a thing
273
+ modulators.push(mod);
274
+ SpessaSynthInfo("%cSucceeded converting to SF2 Modulator!", consoleColors.recognized)
275
+ }
276
+ else
277
+ {
278
+ SpessaSynthWarn("Failed converting to SF2 Modulator!")
279
+ }
280
+ }
281
+ }
282
+ }
283
+
284
+ // override reverb and chorus with 1000 instead of 200
285
+ modulators.push(
286
+ new Modulator({
287
+ srcEnum: 0x00DB,
288
+ dest: generatorTypes.reverbEffectsSend,
289
+ amt: 1000,
290
+ secSrcEnum: 0x0,
291
+ transform: 0
292
+ }),
293
+ // chorus effects to send
294
+ new Modulator({
295
+ srcEnum: 0x00DD,
296
+ dest: generatorTypes.chorusEffectsSend,
297
+ amt: 1000,
298
+ secSrcEnum: 0x0,
299
+ transform: 0
300
+ }),
301
+ )
302
+
303
+ // it seems that dls 1 does not have vibrato lfo, so we shall disable it
304
+ if(disableVibrato)
305
+ {
306
+ modulators.push(
307
+ // mod to vib
308
+ new Modulator({
309
+ srcEnum: 0x0081,
310
+ dest: generatorTypes.vibLfoToPitch,
311
+ amt: 0,
312
+ secSrcEnum: 0x0,
313
+ transform: 0
314
+ }),
315
+ // press to vib
316
+ new Modulator({
317
+ srcEnum: 0x000D,
318
+ dest: generatorTypes.vibLfoToPitch,
319
+ amt: 0,
320
+ secSrcEnum: 0x0,
321
+ transform: 0
322
+ })
323
+ );
324
+ }
325
+
326
+ return {modulators: modulators, generators: generators}
327
+ }
@@ -0,0 +1,100 @@
1
+ import { readBytesAsString } from '../../utils/byte_functions/string.js'
2
+ import { readLittleEndian } from '../../utils/byte_functions/little_endian.js'
3
+ import { DLSPreset } from './dls_preset.js'
4
+ import { findRIFFListType, readRIFFChunk } from '../basic_soundfont/riff_chunk.js'
5
+ import { SpessaSynthGroup, SpessaSynthGroupEnd } from '../../utils/loggin.js'
6
+ import { BasicInstrumentZone } from '../basic_soundfont/basic_zones.js'
7
+ import { consoleColors } from '../../utils/other.js'
8
+
9
+ /**
10
+ * @this {DLSSoundFont}
11
+ * @param chunk {RiffChunk}
12
+ */
13
+ export function readDLSInstrument(chunk)
14
+ {
15
+ this.verifyHeader(chunk, "LIST");
16
+ this.verifyText(readBytesAsString(chunk.chunkData, 4), "ins ");
17
+ /**
18
+ * @type {RiffChunk[]}
19
+ */
20
+ const chunks = [];
21
+ while(chunk.chunkData.length > chunk.chunkData.currentIndex)
22
+ {
23
+ chunks.push(readRIFFChunk(chunk.chunkData));
24
+ }
25
+
26
+
27
+ const instrumentHeader = chunks.find(c => c.header === "insh");
28
+ if(!instrumentHeader)
29
+ {
30
+ SpessaSynthGroupEnd();
31
+ throw new Error("No instrument header!");
32
+ }
33
+
34
+ // read instrument header
35
+ const regions = readLittleEndian(instrumentHeader.chunkData, 4);
36
+ const ulBank = readLittleEndian(instrumentHeader.chunkData, 4);
37
+ const ulInstrument = readLittleEndian(instrumentHeader.chunkData, 4);
38
+ const preset = new DLSPreset(ulBank, ulInstrument);
39
+
40
+ // read preset name in INFO
41
+ let presetName = "unnamedPreset";
42
+ const infoChunk = findRIFFListType(chunks, "INFO");
43
+ if(infoChunk)
44
+ {
45
+ let info = readRIFFChunk(infoChunk.chunkData);
46
+ while(info.header !== "INAM")
47
+ {
48
+ info = readRIFFChunk(infoChunk.chunkData);
49
+ }
50
+ presetName = readBytesAsString(info.chunkData, info.chunkData.length).trim();
51
+ }
52
+ preset.presetName = presetName;
53
+ preset.DLSInstrument.instrumentName = presetName;
54
+ SpessaSynthGroup(`%cParsing %c"${presetName}"%c...`,
55
+ consoleColors.info,
56
+ consoleColors.recognized,
57
+ consoleColors.info);
58
+
59
+ // list of regions
60
+ const regionListChunk = findRIFFListType(chunks, "lrgn");
61
+ if(!regionListChunk)
62
+ {
63
+ SpessaSynthGroupEnd();
64
+ throw new Error("No region list!");
65
+ }
66
+
67
+ // global articulation: essentially global zone
68
+ const globalZone = new BasicInstrumentZone();
69
+ globalZone.isGlobal = true;
70
+
71
+ // read articulators
72
+ const globalLart = findRIFFListType(chunks, "lart");
73
+ const globalLar2 = findRIFFListType(chunks, "lar2");
74
+ this.readLart(globalLart, globalLar2, globalZone);
75
+ preset.DLSInstrument.instrumentZones.push(globalZone);
76
+
77
+ // read regions
78
+ for (let i = 0; i < regions; i++)
79
+ {
80
+ const chunk = readRIFFChunk(regionListChunk.chunkData);
81
+ this.verifyHeader(chunk, "LIST");
82
+ const type = readBytesAsString(chunk.chunkData, 4);
83
+ if(type !== "rgn " && type !== "rgn2")
84
+ {
85
+ SpessaSynthGroupEnd();
86
+ throw new SyntaxError(`Invalid DLS region! Expected "rgn " or "rgn2" got "${type}"`);
87
+ }
88
+
89
+
90
+ const zone = this.readRegion(chunk);
91
+ if(zone)
92
+ {
93
+ preset.DLSInstrument.instrumentZones.push(zone);
94
+ }
95
+ }
96
+
97
+ this.presets.push(preset);
98
+ this.instruments.push(preset.DLSInstrument);
99
+ SpessaSynthGroupEnd();
100
+ }
@@ -0,0 +1,17 @@
1
+ import { readRIFFChunk } from '../basic_soundfont/riff_chunk.js'
2
+ import { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd } from '../../utils/loggin.js'
3
+ import { consoleColors } from '../../utils/other.js'
4
+
5
+ /**
6
+ * @this {DLSSoundFont}
7
+ * @param instrumentListChunk {RiffChunk}
8
+ */
9
+ export function readDLSInstrumentList(instrumentListChunk)
10
+ {
11
+ SpessaSynthGroupCollapsed("%cLoading instruments...", consoleColors.info);
12
+ for(let i = 0; i < this.instrumentAmount; i++)
13
+ {
14
+ this.readDLSInstrument(readRIFFChunk(instrumentListChunk.chunkData));
15
+ }
16
+ SpessaSynthGroupEnd();
17
+ }
@@ -0,0 +1,35 @@
1
+ import { readRIFFChunk } from '../basic_soundfont/riff_chunk.js'
2
+ import { readArticulation } from './read_articulation.js'
3
+
4
+ /**
5
+ * @param lartChunk {RiffChunk|undefined}
6
+ * @param lar2Chunk {RiffChunk|undefined}
7
+ * @param zone {BasicInstrumentZone}
8
+ * @this {DLSSoundFont}
9
+ */
10
+ export function readLart(lartChunk, lar2Chunk, zone)
11
+ {
12
+ if(lartChunk)
13
+ {
14
+ while(lartChunk.chunkData.currentIndex < lartChunk.chunkData.length)
15
+ {
16
+ const art1 = readRIFFChunk(lartChunk.chunkData);
17
+ this.verifyHeader(art1, "art1");
18
+ const modsAndGens = readArticulation(art1, true);
19
+ zone.generators.push(...modsAndGens.generators);
20
+ zone.modulators.push(...modsAndGens.modulators);
21
+ }
22
+ }
23
+
24
+ if(lar2Chunk)
25
+ {
26
+ while(lar2Chunk.chunkData.currentIndex < lar2Chunk.chunkData.length)
27
+ {
28
+ const art2 = readRIFFChunk(lar2Chunk.chunkData);
29
+ this.verifyHeader(art2, "art2");
30
+ const modsAndGens = readArticulation(art2, false);
31
+ zone.generators.push(...modsAndGens.generators);
32
+ zone.modulators.push(...modsAndGens.modulators);
33
+ }
34
+ }
35
+ }