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,129 @@
1
+ import { readLittleEndian } from '../../utils/byte_functions/little_endian.js'
2
+ import { findRIFFListType, readRIFFChunk } from '../basic_soundfont/riff_chunk.js'
3
+ import { Generator, generatorTypes } from '../read_sf2/generators.js'
4
+ import { DLSZone } from './dls_zone.js'
5
+
6
+ /**
7
+ * @this {DLSSoundFont}
8
+ * @param chunk {RiffChunk}
9
+ * @returns {DLSZone}
10
+ */
11
+ export function readRegion(chunk)
12
+ {
13
+ // regions are essentially instrument zones
14
+
15
+ /**
16
+ * read chunks in the region
17
+ * @type {RiffChunk[]}
18
+ */
19
+ const regionChunks = [];
20
+ while(chunk.chunkData.length > chunk.chunkData.currentIndex)
21
+ {
22
+ regionChunks.push(readRIFFChunk(chunk.chunkData));
23
+ }
24
+
25
+ // region header
26
+ const regionHeader = regionChunks.find(c => c.header === "rgnh");
27
+ // key range
28
+ const keyMin = readLittleEndian(regionHeader.chunkData, 2);
29
+ const keyMax = readLittleEndian(regionHeader.chunkData, 2);
30
+ // vel range
31
+ const velMin = readLittleEndian(regionHeader.chunkData, 2);
32
+ const velMax = readLittleEndian(regionHeader.chunkData, 2);
33
+
34
+ const zone = new DLSZone(
35
+ {min: keyMin, max: keyMax},
36
+ {min: velMin, max: velMax}
37
+ )
38
+
39
+ // fusOptions: no idea about that one???
40
+ readLittleEndian(regionHeader.chunkData, 2);
41
+
42
+ // keyGroup: essentially exclusive class
43
+ const exclusive = readLittleEndian(regionHeader.chunkData, 2);
44
+ if(exclusive !== 0)
45
+ {
46
+ zone.generators.push(new Generator(generatorTypes.exclusiveClass, exclusive));
47
+ }
48
+
49
+ // lart
50
+ const lart = findRIFFListType(regionChunks, "lart");
51
+ const lar2 = findRIFFListType(regionChunks, "lar2");
52
+ this.readLart(lart, lar2, zone);
53
+
54
+ // wsmpl: wave sample chunk
55
+ zone.isGlobal = false;
56
+ const waveSampleChunk = regionChunks.find(c => c.header === "wsmp");
57
+ // cbSize
58
+ readLittleEndian(waveSampleChunk.chunkData, 4);
59
+ const originalKey = readLittleEndian(waveSampleChunk.chunkData, 2);
60
+ // pitch correction is read from the wave wsmpl chunk
61
+ readLittleEndian(waveSampleChunk.chunkData, 2);
62
+
63
+ // gain correction: Each unit of gain represents 1/655360 dB
64
+ const gainCorrection = readLittleEndian(waveSampleChunk.chunkData, 4);
65
+ // convert to signed and turn into attenuation (invert)
66
+ const dbCorrection = (gainCorrection | 0) / -655360;
67
+ // convert to centibels
68
+ const attenuation = (dbCorrection * 10) / 0.4; // make sure to apply EMU correction
69
+
70
+ // skip options
71
+ readLittleEndian(waveSampleChunk.chunkData, 4);
72
+
73
+ // read loop count (always one or zero)
74
+ const loopsAmount = readLittleEndian(waveSampleChunk.chunkData, 4);
75
+ let loopingMode;
76
+ const loop = {start: 0, end: 0};
77
+ if(loopsAmount === 0)
78
+ {
79
+ // no loop
80
+ loopingMode = 0;
81
+ }
82
+ else
83
+ {
84
+ // ignore cbSize
85
+ readLittleEndian(waveSampleChunk.chunkData, 4);
86
+ // loop type: loop normally or loop until release (like soundfont)
87
+ const loopType = readLittleEndian(waveSampleChunk.chunkData, 4); // why is it long???
88
+ if(loopType === 0)
89
+ {
90
+ loopingMode = 1;
91
+ }
92
+ else
93
+ {
94
+ loopingMode = 3;
95
+ }
96
+ loop.start = readLittleEndian(waveSampleChunk.chunkData, 4);
97
+ const loopLength = readLittleEndian(waveSampleChunk.chunkData, 4);
98
+ loop.end = loop.start + loopLength;
99
+ }
100
+
101
+ // wave link
102
+ const waveLinkChunk = regionChunks.find(c => c.header === "wlnk");
103
+ if(waveLinkChunk === undefined)
104
+ {
105
+ // no wave link = no sample. What? Why is it even here then????
106
+ return undefined;
107
+ }
108
+
109
+ // flags
110
+ readLittleEndian(waveLinkChunk.chunkData, 2);
111
+ // phasse group
112
+ readLittleEndian(waveLinkChunk.chunkData, 2);
113
+ // channel
114
+ readLittleEndian(waveLinkChunk.chunkData, 4);
115
+ // sampleID
116
+ const sampleID = readLittleEndian(waveLinkChunk.chunkData, 4);
117
+ const sample = this.samples[sampleID];
118
+ if(sample === undefined)
119
+ {
120
+ throw new Error("Invalid sample ID!");
121
+ }
122
+ zone.setWavesample(
123
+ attenuation, loopingMode,
124
+ loop,
125
+ originalKey,
126
+ sample,
127
+ sampleID);
128
+ return zone;
129
+ }
@@ -0,0 +1,174 @@
1
+ import { findRIFFListType, readRIFFChunk } from '../basic_soundfont/riff_chunk.js'
2
+ import { readBytesAsString } from '../../utils/byte_functions/string.js'
3
+ import {
4
+ SpessaSynthGroupCollapsed,
5
+ SpessaSynthGroupEnd,
6
+ SpessaSynthInfo, SpessaSynthWarn,
7
+ } from '../../utils/loggin.js'
8
+ import { consoleColors } from '../../utils/other.js'
9
+ import { readLittleEndian, signedInt16 } from '../../utils/byte_functions/little_endian.js'
10
+ import { DLSSample } from './dls_sample.js'
11
+
12
+ /**
13
+ * @this {DLSSoundFont}
14
+ * @param waveListChunk {RiffChunk}
15
+ */
16
+ export function readDLSSamples(waveListChunk)
17
+ {
18
+ SpessaSynthGroupCollapsed("%cLoading Wave samples...",
19
+ consoleColors.recognized);
20
+ let sampleID = 0;
21
+ while(waveListChunk.chunkData.currentIndex < waveListChunk.chunkData.length)
22
+ {
23
+ const waveChunk = readRIFFChunk(waveListChunk.chunkData);
24
+ this.verifyHeader(waveChunk, "LIST");
25
+ this.verifyText(readBytesAsString(waveChunk.chunkData, 4), "wave");
26
+
27
+ /**
28
+ * @type {RiffChunk[]}
29
+ */
30
+ const waveChunks = [];
31
+ while(waveChunk.chunkData.currentIndex < waveChunk.chunkData.length)
32
+ {
33
+ waveChunks.push(readRIFFChunk(waveChunk.chunkData));
34
+ }
35
+
36
+ const fmtChunk = waveChunks.find(c => c.header === "fmt ");
37
+ if(!fmtChunk)
38
+ {
39
+ throw new Error("No fmt chunk in the wave file!");
40
+ }
41
+ const waveFormat = readLittleEndian(fmtChunk.chunkData, 2);
42
+ if(waveFormat !== 1)
43
+ {
44
+ throw new Error("Only PCM format in WAVE is supported.");
45
+ }
46
+ const channelsAmount = readLittleEndian(fmtChunk.chunkData, 2);
47
+ if(channelsAmount !== 1)
48
+ {
49
+ throw new Error("Only mono samples are supported.");
50
+ }
51
+ const sampleRate = readLittleEndian(fmtChunk.chunkData, 4);
52
+ // skip avg bytes
53
+ readLittleEndian(fmtChunk.chunkData, 4);
54
+ // blockAlign
55
+ readLittleEndian(fmtChunk.chunkData, 2);
56
+ // it's bits per sample because one channel
57
+ const wBitsPerSample = readLittleEndian(fmtChunk.chunkData, 2);
58
+ const bytesPerSample = wBitsPerSample / 8;
59
+
60
+ const maxSampleValue = Math.pow(2, bytesPerSample * 8 - 1); // Max value for the sample
61
+ const maxUnsigned = Math.pow(2, bytesPerSample * 8);
62
+
63
+ let normalizationFactor;
64
+ let isUnsigned = false;
65
+
66
+ if (wBitsPerSample === 8)
67
+ {
68
+ normalizationFactor = 255; // For 8-bit normalize from 0-255
69
+ isUnsigned = true;
70
+ }
71
+ else
72
+ {
73
+ normalizationFactor = maxSampleValue; // For 16-bit normalize from -32768 to 32767
74
+ }
75
+ // read the data
76
+ const dataChunk = waveChunks.find(c => c.header === "data");
77
+ if(!dataChunk)
78
+ {
79
+ throw new Error("No data chunk in the wave chunk!");
80
+ }
81
+ const sampleLength = dataChunk.size / bytesPerSample;
82
+ const sampleData = new Float32Array(sampleLength);
83
+ for (let i = 0; i < sampleData.length; i++)
84
+ {
85
+ // read
86
+ let sample = readLittleEndian(dataChunk.chunkData, bytesPerSample);
87
+ // turn into signed
88
+ if (isUnsigned)
89
+ {
90
+ // normalize unsigned 8-bit sample
91
+ sampleData[i] = (sample / normalizationFactor) - 0.5;
92
+ }
93
+ else
94
+ {
95
+ // normalize signed 16-bit sample
96
+ if (sample >= maxSampleValue)
97
+ {
98
+ sample -= maxUnsigned;
99
+ }
100
+ sampleData[i] = sample / normalizationFactor;
101
+ }
102
+ }
103
+
104
+ // sane defaults
105
+ let sampleKey = 60;
106
+ let samplePitch = 0;
107
+ let sampleLoopStart = 0;
108
+ let sampleLoopEnd = sampleData.length - 1;
109
+
110
+ // read wsmp
111
+ const wsmpChunk = waveChunks.find(c => c.header === "wsmp")
112
+ if(wsmpChunk)
113
+ {
114
+ // skip cbsize
115
+ readLittleEndian(wsmpChunk.chunkData, 4);
116
+ sampleKey = readLittleEndian(wsmpChunk.chunkData, 2);
117
+ // section 1.14.2: Each relative pitch unit represents 1/65536 cents.
118
+ // but that doesn't seem to be true for this one: it's just cents.
119
+ samplePitch = signedInt16(
120
+ wsmpChunk.chunkData[wsmpChunk.chunkData.currentIndex++],
121
+ wsmpChunk.chunkData[wsmpChunk.chunkData.currentIndex++]
122
+ );
123
+ // gain is handled in regions as initialAttenuation
124
+ readLittleEndian(wsmpChunk.chunkData, 4);
125
+ // no idea about ful options
126
+ readLittleEndian(wsmpChunk.chunkData, 4);
127
+ const loopsAmount = readLittleEndian(wsmpChunk.chunkData, 4);
128
+ if(loopsAmount === 1)
129
+ {
130
+ // skip size and type
131
+ readLittleEndian(wsmpChunk.chunkData, 8);
132
+ sampleLoopStart = readLittleEndian(wsmpChunk.chunkData, 4);
133
+ const loopSize = readLittleEndian(wsmpChunk.chunkData, 4);
134
+ sampleLoopEnd = sampleLoopStart + loopSize;
135
+ }
136
+ }
137
+ else
138
+ {
139
+ SpessaSynthWarn("No wsmp chunk in wave... using sane defaults.")
140
+ }
141
+
142
+ // read sample name
143
+ const waveInfo = findRIFFListType(waveChunks, "INFO");
144
+ let sampleName = `Unnamed ${sampleID}`;
145
+ if(waveInfo)
146
+ {
147
+ let infoChunk = readRIFFChunk(waveInfo.chunkData);
148
+ while(infoChunk.header !== "INAM" && waveInfo.chunkData.currentIndex < waveInfo.chunkData.length)
149
+ {
150
+ infoChunk = readRIFFChunk(waveInfo.chunkData);
151
+ }
152
+ if(infoChunk.header === "INAM")
153
+ {
154
+ sampleName = readBytesAsString(infoChunk.chunkData, infoChunk.size).trim();
155
+ }
156
+ }
157
+
158
+ this.samples.push(new DLSSample(
159
+ sampleName,
160
+ sampleRate,
161
+ sampleKey,
162
+ samplePitch,
163
+ sampleLoopStart,
164
+ sampleLength,
165
+ sampleData
166
+ ));
167
+
168
+ sampleID++;
169
+ SpessaSynthInfo(`%cLoaded sample %c${sampleName}`,
170
+ consoleColors.info,
171
+ consoleColors.recognized);
172
+ }
173
+ SpessaSynthGroupEnd();
174
+ }
@@ -0,0 +1,21 @@
1
+ import { IndexedByteArray } from '../utils/indexed_array.js'
2
+ import { readBytesAsString } from '../utils/byte_functions/string.js'
3
+ import { DLSSoundFont } from './dls/dls_soundfont.js'
4
+ import { SoundFont2 } from './soundfont.js'
5
+
6
+ /**
7
+ * Loads a soundfont file
8
+ * @param buffer {ArrayBuffer}
9
+ * @returns {BasicSoundFont}
10
+ */
11
+ export function loadSoundFont(buffer)
12
+ {
13
+ const check = buffer.slice(8, 12);
14
+ const a = new IndexedByteArray(check);
15
+ const id = readBytesAsString(a, 4, undefined, false).toLowerCase();
16
+ if(id === "dls ")
17
+ {
18
+ return new DLSSoundFont(buffer);
19
+ }
20
+ return new SoundFont2(buffer, false);
21
+ }
@@ -149,6 +149,39 @@ generatorLimits[generatorTypes.exclusiveClass] = {min: 0, max: 99999, def: 0};
149
149
  generatorLimits[generatorTypes.overridingRootKey] = {min: 0-1, max: 127, def: -1};
