spessasynth_core 3.26.28 → 3.26.30

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 (26) hide show
  1. package/package.json +1 -1
  2. package/src/soundfont/basic_soundfont/basic_instrument.js +16 -1
  3. package/src/soundfont/basic_soundfont/basic_instrument_zone.js +1 -1
  4. package/src/soundfont/basic_soundfont/basic_sample.js +39 -17
  5. package/src/soundfont/basic_soundfont/basic_soundbank.js +3 -3
  6. package/src/soundfont/basic_soundfont/riff_chunk.js +4 -1
  7. package/src/soundfont/basic_soundfont/write_dls/wave.js +1 -1
  8. package/src/soundfont/basic_soundfont/write_sf2/ibag.js +28 -10
  9. package/src/soundfont/basic_soundfont/write_sf2/igen.js +26 -11
  10. package/src/soundfont/basic_soundfont/write_sf2/imod.js +28 -14
  11. package/src/soundfont/basic_soundfont/write_sf2/inst.js +28 -10
  12. package/src/soundfont/basic_soundfont/write_sf2/pbag.js +26 -11
  13. package/src/soundfont/basic_soundfont/write_sf2/pgen.js +25 -11
  14. package/src/soundfont/basic_soundfont/write_sf2/phdr.js +45 -20
  15. package/src/soundfont/basic_soundfont/write_sf2/pmod.js +28 -14
  16. package/src/soundfont/basic_soundfont/write_sf2/shdr.js +28 -5
  17. package/src/soundfont/basic_soundfont/write_sf2/write.js +53 -14
  18. package/src/soundfont/dls/dls_sample.js +179 -18
  19. package/src/soundfont/dls/read_samples.js +7 -123
  20. package/src/soundfont/read_sf2/instrument_zones.js +4 -17
  21. package/src/soundfont/read_sf2/instruments.js +1 -1
  22. package/src/soundfont/read_sf2/preset_zones.js +6 -19
  23. package/src/soundfont/read_sf2/presets.js +0 -1
  24. package/src/soundfont/read_sf2/samples.js +121 -103
  25. package/src/soundfont/read_sf2/soundfont.js +198 -56
  26. package/src/soundfont/read_sf2/zones.js +28 -0
@@ -10,101 +10,6 @@ import { consoleColors } from "../../utils/other.js";
10
10
  import { readLittleEndian, signedInt16 } from "../../utils/byte_functions/little_endian.js";
11
11
  import { DLSSample } from "./dls_sample.js";
12
12
 
13
- const W_FORMAT_TAG = {
14
- PCM: 0x01,
15
- ALAW: 0x6
16
- };
17
-
18
- /**
19
- * @param dataChunk {RiffChunk}
20
- * @param bytesPerSample {number}
21
- * @returns {Float32Array}
22
- */
23
- function readPCM(dataChunk, bytesPerSample)
24
- {
25
- const maxSampleValue = Math.pow(2, bytesPerSample * 8 - 1); // Max value for the sample
26
- const maxUnsigned = Math.pow(2, bytesPerSample * 8);
27
-
28
- let normalizationFactor;
29
- let isUnsigned = false;
30
-
31
- if (bytesPerSample === 1)
32
- {
33
- normalizationFactor = 255; // For 8-bit normalize from 0-255
34
- isUnsigned = true;
35
- }
36
- else
37
- {
38
- normalizationFactor = maxSampleValue; // For 16-bit normalize from -32,768 to 32,767
39
- }
40
- const sampleLength = dataChunk.size / bytesPerSample;
41
- const sampleData = new Float32Array(sampleLength);
42
- for (let i = 0; i < sampleData.length; i++)
43
- {
44
- // read
45
- let sample = readLittleEndian(dataChunk.chunkData, bytesPerSample);
46
- // turn into signed
47
- if (isUnsigned)
48
- {
49
- // normalize unsigned 8-bit sample
50
- sampleData[i] = (sample / normalizationFactor) - 0.5;
51
- }
52
- else
53
- {
54
- // normalize signed 16-bit sample
55
- if (sample >= maxSampleValue)
56
- {
57
- sample -= maxUnsigned;
58
- }
59
- sampleData[i] = sample / normalizationFactor;
60
- }
61
- }
62
- return sampleData;
63
- }
64
-
65
- /**
66
- * @param dataChunk {RiffChunk}
67
- * @param bytesPerSample {number}
68
- * @returns {Float32Array}
69
- */
70
- function readALAW(dataChunk, bytesPerSample)
71
- {
72
- const sampleLength = dataChunk.size / bytesPerSample;
73
- const sampleData = new Float32Array(sampleLength);
74
- for (let i = 0; i < sampleData.length; i++)
75
- {
76
- // read
77
- const input = readLittleEndian(dataChunk.chunkData, bytesPerSample);
78
-
79
- // https://en.wikipedia.org/wiki/G.711#A-law
80
- // re-toggle toggled bits
81
- let sample = input ^ 0x55;
82
-
83
- // remove sign bit
84
- sample &= 0x7F;
85
-
86
- // extract exponent
87
- let exponent = sample >> 4;
88
- // extract mantissa
89
- let mantissa = sample & 0xF;
90
- if (exponent > 0)
91
- {
92
- mantissa += 16; // add leading '1', if exponent > 0
93
- }
94
-
95
- mantissa = (mantissa << 4) + 0x8;
96
- if (exponent > 1)
97
- {
98
- mantissa = mantissa << (exponent - 1);
99
- }
100
-
101
- const s16sample = input > 127 ? mantissa : -mantissa;
102
-
103
- // convert to float
104
- sampleData[i] = s16sample / 32678;
105
- }
106
- return sampleData;
107
- }
108
13
 
109
14
  /**
110
15
  * @this {DLSSoundFont}
@@ -138,7 +43,7 @@ export function readDLSSamples(waveListChunk)
138
43
  throw new Error("No fmt chunk in the wave file!");
139
44
  }
140
45
  // https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.14393.0/shared/mmreg.h#L2108
141
- const waveFormat = readLittleEndian(fmtChunk.chunkData, 2);
46
+ const wFormatTag = readLittleEndian(fmtChunk.chunkData, 2);
142
47
  const channelsAmount = readLittleEndian(fmtChunk.chunkData, 2);
143
48
  if (channelsAmount !== 1)
144
49
  {
@@ -153,30 +58,11 @@ export function readDLSSamples(waveListChunk)
153
58
  const wBitsPerSample = readLittleEndian(fmtChunk.chunkData, 2);
154
59
  const bytesPerSample = wBitsPerSample / 8;
155
60
 
156
- // read the data
157
- let failed = false;
158
61
  const dataChunk = waveChunks.find(c => c.header === "data");
159
62
  if (!dataChunk)
160
63
  {
161
64
  this.parsingError("No data chunk in the WAVE chunk!");
162
65
  }
163
- let sampleData;
164
- switch (waveFormat)
165
- {
166
- default:
167
- failed = true;
168
- sampleData = new Float32Array(dataChunk.size / bytesPerSample);
169
- break;
170
-
171
- case W_FORMAT_TAG.PCM:
172
- sampleData = readPCM(dataChunk, bytesPerSample);
173
- break;
174
-
175
- case W_FORMAT_TAG.ALAW:
176
- sampleData = readALAW(dataChunk, bytesPerSample);
177
- break;
178
-
179
- }
180
66
 
181
67
  // read sample name
182
68
  const waveInfo = findRIFFListType(waveChunks, "INFO");
@@ -198,7 +84,8 @@ export function readDLSSamples(waveListChunk)
198
84
  let sampleKey = 60;
199
85
  let samplePitch = 0;
200
86
  let sampleLoopStart = 0;
201
- let sampleLoopEnd = sampleData.length - 1;
87
+ const sampleLength = dataChunk.size / bytesPerSample;
88
+ let sampleLoopEnd = sampleLength - 1;
202
89
  let sampleDbAttenuation = 0;
203
90
 
204
91
  // read wsmp
@@ -242,11 +129,6 @@ export function readDLSSamples(waveListChunk)
242
129
  SpessaSynthWarn("No wsmp chunk in wave... using sane defaults.");
243
130
  }
244
131
 
245
- if (failed)
246
- {
247
- console.error(`Failed to load '${sampleName}': Unsupported format: (${waveFormat})`);
248
- }
249
-
250
132
  this.samples.push(new DLSSample(
251
133
  sampleName,
252
134
  sampleRate,
@@ -254,8 +136,10 @@ export function readDLSSamples(waveListChunk)
254
136
  samplePitch,
255
137
  sampleLoopStart,
256
138
  sampleLoopEnd,
257
- sampleData,
258
- sampleDbAttenuation
139
+ sampleDbAttenuation,
140
+ dataChunk,
141
+ wFormatTag,
142
+ bytesPerSample
259
143
  ));
260
144
 
261
145
 
@@ -4,7 +4,6 @@
4
4
  */