150
150
 
151
151
 
152
+ export class Generator
153
+ {
154
+ /**
155
+ * Constructs a new generator
156
+ * @param type {generatorTypes|number}
157
+ * @param value {number}
158
+ */
159
+ constructor(type = generatorTypes.INVALID, value = 0)
160
+ {
161
+ this.generatorType = type;
162
+ if(value === undefined)
163
+ {
164
+ throw new Error("No value provided.");
165
+ }
166
+ const lim = generatorLimits[type];
167
+ this.generatorValue = Math.round(value);
168
+ if(lim !== undefined)
169
+ {
170
+ this.generatorValue = Math.max(lim.min, Math.min(lim.max, this.generatorValue));
171
+ }
172
+ }
173
+ /**
174
+ * The generator's enum number
175
+ * @type {generatorTypes|number}
176
+ */
177
+ generatorType = generatorTypes.INVALID;
178
+ /**
179
+ * The generator's 16-bit value
180
+ * @type {number}
181
+ */
182
+ generatorValue = 0;
183
+ }
184
+
152
185
  /**
153
186
  * @param generatorType {number}
154
187
  * @param presetGens {Generator[]}
@@ -173,19 +206,21 @@ export function addAndClampGenerator(generatorType, presetGens, instrumentGens)
173
206
  return Math.max(limits.min, Math.min(limits.max, instruValue + presetValue));
174
207
  }
175
208
 
176
-
177
- export class Generator{
209
+ export class ReadGenerator extends Generator
210
+ {
178
211
  /**
179
212
  * Creates a generator
180
213
  * @param dataArray {IndexedByteArray}
181
214
  */