5
5
  import { BasicInstrumentZone } from "../basic_soundfont/basic_instrument_zone.js";
6
6
  import { generatorTypes } from "../basic_soundfont/generator_types.js";
7
- import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
8
7
 
9
8
  export class InstrumentZone extends BasicInstrumentZone
10
9
  {
@@ -33,28 +32,16 @@ export class InstrumentZone extends BasicInstrumentZone
33
32
 
34
33
  /**
35
34
  * Reads the given instrument zone
36
- * @param zonesChunk {RiffChunk}
35
+ * @param indexes {{mod: number[], gen: number[]}}
37
36
  * @param instrumentGenerators {Generator[]}
38
37
  * @param instrumentModulators {Modulator[]}
39
38
  * @param samples {BasicSample[]}
40
39
  * @param instruments {Instrument[]}
41
40
  */
42
- export function readInstrumentZones(zonesChunk, instrumentGenerators, instrumentModulators, samples, instruments)
41
+ export function applyInstrumentZones(indexes, instrumentGenerators, instrumentModulators, samples, instruments)
43
42
  {
44
- /**
45
- * @type {number[]}
46
- */
47
- const modStartIndexes = [];
48
- /**
49
- * @type {number[]}
50
- */
51
- const genStartIndexes = [];
52
-
53
- while (zonesChunk.chunkData.length > zonesChunk.chunkData.currentIndex)
54
- {
55
- genStartIndexes.push(readLittleEndian(zonesChunk.chunkData, 2));
56
- modStartIndexes.push(readLittleEndian(zonesChunk.chunkData, 2));
57
- }
43
+ const genStartIndexes = indexes.gen;
44
+ const modStartIndexes = indexes.mod;
58
45
 
59
46
  let modIndex = 0;
60
47
  let genIndex = 0;
@@ -28,7 +28,7 @@ export class Instrument extends BasicInstrument
28
28
  constructor(instrumentChunk)
29
29
  {
30
30
  super();
31
- this.instrumentName = readBytesAsString(instrumentChunk.chunkData, 20).trim();
31
+ this.instrumentName = readBytesAsString(instrumentChunk.chunkData, 20);
32
32
  this.zoneStartIndex = readLittleEndian(instrumentChunk.chunkData, 2);
33
33
  }
34
34
 
@@ -1,5 +1,3 @@
1
- import { readLittleEndian } from "../../utils/byte_functions/little_endian.js";
2
- import { RiffChunk } from "../basic_soundfont/riff_chunk.js";
3
1
  import { BasicPresetZone } from "../basic_soundfont/basic_preset_zone.js";
4
2
  import { Generator } from "../basic_soundfont/generator.js";
5
3
  import { Modulator } from "../basic_soundfont/modulator.js";
@@ -35,30 +33,19 @@ export class PresetZone extends BasicPresetZone
35
33
  }
36
34
  }
37
35
 
36
+
38
37
  /**
39
- * Reads the given preset zone read
40
- * @param zonesChunk {RiffChunk}
38
+ * Reads the given preset zone
39
+ * @param indexes {{mod: number[], gen: number[]}}
41
40
  * @param presetGens {Generator[]}
42
41
  * @param instruments {BasicInstrument[]}
43
42
  * @param presetMods {Modulator[]}
44
43
  * @param presets {Preset[]}
45
44
  */
46
- export function readPresetZones(zonesChunk, presetGens, presetMods, instruments, presets)
45
+ export function applyPresetZones(indexes, presetGens, presetMods, instruments, presets)
47
46
  {
48
- /**
49
- * @type {number[]}
50
- */
51
- const modStartIndexes = [];
52
- /**
53
- * @type {number[]}
54
- */
55
- const genStartIndexes = [];
56
-
57
- while (zonesChunk.chunkData.length > zonesChunk.chunkData.currentIndex)
58
- {
59
- genStartIndexes.push(readLittleEndian(zonesChunk.chunkData, 2));
60
- modStartIndexes.push(readLittleEndian(zonesChunk.chunkData, 2));
61
- }
47
+ const genStartIndexes = indexes.gen;
48
+ const modStartIndexes = indexes.mod;
62
49
 
63
50
  let modIndex = 0;
64
51
  let genIndex = 0;
@@ -29,7 +29,6 @@ export class Preset extends BasicPreset
29
29
  {
30
30
  super(sf2);
31
31
  this.presetName = readBytesAsString(presetChunk.chunkData, 20)
32
- .trim()
33
32
  .replace(/\d{3}:\d{3}/, ""); // remove those pesky "000:001"
34
33
 
35
34
  this.program = readLittleEndian(presetChunk.chunkData, 2);
@@ -4,7 +4,7 @@ import { readLittleEndian, signedInt8 } from "../../utils/byte_functions/little_
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";
7
- import { BasicSample } from "../basic_soundfont/basic_sample.js";
7
+ import { BasicSample, sampleTypes } from "../basic_soundfont/basic_sample.js";
8
8
 
9
9
  export const SF3_BIT_FLIT = 0x10;
10
10
 
@@ -16,6 +16,23 @@ export class SoundFontSample extends BasicSample
16
16
  */
17
17
  linkedSampleIndex;
18
18
 
19
+ /**
20
+ * The handle to the core sf2 file for dynamic sample reading
21
+ * @type {Uint8Array}
22
+ */
23
+ sf2FileArrayHandle;
24
+
25
+ /**
26
+ * Start index of the sample in the file byte array
27
+ * @type {number}
28
+ */
29
+ s16leStart = 0;
30
+ /**
31
+ * End index of the sample in the file byte array
32
+ * @type {number}
33
+ */
34
+ s16leEnd = 0;
35
+
19
36
  /**
20
37
  * Creates a sample
21
38
  * @param sampleName {string}
@@ -28,9 +45,8 @@ export class SoundFontSample extends BasicSample
28
45
  * @param samplePitchCorrection {number}
29
46
  * @param linkedSampleIndex {number}
30
47
  * @param sampleType {number}
31
- * @param smplArr {IndexedByteArray|Float32Array}
48
+ * @param sampleDataArray {IndexedByteArray|Float32Array}
32
49
  * @param sampleIndex {number} initial sample index when loading the sfont
33
- * @param isDataRaw {boolean} if false, the data is decoded as float32.
34
50
  * Used for SF2Pack support
35
51
  */
36
52
  constructor(
@@ -44,9 +60,8 @@ export class SoundFontSample extends BasicSample
44
60
  samplePitchCorrection,
45
61
  linkedSampleIndex,
46
62
  sampleType,
47
- smplArr,
48
- sampleIndex,
49
- isDataRaw
63
+ sampleDataArray,
64
+ sampleIndex
50
65
  )
51
66
  {
52
67
  // read sf3
@@ -68,20 +83,47 @@ export class SoundFontSample extends BasicSample
68
83
  // in bytes
69
84
  this.sampleStartIndex = sampleStartIndex;
70
85
  this.sampleEndIndex = sampleEndIndex;
71
- this.isSampleLoaded = false;
72
86
  this.sampleID = sampleIndex;
73
87
  // in bytes
74
88
  this.sampleLength = this.sampleEndIndex - this.sampleStartIndex;
75
- this.sampleDataArray = smplArr;
76
- this.sampleData = new Float32Array(0);
89
+ const smplStart = sampleDataArray.currentIndex;
90
+
91
+ // three data types in:
92
+ // SF2 (s16le)
93
+ // SF3 (vorbis)
94
+ // SF2Pack (
77
95
  if (this.isCompressed)
78
96
  {
79
97
  // correct loop points
80
98
  this.sampleLoopStartIndex += this.sampleStartIndex / 2;
81
99
  this.sampleLoopEndIndex += this.sampleStartIndex / 2;
82
100
  this.sampleLength = 99999999; // set to 999,999 before we decode it
101
+
102
+ // copy the compressed data, it can be preserved during writing
103
+ this.compressedData = sampleDataArray.slice(
104
+ this.sampleStartIndex / 2 + smplStart,
105
+ this.sampleEndIndex / 2 + smplStart
106
+ );
107
+ }
108
+ else
109
+ {
110
+ if (sampleDataArray instanceof Float32Array)
111
+ {
112
+ // float32 array from SF2pack, copy directly
113
+ this.sampleData = sampleDataArray.slice(
114
+ this.sampleStartIndex / 2,
115
+ this.sampleEndIndex / 2
116
+ );
117
+ }
118
+ else
119
+ {
120
+ // regular sf2 s16le
121
+ this.s16leStart = smplStart + this.sampleStartIndex;
122
+ this.s16leEnd = smplStart + this.sampleEndIndex;
123
+ this.sf2FileArrayHandle = sampleDataArray;
124
+ }
125
+
83
126
  }
84
- this.isDataRaw = isDataRaw;
85
127
  this.linkedSampleIndex = linkedSampleIndex;
86
128
  }
87
129
 
@@ -94,70 +136,62 @@ export class SoundFontSample extends BasicSample
94
136
  {
95
137
  return;
96
138
  }
97
- this.setLinkedSample(samplesArray[this.linkedSampleIndex], this.sampleType);
98
- }
99
-
100
- /**
101
- * Get raw data, whether it's compressed or not as we simply write it to the file
102
- * @return {Uint8Array} either s16 or vorbis data
103
- */
104
- getRawData()
105
- {
106
- const smplArr = this.sampleDataArray;
107
- if (this.isCompressed)
139
+ const linkedSample = samplesArray[this.linkedSampleIndex];
140
+ if (!linkedSample)
108
141
  {
109
- if (this.compressedData)
110
- {
111
- return this.compressedData;
112
- }
113
- const smplStart = smplArr.currentIndex;
114
- return smplArr.slice(this.sampleStartIndex / 2 + smplStart, this.sampleEndIndex / 2 + smplStart);
142
+ SpessaSynthWarn(`Invalid linked sample for ${this.sampleName}. Setting to mono.`);
143
+ this.setSampleType(sampleTypes.monoSample);
115
144
  }
116
145
  else
117
146
  {
118
- if (!this.isDataRaw)
119
- {
120
- // encode the f32 into s16 manually
121
- super.getRawData();
122
- }
123
- const dataStartIndex = smplArr.currentIndex;
124
- return smplArr.slice(dataStartIndex + this.sampleStartIndex, dataStartIndex + this.sampleEndIndex);
147
+ this.setLinkedSample(samplesArray[this.linkedSampleIndex], this.sampleType);
125
148
  }
126
149
  }
127
150
 
128
151
  /**
152
+ * @private
129
153
  * Decode binary vorbis into a float32 pcm
154
+ * @returns {Float32Array}
130
155
  */
131
156
  decodeVorbis()
132
157
  {
158
+ if (this.sampleData)
159
+ {
160
+ return this.sampleData;
161
+ }
133
162
  if (this.sampleLength < 1)
134
163
  {
135
164
  // eos, do not do anything
136
- return;
165
+ return new Float32Array(0);
137
166
  }
138
167
  // get the compressed byte stream
139
- const smplArr = this.sampleDataArray;
140
- const smplStart = smplArr.currentIndex;
141
- const buff = smplArr.slice(this.sampleStartIndex / 2 + smplStart, this.sampleEndIndex / 2 + smplStart);
142
168
  // reset array and being decoding
143
- this.sampleData = new Float32Array(0);
144
169
  try
145
170
  {
146
171
  /**
147
172
  * @type {{data: Float32Array[], error: (string|null), sampleRate: number, eof: boolean}}
148
173
  */
149
- const vorbis = stbvorbis.decode(buff.buffer);
150
- this.sampleData = vorbis.data[0];
151
- if (this.sampleData === undefined)
174
+ const vorbis = stbvorbis.decode(this.compressedData);
175
+ const decoded = vorbis.data[0];
176
+ if (decoded === undefined)
152
177
  {
153
178
  SpessaSynthWarn(`Error decoding sample ${this.sampleName}: Vorbis decode returned undefined.`);
179
+ return new Float32Array(0);
154
180
  }
181
+ // clip
182
+ // because vorbis can go above 1 sometimes
183
+ for (let i = 0; i < decoded.length; i++)
184
+ {
185
+ // magic number is 32,767 / 32,768
186
+ decoded[i] = Math.max(-1, Math.min(decoded[i], 0.999969482421875));
187
+ }
188
+ return decoded;
155
189
  }
156
190
  catch (e)
157
191
  {
158
192
  // do not error out, fill with silence
159
193
  SpessaSynthWarn(`Error decoding sample ${this.sampleName}: ${e}`);
160
- this.sampleData = new Float32Array(this.sampleLoopEndIndex + 1);
194
+ return new Float32Array(this.sampleLoopEndIndex + 1);
161
195
  }
162
196
  }
163
197
 
@@ -167,8 +201,6 @@ export class SoundFontSample extends BasicSample
167
201
  setAudioData(audioData)
168
202
  {
169
203
  super.setAudioData(audioData);
170
- this.isSampleLoaded = true;
171
- this.isDataRaw = false;
172
204
  }
173
205
 
174
206
  /**
@@ -177,48 +209,31 @@ export class SoundFontSample extends BasicSample
177
209
  */
178
210
  getAudioData()
179
211
  {
180
- if (!this.isSampleLoaded)
212
+ if (this.sampleData)
181
213
  {
182
- // start loading data if it is not loaded
183
- if (this.sampleLength < 1)
184
- {
185
- SpessaSynthWarn(`Invalid sample ${this.sampleName}! Invalid length: ${this.sampleLength}`);
186
- return new Float32Array(1);
187
- }
188
-
189
- if (this.isCompressed)
190
- {
191
- // if compressed, decode
192
- this.decodeVorbis();
193
- this.isSampleLoaded = true;
194
- return this.sampleData;
195
- }
196
- else if (!this.isDataRaw)
197
- {
198
- return this.getUncompressedReadyData();
199
- }
200
- return this.loadUncompressedData();
214
+ return this.sampleData;
201
215
  }
202
- return this.sampleData;
203
- }
204
-
205
- /**
206
- * @returns {Float32Array}
207
- */
208
- loadUncompressedData()
209
- {
210
- if (this.isCompressed)
216
+ // SF2Pack is decoded during load time
217
+
218
+ // start loading data if it is not loaded
219
+ if (this.sampleLength < 1)
211
220
  {
212
- SpessaSynthWarn("Trying to load a compressed sample via loadUncompressedData()... aborting!");
213
- return new Float32Array(0);
221
+ SpessaSynthWarn(`Invalid sample ${this.sampleName}! Invalid length: ${this.sampleLength}`);
222
+ return new Float32Array(1);
214
223
  }
215
224
 
225
+ if (this.isCompressed)
226
+ {
227
+ // SF3
228
+ // if compressed, decode
229
+ this.sampleData = this.decodeVorbis();
230
+ return this.sampleData;
231
+ }
232
+ // SF2
216
233
  // read the sample data
217
234
  let audioData = new Float32Array(this.sampleLength / 2);
218
- const dataStartIndex = this.sampleDataArray.currentIndex;
219
235
  let convertedSigned16 = new Int16Array(
220
- this.sampleDataArray.slice(dataStartIndex + this.sampleStartIndex, dataStartIndex + this.sampleEndIndex)
221
- .buffer
236
+ this.sf2FileArrayHandle.buffer.slice(this.s16leStart, this.s16leEnd)
222
237
  );
223
238
 
224
239
  // convert to float
@@ -228,26 +243,28 @@ export class SoundFontSample extends BasicSample
228
243
  }
229
244
 
230
245
  this.sampleData = audioData;
231
- this.isSampleLoaded = true;
232
246
  return audioData;
247
+
233
248
  }