182
- constructor(dataArray) {
215
+ constructor(dataArray)
216
+ {
217
+ super();
183
218
  // 4 bytes:
184
219
  // type, type, type, value
185
220
  const i = dataArray.currentIndex;
186
221
  /**
187
- * @type {generatorTypes}
188
- **/
222
+ * @type {generatorTypes|number}
223
+ */
189
224
  this.generatorType = (dataArray[i + 1] << 8) | dataArray[i];
190
225
  this.generatorValue = signedInt16(dataArray[i + 2], dataArray[i + 3]);
191
226
  dataArray.currentIndex += 4;
@@ -202,7 +237,7 @@ export function readGenerators(generatorChunk)
202
237
  let gens = [];
203
238
  while(generatorChunk.chunkData.length > generatorChunk.chunkData.currentIndex)
204
239
  {
205
- gens.push(new Generator(generatorChunk.chunkData));
240
+ gens.push(new ReadGenerator(generatorChunk.chunkData));
206
241
  }
207
242
  if(gens.length > 1)
208
243
  {
@@ -1,6 +1,6 @@
1
1
  import {RiffChunk} from "../basic_soundfont/riff_chunk.js";
2
2
  import {InstrumentZone} from "./zones.js";
3
- import {readBytesAsUintLittleEndian} from "../../utils/byte_functions/little_endian.js";
3
+ import {readLittleEndian} from "../../utils/byte_functions/little_endian.js";
4
4
  import { readBytesAsString } from '../../utils/byte_functions/string.js'
5
5
  import { BasicInstrument } from '../basic_soundfont/basic_instrument.js'
6
6
 
@@ -19,7 +19,7 @@ export class Instrument extends BasicInstrument
19
19
  {
20
20
  super();
21
21
  this.instrumentName = readBytesAsString(instrumentChunk.chunkData, 20).trim();
22
- this.instrumentZoneIndex = readBytesAsUintLittleEndian(instrumentChunk.chunkData, 2);
22
+ this.instrumentZoneIndex = readLittleEndian(instrumentChunk.chunkData, 2);
23
23
  this.instrumentZonesAmount = 0;
24
24
  }
25
25
 
@@ -1,4 +1,4 @@
1
- import {signedInt16, readBytesAsUintLittleEndian} from "../../utils/byte_functions/little_endian.js";
1
+ import {signedInt16, readLittleEndian} from "../../utils/byte_functions/little_endian.js";
2
2
  import { IndexedByteArray } from '../../utils/indexed_array.js';
3
3
  import { generatorTypes } from './generators.js'
4
4
  import { midiControllers } from '../../midi_parser/midi_message.js'
@@ -15,7 +15,8 @@ export const modulatorSources = {
15
15
  channelPressure: 13,
16
16
  pitchWheel: 14,
17
17
  pitchWheelRange: 16,
18
- link: 127
18
+ link: 127,
19
+
19
20
  }
20
21
 
21
22
  export const modulatorCurveTypes = {
@@ -54,11 +55,11 @@ export class Modulator{
54
55
  }
55
56
  else
56
57
  {
57
- this.modulatorSource = readBytesAsUintLittleEndian(dataArray, 2);
58
- this.modulatorDestination = readBytesAsUintLittleEndian(dataArray, 2);
58
+ this.modulatorSource = readLittleEndian(dataArray, 2);
59
+ this.modulatorDestination = readLittleEndian(dataArray, 2);
59
60
  this.transformAmount = signedInt16(dataArray[dataArray.currentIndex++], dataArray[dataArray.currentIndex++]);
60
- this.modulationSecondarySrc = readBytesAsUintLittleEndian(dataArray, 2);
61
- this.transformType = readBytesAsUintLittleEndian(dataArray, 2);
61
+ this.modulationSecondarySrc = readLittleEndian(dataArray, 2);
62
+ this.transformType = readLittleEndian(dataArray, 2);
62
63
  }
63
64
 
64
65
  if(this.modulatorDestination > 58)
@@ -142,7 +143,7 @@ export class Modulator{
142
143
  }
143
144
  }
144
145
 
145
- function getModSourceEnum(curveType, polarity, direction, isCC, index)
146
+ export function getModSourceEnum(curveType, polarity, direction, isCC, index)
146
147
  {
147
148
  return (curveType << 10) | (polarity << 9) | (direction << 8) | (isCC << 7) | index;
148
149
  }
@@ -189,7 +190,6 @@ export const defaultModulators = [
189
190
  }),
190
191
 
191
192
  // reverb effects to send
192
- // 1000 to align with the reverbSend (overriding it works anyways)
193
193
  new Modulator({srcEnum: 0x00DB, dest: generatorTypes.reverbEffectsSend, amt: 200, secSrcEnum: 0x0, transform: 0}),
194
194
 
195
195
  // chorus effects to send
@@ -1,6 +1,6 @@
1
1
  import {RiffChunk} from "../basic_soundfont/riff_chunk.js";
2
2
  import {PresetZone} from "./zones.js";
3
- import {readBytesAsUintLittleEndian} from "../../utils/byte_functions/little_endian.js";
3
+ import {readLittleEndian} from "../../utils/byte_functions/little_endian.js";
4
4
  import { readBytesAsString } from '../../utils/byte_functions/string.js'
5
5
  import { BasicPreset } from '../basic_soundfont/basic_preset.js'
6
6
 
@@ -21,14 +21,14 @@ export class Preset extends BasicPreset
21
21
  .trim()
22
22
  .replace(/\d{3}:\d{3}/, ""); // remove those pesky "000:001"
23
23
 
24
- this.program = readBytesAsUintLittleEndian(presetChunk.chunkData, 2);
25
- this.bank = readBytesAsUintLittleEndian(presetChunk.chunkData, 2);
26
- this.presetZoneStartIndex = readBytesAsUintLittleEndian(presetChunk.chunkData, 2);
24
+ this.program = readLittleEndian(presetChunk.chunkData, 2);
25
+ this.bank = readLittleEndian(presetChunk.chunkData, 2);
26
+ this.presetZoneStartIndex = readLittleEndian(presetChunk.chunkData, 2);
27
27
 
28
28
  // read the dwords
29
- this.library = readBytesAsUintLittleEndian(presetChunk.chunkData, 4);
30
- this.genre = readBytesAsUintLittleEndian(presetChunk.chunkData, 4);
31
- this.morphology = readBytesAsUintLittleEndian(presetChunk.chunkData, 4);
29
+ this.library = readLittleEndian(presetChunk.chunkData, 4);
30
+ this.genre = readLittleEndian(presetChunk.chunkData, 4);
31
+ this.morphology = readLittleEndian(presetChunk.chunkData, 4);
32
32
  this.presetZonesAmount = 0;
33
33
  }
34
34
 
@@ -1,6 +1,6 @@
1
1
  import { RiffChunk } from '../basic_soundfont/riff_chunk.js'
2
2
  import { IndexedByteArray } from '../../utils/indexed_array.js'
3
- import { readBytesAsUintLittleEndian, signedInt8 } from '../../utils/byte_functions/little_endian.js'
3
+ import { readLittleEndian, signedInt8 } from '../../utils/byte_functions/little_endian.js'
4
4
  import { stbvorbis } from '../../externals/stbvorbis_sync/stbvorbis_sync.min.js'
5
5
  import { SpessaSynthWarn } from '../../utils/loggin.js'
6
6
  import { readBytesAsString } from '../../utils/byte_functions/string.js'
@@ -239,19 +239,19 @@ function readSample(index, sampleHeaderData, smplArrayData, isDataRaw) {
239
239
  let sampleName = readBytesAsString(sampleHeaderData, 20);
240
240
 
241
241
  // read the sample start index
242
- let sampleStartIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
242
+ let sampleStartIndex = readLittleEndian(sampleHeaderData, 4) * 2;
243
243
 
244
244
  // read the sample end index
245
- let sampleEndIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
245
+ let sampleEndIndex = readLittleEndian(sampleHeaderData, 4) * 2;
246
246
 
247
247
  // read the sample looping start index
248
- let sampleLoopStartIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
248
+ let sampleLoopStartIndex = readLittleEndian(sampleHeaderData, 4) * 2;
249
249
 
250
250
  // read the sample looping end index
251
- let sampleLoopEndIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
251
+ let sampleLoopEndIndex = readLittleEndian(sampleHeaderData, 4) * 2;
252
252
 
253
253
  // read the sample rate
254
- let sampleRate = readBytesAsUintLittleEndian(sampleHeaderData, 4);
254
+ let sampleRate = readLittleEndian(sampleHeaderData, 4);
255
255
 
256
256
  // read the original sample pitch
257
257
  let samplePitch = sampleHeaderData[sampleHeaderData.currentIndex++];
@@ -266,8 +266,8 @@ function readSample(index, sampleHeaderData, smplArrayData, isDataRaw) {
266
266
 
267
267
 
268
268
  // read the link to the other channel
269
- let sampleLink = readBytesAsUintLittleEndian(sampleHeaderData, 2);
270
- let sampleType = readBytesAsUintLittleEndian(sampleHeaderData, 2);
269
+ let sampleLink = readLittleEndian(sampleHeaderData, 2);
270
+ let sampleType = readLittleEndian(sampleHeaderData, 2);
271
271
 
272
272
 
273
273
 
@@ -1,4 +1,4 @@
1
- import {readBytesAsUintLittleEndian} from "../../utils/byte_functions/little_endian.js";
1
+ import {readLittleEndian} from "../../utils/byte_functions/little_endian.js";
2
2
  import {IndexedByteArray} from "../../utils/indexed_array.js";
3
3
  import {RiffChunk} from "../basic_soundfont/riff_chunk.js";
4
4
  import {Generator, generatorTypes} from "./generators.js";
@@ -20,8 +20,8 @@ export class InstrumentZone extends BasicInstrumentZone
20
20
  constructor(dataArray)
21
21
  {
22
22
  super();
23
- this.generatorZoneStartIndex = readBytesAsUintLittleEndian(dataArray, 2);
24
- this.modulatorZoneStartIndex = readBytesAsUintLittleEndian(dataArray, 2);
23
+ this.generatorZoneStartIndex = readLittleEndian(dataArray, 2);
24
+ this.modulatorZoneStartIndex = readLittleEndian(dataArray, 2);
25
25
  this.modulatorZoneSize = 0;
26
26
  this.generatorZoneSize = 0;
27
27
  this.isGlobal = true;
@@ -146,8 +146,8 @@ export class PresetZone extends BasicPresetZone
146
146
  constructor(dataArray)
147
147
  {
148
148
  super();
149
- this.generatorZoneStartIndex = readBytesAsUintLittleEndian(dataArray, 2);
150
- this.modulatorZoneStartIndex = readBytesAsUintLittleEndian(dataArray, 2);
149
+ this.generatorZoneStartIndex = readLittleEndian(dataArray, 2);
150
+ this.modulatorZoneStartIndex = readLittleEndian(dataArray, 2);
151
151
  this.modulatorZoneSize = 0;
152
152
  this.generatorZoneSize = 0;
153
153
  this.isGlobal = true;
@@ -1,6 +1,6 @@
1
1
  import { IndexedByteArray } from '../utils/indexed_array.js'
2
2
  import {readSamples} from "./read_sf2/samples.js";
3
- import { readBytesAsUintLittleEndian } from '../utils/byte_functions/little_endian.js'
3
+ import { readLittleEndian } from '../utils/byte_functions/little_endian.js'
4
4
  import { readGenerators, Generator } from './read_sf2/generators.js'
5
5
  import {readInstrumentZones, InstrumentZone, readPresetZones} from "./read_sf2/zones.js";
6
6
  import { readPresets } from "./read_sf2/presets.js";
@@ -23,10 +23,15 @@ export class SoundFont2 extends BasicSoundFont
23
23
  /**
24
24
  * Initializes a new SoundFont2 Parser and parses the given data array
25
25
  * @param arrayBuffer {ArrayBuffer}
26
+ * @param warnDeprecated {boolean}
26
27
  */
27
- constructor(arrayBuffer)
28
+ constructor(arrayBuffer, warnDeprecated = true)
28
29
  {
29
30
  super();
31
+ if(warnDeprecated)
32
+ {
33
+ console.warn("Using the constructor directly is deprecated. Use loadSoundFont instead.");
34
+ }
30
35
  this.dataArray = new IndexedByteArray(arrayBuffer);
31
36
  SpessaSynthGroup("%cParsing SoundFont...", consoleColors.info);
32
37
  if(!this.dataArray)
@@ -66,7 +71,7 @@ export class SoundFont2 extends BasicSoundFont
66
71
  {
67
72
  case "ifil":
68
73
  case "iver":
69
- text = `${readBytesAsUintLittleEndian(chunk.chunkData, 2)}.${readBytesAsUintLittleEndian(chunk.chunkData, 2)}`;
74
+ text = `${readLittleEndian(chunk.chunkData, 2)}.${readLittleEndian(chunk.chunkData, 2)}`;
70
75
  break;
71
76
 
72
77
  case "icmt":
@@ -21,7 +21,7 @@ import { SoundfontManager } from './synth_soundfont_manager.js'
21
21
 
22
22
  /**
23
23
  * @typedef {Object} StartRenderingDataConfig
24
- * @property {MIDI} parsedMIDI - the MIDI to render
24
+ * @property {BasicMIDI} parsedMIDI - the MIDI to render
25
25
  * @property {SynthesizerSnapshot} snapshot - the snapshot to apply
26
26
  * @property {boolean|undefined} oneOutput - if synth should use one output with 32 channels (2 audio channels for each midi channel). this disables chorus and reverb.
27
27
  */