234
249
 
235
250
  /**
236
- * @returns {Float32Array}
251
+ * @param allowVorbis
252
+ * @returns {Uint8Array}
237
253
  */
238
- getUncompressedReadyData()
254
+ getRawData(allowVorbis = true)
239
255
  {
240
- /**
241
- * read the sample data
242
- * @type {Float32Array}
243
- */
244
- let audioData = /**@type {Float32Array}*/ this.sampleDataArray.slice(
245
- this.sampleStartIndex / 2,
246
- this.sampleEndIndex / 2
247
- );
248
- this.sampleData = audioData;
249
- this.isSampleLoaded = true;
250
- return audioData;
256
+ if (this.dataOverriden)
257
+ {
258
+ return this.encodeS16LE();
259
+ }
260
+ else
261
+ {
262
+ if (this.compressedData && allowVorbis)
263
+ {
264
+ return this.compressedData;
265
+ }
266
+ return this.sf2FileArrayHandle.slice(this.s16leStart, this.s16leEnd);
267
+ }
251
268
  }
252
269
  }
253
270
 
@@ -255,10 +272,10 @@ export class SoundFontSample extends BasicSample
255
272
  * Reads the generatorTranslator from the shdr read
256
273
  * @param sampleHeadersChunk {RiffChunk}
257
274
  * @param smplChunkData {IndexedByteArray|Float32Array}
258
- * @param isSmplDataRaw {boolean}
275
+ * @param linkSamples {boolean}
259
276
  * @returns {SoundFontSample[]}
260
277
  */
261
- export function readSamples(sampleHeadersChunk, smplChunkData, isSmplDataRaw = true)
278
+ export function readSamples(sampleHeadersChunk, smplChunkData, linkSamples = true)
262
279
  {
263
280
  /**
264
281
  * @type {SoundFontSample[]}
@@ -267,7 +284,7 @@ export function readSamples(sampleHeadersChunk, smplChunkData, isSmplDataRaw = t
267
284
  let index = 0;
268
285
  while (sampleHeadersChunk.chunkData.length > sampleHeadersChunk.chunkData.currentIndex)
269
286
  {
270
- const sample = readSample(index, sampleHeadersChunk.chunkData, smplChunkData, isSmplDataRaw);
287
+ const sample = readSample(index, sampleHeadersChunk.chunkData, smplChunkData);
271
288
  samples.push(sample);
272
289
  index++;
273
290
  }
@@ -275,7 +292,10 @@ export function readSamples(sampleHeadersChunk, smplChunkData, isSmplDataRaw = t
275
292
  samples.pop();
276
293
 
277
294
  // link samples
278
- samples.forEach(s => s.getLinkedSample(samples));
295
+ if (linkSamples)
296
+ {
297
+ samples.forEach(s => s.getLinkedSample(samples));
298
+ }
279
299
 
280
300
  return samples;
281
301
  }
@@ -285,10 +305,9 @@ export function readSamples(sampleHeadersChunk, smplChunkData, isSmplDataRaw = t
285
305
  * @param index {number}
286
306
  * @param sampleHeaderData {IndexedByteArray}
287
307
  * @param smplArrayData {IndexedByteArray|Float32Array}
288
- * @param isDataRaw {boolean} true means binary 16-bit data, false means float32
289
308
  * @returns {SoundFontSample}
290
309
  */
291
- function readSample(index, sampleHeaderData, smplArrayData, isDataRaw)
310
+ function readSample(index, sampleHeaderData, smplArrayData)
292
311
  {
293
312
 
294
313
  // read the sample name
@@ -311,9 +330,9 @@ function readSample(index, sampleHeaderData, smplArrayData, isDataRaw)
311
330
 
312
331
  // read the original sample pitch
313
332
  let samplePitch = sampleHeaderData[sampleHeaderData.currentIndex++];
314
- if (samplePitch === 255)
333
+ if (samplePitch > 127)
315
334
  {
316
- // if it's 255, then default to 60
335
+ // if it's out of range, then default to 60
317
336
  samplePitch = 60;
318
337
  }
319
338
 
@@ -338,7 +357,6 @@ function readSample(index, sampleHeaderData, smplArrayData, isDataRaw)
338
357
  sampleLink,
339
358
  sampleType,
340
359
  smplArrayData,
341
- index,
342
- isDataRaw
360
+ index
343
361
  );
344
362
  }