spessasynth_lib 0.0.1

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 (154) hide show
  1. package/.idea/modules.xml +8 -0
  2. package/.idea/spessasynth_lib.iml +12 -0
  3. package/.idea/vcs.xml +6 -0
  4. package/copy_version.sh +38 -0
  5. package/index.js +73 -0
  6. package/package/@types/externals/stbvorbis_sync/stbvorbis_sync.min.d.ts +1 -0
  7. package/package/@types/index.d.ts +34 -0
  8. package/package/@types/midi_handler/midi_handler.d.ts +39 -0
  9. package/package/@types/midi_handler/web_midi_link.d.ts +12 -0
  10. package/package/@types/midi_parser/midi_data.d.ts +95 -0
  11. package/package/@types/midi_parser/midi_editor.d.ts +45 -0
  12. package/package/@types/midi_parser/midi_loader.d.ts +100 -0
  13. package/package/@types/midi_parser/midi_message.d.ts +154 -0
  14. package/package/@types/midi_parser/midi_writer.d.ts +6 -0
  15. package/package/@types/midi_parser/rmidi_writer.d.ts +9 -0
  16. package/package/@types/midi_parser/used_keys_loaded.d.ts +7 -0
  17. package/package/@types/sequencer/sequencer.d.ts +180 -0
  18. package/package/@types/sequencer/worklet_sequencer/sequencer_message.d.ts +28 -0
  19. package/package/@types/soundfont/read/generators.d.ts +98 -0
  20. package/package/@types/soundfont/read/instruments.d.ts +50 -0
  21. package/package/@types/soundfont/read/modulators.d.ts +73 -0
  22. package/package/@types/soundfont/read/presets.d.ts +87 -0
  23. package/package/@types/soundfont/read/riff_chunk.d.ts +31 -0
  24. package/package/@types/soundfont/read/samples.d.ts +134 -0
  25. package/package/@types/soundfont/read/zones.d.ts +141 -0
  26. package/package/@types/soundfont/soundfont.d.ts +76 -0
  27. package/package/@types/soundfont/write/ibag.d.ts +6 -0
  28. package/package/@types/soundfont/write/igen.d.ts +6 -0
  29. package/package/@types/soundfont/write/imod.d.ts +6 -0
  30. package/package/@types/soundfont/write/inst.d.ts +6 -0
  31. package/package/@types/soundfont/write/pbag.d.ts +6 -0
  32. package/package/@types/soundfont/write/pgen.d.ts +6 -0
  33. package/package/@types/soundfont/write/phdr.d.ts +6 -0
  34. package/package/@types/soundfont/write/pmod.d.ts +6 -0
  35. package/package/@types/soundfont/write/sdta.d.ts +11 -0
  36. package/package/@types/soundfont/write/shdr.d.ts +8 -0
  37. package/package/@types/soundfont/write/soundfont_trimmer.d.ts +6 -0
  38. package/package/@types/soundfont/write/write.d.ts +21 -0
  39. package/package/@types/synthetizer/audio_effects/effects_config.d.ts +29 -0
  40. package/package/@types/synthetizer/audio_effects/fancy_chorus.d.ts +93 -0
  41. package/package/@types/synthetizer/audio_effects/reverb.d.ts +7 -0
  42. package/package/@types/synthetizer/synth_event_handler.d.ts +161 -0
  43. package/package/@types/synthetizer/synthetizer.d.ts +294 -0
  44. package/package/@types/synthetizer/worklet_system/message_protocol/worklet_message.d.ts +89 -0
  45. package/package/@types/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.d.ts +134 -0
  46. package/package/@types/synthetizer/worklet_url.d.ts +5 -0
  47. package/package/@types/utils/buffer_to_wav.d.ts +8 -0
  48. package/package/@types/utils/byte_functions/big_endian.d.ts +13 -0
  49. package/package/@types/utils/byte_functions/little_endian.d.ts +35 -0
  50. package/package/@types/utils/byte_functions/string.d.ts +22 -0
  51. package/package/@types/utils/byte_functions/variable_length_quantity.d.ts +12 -0
  52. package/package/@types/utils/indexed_array.d.ts +21 -0
  53. package/package/@types/utils/loggin.d.ts +26 -0
  54. package/package/@types/utils/other.d.ts +32 -0
  55. package/package/LICENSE +26 -0
  56. package/package/README.md +84 -0
  57. package/package/externals/NOTICE +9 -0
  58. package/package/externals/libvorbis/@types/OggVorbisEncoder.d.ts +34 -0
  59. package/package/externals/libvorbis/OggVorbisEncoder.min.js +1 -0
  60. package/package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +12 -0
  61. package/package/externals/stbvorbis_sync/LICENSE +202 -0
  62. package/package/externals/stbvorbis_sync/stbvorbis_sync.min.js +1 -0
  63. package/package/index.js +73 -0
  64. package/package/midi_handler/README.md +3 -0
  65. package/package/midi_handler/midi_handler.js +118 -0
  66. package/package/midi_handler/web_midi_link.js +41 -0
  67. package/package/midi_parser/README.md +3 -0
  68. package/package/midi_parser/midi_data.js +121 -0
  69. package/package/midi_parser/midi_editor.js +557 -0
  70. package/package/midi_parser/midi_loader.js +502 -0
  71. package/package/midi_parser/midi_message.js +234 -0
  72. package/package/midi_parser/midi_writer.js +95 -0
  73. package/package/midi_parser/rmidi_writer.js +271 -0
  74. package/package/midi_parser/used_keys_loaded.js +172 -0
  75. package/package/package.json +43 -0
  76. package/package/sequencer/README.md +23 -0
  77. package/package/sequencer/sequencer.js +439 -0
  78. package/package/sequencer/worklet_sequencer/events.js +92 -0
  79. package/package/sequencer/worklet_sequencer/play.js +309 -0
  80. package/package/sequencer/worklet_sequencer/process_event.js +167 -0
  81. package/package/sequencer/worklet_sequencer/process_tick.js +85 -0
  82. package/package/sequencer/worklet_sequencer/sequencer_message.js +39 -0
  83. package/package/sequencer/worklet_sequencer/song_control.js +193 -0
  84. package/package/sequencer/worklet_sequencer/worklet_sequencer.js +218 -0
  85. package/package/soundfont/README.md +8 -0
  86. package/package/soundfont/read/generators.js +212 -0
  87. package/package/soundfont/read/instruments.js +125 -0
  88. package/package/soundfont/read/modulators.js +249 -0
  89. package/package/soundfont/read/presets.js +300 -0
  90. package/package/soundfont/read/riff_chunk.js +81 -0
  91. package/package/soundfont/read/samples.js +398 -0
  92. package/package/soundfont/read/zones.js +310 -0
  93. package/package/soundfont/soundfont.js +357 -0
  94. package/package/soundfont/write/ibag.js +39 -0
  95. package/package/soundfont/write/igen.js +75 -0
  96. package/package/soundfont/write/imod.js +46 -0
  97. package/package/soundfont/write/inst.js +34 -0
  98. package/package/soundfont/write/pbag.js +39 -0
  99. package/package/soundfont/write/pgen.js +77 -0
  100. package/package/soundfont/write/phdr.js +42 -0
  101. package/package/soundfont/write/pmod.js +46 -0
  102. package/package/soundfont/write/sdta.js +72 -0
  103. package/package/soundfont/write/shdr.js +54 -0
  104. package/package/soundfont/write/soundfont_trimmer.js +169 -0
  105. package/package/soundfont/write/write.js +180 -0
  106. package/package/synthetizer/README.md +6 -0
  107. package/package/synthetizer/audio_effects/effects_config.js +21 -0
  108. package/package/synthetizer/audio_effects/fancy_chorus.js +120 -0
  109. package/package/synthetizer/audio_effects/impulse_response_2.flac +0 -0
  110. package/package/synthetizer/audio_effects/reverb.js +24 -0
  111. package/package/synthetizer/synth_event_handler.js +156 -0
  112. package/package/synthetizer/synthetizer.js +766 -0
  113. package/package/synthetizer/worklet_processor.min.js +13 -0
  114. package/package/synthetizer/worklet_system/README.md +6 -0
  115. package/package/synthetizer/worklet_system/main_processor.js +363 -0
  116. package/package/synthetizer/worklet_system/message_protocol/handle_message.js +197 -0
  117. package/package/synthetizer/worklet_system/message_protocol/message_sending.js +74 -0
  118. package/package/synthetizer/worklet_system/message_protocol/worklet_message.js +121 -0
  119. package/package/synthetizer/worklet_system/minify_processor.sh +4 -0
  120. package/package/synthetizer/worklet_system/worklet_methods/controller_control.js +230 -0
  121. package/package/synthetizer/worklet_system/worklet_methods/data_entry.js +277 -0
  122. package/package/synthetizer/worklet_system/worklet_methods/note_off.js +109 -0
  123. package/package/synthetizer/worklet_system/worklet_methods/note_on.js +91 -0
  124. package/package/synthetizer/worklet_system/worklet_methods/program_control.js +183 -0
  125. package/package/synthetizer/worklet_system/worklet_methods/reset_controllers.js +177 -0
  126. package/package/synthetizer/worklet_system/worklet_methods/snapshot.js +129 -0
  127. package/package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +272 -0
  128. package/package/synthetizer/worklet_system/worklet_methods/tuning_control.js +195 -0
  129. package/package/synthetizer/worklet_system/worklet_methods/vibrato_control.js +29 -0
  130. package/package/synthetizer/worklet_system/worklet_methods/voice_control.js +233 -0
  131. package/package/synthetizer/worklet_system/worklet_processor.js +9 -0
  132. package/package/synthetizer/worklet_system/worklet_utilities/lfo.js +23 -0
  133. package/package/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +130 -0
  134. package/package/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +73 -0
  135. package/package/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +86 -0
  136. package/package/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +81 -0
  137. package/package/synthetizer/worklet_system/worklet_utilities/unit_converter.js +66 -0
  138. package/package/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +265 -0
  139. package/package/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +83 -0
  140. package/package/synthetizer/worklet_system/worklet_utilities/worklet_modulator.js +234 -0
  141. package/package/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +116 -0
  142. package/package/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +272 -0
  143. package/package/synthetizer/worklet_url.js +5 -0
  144. package/package/utils/README.md +4 -0
  145. package/package/utils/buffer_to_wav.js +101 -0
  146. package/package/utils/byte_functions/big_endian.js +28 -0
  147. package/package/utils/byte_functions/little_endian.js +74 -0
  148. package/package/utils/byte_functions/string.js +97 -0
  149. package/package/utils/byte_functions/variable_length_quantity.js +37 -0
  150. package/package/utils/encode_vorbis.js +30 -0
  151. package/package/utils/indexed_array.js +41 -0
  152. package/package/utils/loggin.js +79 -0
  153. package/package/utils/other.js +54 -0
  154. package/package.json +43 -0
@@ -0,0 +1,81 @@
1
+ import { IndexedByteArray } from '../../utils/indexed_array.js'
2
+ import { readBytesAsUintLittleEndian, writeDword } from '../../utils/byte_functions/little_endian.js'
3
+ import { readBytesAsString, writeStringAsBytes } from '../../utils/byte_functions/string.js'
4
+
5
+ /**
6
+ * riff_chunk.js
7
+ * reads a riff read and stores it as a class
8
+ */
9
+
10
+ export class RiffChunk
11
+ {
12
+ /**
13
+ * Creates a new riff read
14
+ * @constructor
15
+ * @param header {string}
16
+ * @param size {number}
17
+ * @param data {IndexedByteArray}
18
+ */
19
+ constructor(header, size, data) {
20
+ this.header = header;
21
+ this.size = size;
22
+ this.chunkData = data;
23
+ }
24
+
25
+ }
26
+
27
+ /**
28
+ * @param dataArray {IndexedByteArray}
29
+ * @param readData {boolean}
30
+ * @param forceShift {boolean}
31
+ * @returns {RiffChunk}
32
+ */
33
+ export function readRIFFChunk(dataArray, readData = true, forceShift = false) {
34
+ let header = readBytesAsString(dataArray, 4)
35
+
36
+ let size = readBytesAsUintLittleEndian(dataArray, 4)
37
+ let chunkData = undefined
38
+ if (readData)
39
+ {
40
+ chunkData = new IndexedByteArray(size)
41
+ chunkData.set(dataArray.slice(dataArray.currentIndex, dataArray.currentIndex + size))
42
+ }
43
+ if(readData || forceShift)
44
+ {
45
+ dataArray.currentIndex += size;
46
+ }
47
+
48
+ return new RiffChunk(header, size, chunkData)
49
+ }
50
+
51
+ /**
52
+ * @param chunk {RiffChunk}
53
+ * @param prepend {IndexedByteArray}
54
+ * @returns {IndexedByteArray}
55
+ */
56
+ export function writeRIFFChunk(chunk, prepend = undefined)
57
+ {
58
+ let size = 8 + chunk.size;
59
+ if(chunk.size % 2 !== 0)
60
+ {
61
+ size++;
62
+ }
63
+ if(prepend)
64
+ {
65
+ size += prepend.length;
66
+ }
67
+ const array = new IndexedByteArray(size);
68
+ // prepend data (for example type before the read)
69
+ if(prepend)
70
+ {
71
+ array.set(prepend, array.currentIndex);
72
+ array.currentIndex += prepend.length;
73
+ }
74
+ // write header
75
+ writeStringAsBytes(array, chunk.header);
76
+ // write size (excluding header and the size itself) and the prepend if specified
77
+ writeDword(array, size - 8 - (prepend?.length || 0));
78
+ // write data
79
+ array.set(chunk.chunkData, array.currentIndex);
80
+ return array;
81
+ }
@@ -0,0 +1,398 @@
1
+ import {RiffChunk} from "./riff_chunk.js";
2
+ import {IndexedByteArray} from "../../utils/indexed_array.js";
3
+ import { readBytesAsUintLittleEndian, signedInt8} from "../../utils/byte_functions/little_endian.js";
4
+ import { stbvorbis } from '../../externals/stbvorbis_sync/stbvorbis_sync.min.js'
5
+ import { SpessaSynthWarn } from '../../utils/loggin.js'
6
+ import { readBytesAsString } from '../../utils/byte_functions/string.js'
7
+
8
+ /**
9
+ * samples.js
10
+ * purpose: parses soundfont samples, resamples if needed.
11
+ * loads sample data, handles async loading of sf3 compressed samples
12
+ */
13
+
14
+ export class BasicSample
15
+ {
16
+ /**
17
+ * The basic representation of a soundfont sample
18
+ * @param sampleName {string}
19
+ * @param sampleRate {number}
20
+ * @param samplePitch {number}
21
+ * @param samplePitchCorrection {number}
22
+ * @param sampleLink {number}
23
+ * @param sampleType {number}
24
+ * @param loopStart {number} relative to sample start
25
+ * @param loopEnd {number} relative to sample start
26
+ */
27
+ constructor(
28
+ sampleName,
29
+ sampleRate,
30
+ samplePitch,
31
+ samplePitchCorrection,
32
+ sampleLink,
33
+ sampleType,
34
+ loopStart,
35
+ loopEnd
36
+ )
37
+ {
38
+ /**
39
+ * Sample's name
40
+ * @type {string}
41
+ */
42
+ this.sampleName = sampleName;
43
+ /**
44
+ * Sample rate in Hz
45
+ * @type {number}
46
+ */
47
+ this.sampleRate = sampleRate;
48
+ /**
49
+ * Original pitch of the sample as a MIDI note number
50
+ * @type {number}
51
+ */
52
+ this.samplePitch = samplePitch;
53
+ /**
54
+ * Pitch correction, in cents. Can be negative
55
+ * @type {number}
56
+ */
57
+ this.samplePitchCorrection = samplePitchCorrection;
58
+ /**
59
+ * Sample link, currently unused.
60
+ * @type {number}
61
+ */
62
+ this.sampleLink = sampleLink;
63
+ /**
64
+ * Type of the sample, an enum
65
+ * @type {number}
66
+ */
67
+ this.sampleType = sampleType;
68
+ /**
69
+ * Relative to start of the sample, bytes
70
+ * @type {number}
71
+ */
72
+ this.sampleLoopStartIndex = loopStart;
73
+ /**
74
+ * Relative to start of the sample, in bytes
75
+ * @type {number}
76
+ */
77
+ this.sampleLoopEndIndex = loopEnd;
78
+
79
+ /**
80
+ * Indicates if the sample is compressed
81
+ * @type {boolean}
82
+ */
83
+ this.isCompressed = (sampleType & 0x10) > 0;
84
+
85
+ /**
86
+ * The compressed sample data if it was compressed by spessasynth
87
+ * @type {Uint8Array}
88
+ */
89
+ this.compressedData = undefined;
90
+ }
91
+
92
+ /**
93
+ * @returns {Uint8Array|IndexedByteArray}
94
+ */
95
+ getRawData()
96
+ {
97
+ const e = new Error("Not implemented");
98
+ e.name = "NotImplementedError";
99
+ throw e;
100
+ }
101
+
102
+ /**
103
+ * @param quality {number}
104
+ * @param encodeVorbis {EncodeVorbisFunction}
105
+ */
106
+ compressSample(quality, encodeVorbis)
107
+ {
108
+ // no need to compress
109
+ if(this.isCompressed)
110
+ {
111
+ return;
112
+ }
113
+ // compress, always mono!
114
+ try {
115
+ this.compressedData = encodeVorbis([this.getAudioData()], 1, this.sampleRate, quality);
116
+ // flag as compressed
117
+ this.sampleType |= 0x10;
118
+ this.isCompressed = true;
119
+ }
120
+ catch (e)
121
+ {
122
+ SpessaSynthWarn(`Failed to compress ${this.sampleName}. Leaving as uncompressed!`);
123
+ this.isCompressed = false;
124
+ this.compressedData = undefined;
125
+ this.sampleType &= -17;
126
+ }
127
+
128
+ }
129
+
130
+ /**
131
+ * @returns {Float32Array}
132
+ */
133
+ getAudioData()
134
+ {
135
+ const e = new Error("Not implemented");
136
+ e.name = "NotImplementedError";
137
+ throw e;
138
+ }
139
+ }
140
+
141
+ export class Sample extends BasicSample
142
+ {
143
+ /**
144
+ * Creates a sample
145
+ * @param sampleName {string}
146
+ * @param sampleStartIndex {number}
147
+ * @param sampleEndIndex {number}
148
+ * @param sampleLoopStartIndex {number}
149
+ * @param sampleLoopEndIndex {number}
150
+ * @param sampleRate {number}
151
+ * @param samplePitch {number}
152
+ * @param samplePitchCorrection {number}
153
+ * @param sampleLink {number}
154
+ * @param sampleType {number}
155
+ * @param smplArr {IndexedByteArray}
156
+ * @param sampleIndex {number} initial sample index when loading the sfont
157
+ */
158
+ constructor(sampleName,
159
+ sampleStartIndex,
160
+ sampleEndIndex,
161
+ sampleLoopStartIndex,
162
+ sampleLoopEndIndex,
163
+ sampleRate,
164
+ samplePitch,
165
+ samplePitchCorrection,
166
+ sampleLink,
167
+ sampleType,
168
+ smplArr,
169
+ sampleIndex
170
+ )
171
+ {
172
+ super(
173
+ sampleName,
174
+ sampleRate,
175
+ samplePitch,
176
+ samplePitchCorrection,
177
+ sampleLink,
178
+ sampleType,
179
+ sampleLoopStartIndex - sampleStartIndex,
180
+ sampleLoopEndIndex - sampleStartIndex
181
+ );
182
+ this.sampleName = sampleName
183
+ // in bytes
184
+ this.sampleStartIndex = sampleStartIndex;
185
+ this.sampleEndIndex = sampleEndIndex;
186
+ this.isSampleLoaded = false;
187
+ this.sampleID = sampleIndex;
188
+ this.useCount = 0;
189
+ // in bytes
190
+ this.sampleLength = this.sampleEndIndex - this.sampleStartIndex;
191
+ this.sampleDataArray = smplArr;
192
+ this.sampleData = new Float32Array(0);
193
+ if(this.isCompressed)
194
+ {
195
+ // correct loop points
196
+ this.sampleLoopStartIndex += this.sampleStartIndex;
197
+ this.sampleLoopEndIndex += this.sampleStartIndex;
198
+ this.sampleLength = 99999999; // set to 999999 before we decode it
199
+ }
200
+
201
+ }
202
+
203
+ /**
204
+ * Get raw data, whether it's compressed or not as we simply write it to the file
205
+ * @return {Uint8Array}
206
+ */
207
+ getRawData()
208
+ {
209
+ const smplArr = this.sampleDataArray;
210
+ if(this.isCompressed)
211
+ {
212
+ if(this.compressedData)
213
+ {
214
+ return this.compressedData;
215
+ }
216
+ const smplStart = smplArr.currentIndex;
217
+ return smplArr.slice(this.sampleStartIndex / 2 + smplStart, this.sampleEndIndex / 2 + smplStart);
218
+ }
219
+ else
220
+ {
221
+ const dataStartIndex = smplArr.currentIndex;
222
+ return smplArr.slice(dataStartIndex + this.sampleStartIndex, dataStartIndex + this.sampleEndIndex)
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Decode binary vorbis into a float32 pcm
228
+ */
229
+ decodeVorbis()
230
+ {
231
+ if (this.sampleLength < 1)
232
+ {
233
+ // eos, do not do anything
234
+ return;
235
+ }
236
+ // get the compressed byte stream
237
+ const smplArr = this.sampleDataArray;
238
+ const smplStart = smplArr.currentIndex;
239
+ const buff = smplArr.slice(this.sampleStartIndex / 2 + smplStart, this.sampleEndIndex / 2 + smplStart);
240
+ // reset array and being decoding
241
+ this.sampleData = new Float32Array(0);
242
+ /**
243
+ * @type {{data: Float32Array[], error: (string|null), sampleRate: number, eof: boolean}}
244
+ */
245
+ const vorbis = stbvorbis.decode(buff.buffer);
246
+ this.sampleData = vorbis.data[0];
247
+ }
248
+
249
+ /**
250
+ * Loads the audio data and stores it for reuse
251
+ * @returns {Float32Array} The audioData
252
+ */
253
+ getAudioData()
254
+ {
255
+ if (!this.isSampleLoaded)
256
+ {
257
+ // start loading data if not loaded
258
+ return this.loadBufferData();
259
+ }
260
+ return this.sampleData;
261
+ }
262
+
263
+ /**
264
+ * @returns {Float32Array}
265
+ */
266
+ loadUncompressedData()
267
+ {
268
+ if(this.isCompressed)
269
+ {
270
+ SpessaSynthWarn("Trying to load a compressed sample via loadUncompressedData()... aborting!");
271
+ return new Float32Array(0);
272
+ }
273
+
274
+ // read the sample data
275
+ let audioData = new Float32Array(this.sampleLength / 2);
276
+ const dataStartIndex = this.sampleDataArray.currentIndex;
277
+ let convertedSigned16 = new Int16Array(
278
+ this.sampleDataArray.slice(dataStartIndex + this.sampleStartIndex, dataStartIndex + this.sampleEndIndex)
279
+ .buffer
280
+ );
281
+
282
+ // convert to float
283
+ for(let i = 0; i < convertedSigned16.length; i++)
284
+ {
285
+ audioData[i] = convertedSigned16[i] / 32768;
286
+ }
287
+
288
+ this.sampleData = audioData;
289
+ this.isSampleLoaded = true;
290
+ return audioData;
291
+ }
292
+
293
+ /**
294
+ * @returns {Float32Array}
295
+ */
296
+ loadBufferData()
297
+ {
298
+ if (this.sampleLength < 1)
299
+ {
300
+ // eos, do not do anything
301
+ return new Float32Array(1);
302
+ }
303
+
304
+ if(this.isCompressed)
305
+ {
306
+ this.decodeVorbis();
307
+ this.isSampleLoaded = true;
308
+ return this.sampleData;
309
+ }
310
+ return this.loadUncompressedData();
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Reads the generatorTranslator from the shdr read
316
+ * @param sampleHeadersChunk {RiffChunk}
317
+ * @param smplChunkData {IndexedByteArray}
318
+ * @returns {Sample[]}
319
+ */
320
+ export function readSamples(sampleHeadersChunk, smplChunkData)
321
+ {
322
+ /**
323
+ * @type {Sample[]}
324
+ */
325
+ let samples = [];
326
+ let index = 0;
327
+ while(sampleHeadersChunk.chunkData.length > sampleHeadersChunk.chunkData.currentIndex)
328
+ {
329
+ const sample = readSample(index, sampleHeadersChunk.chunkData, smplChunkData);
330
+ samples.push(sample);
331
+ index++;
332
+ }
333
+ // remove EOS
334
+ if (samples.length > 1)
335
+ {
336
+ samples.pop();
337
+ }
338
+ return samples;
339
+ }
340
+
341
+ /**
342
+ * Reads it into a sample
343
+ * @param index {number}
344
+ * @param sampleHeaderData {IndexedByteArray}
345
+ * @param smplArrayData {IndexedByteArray}
346
+ * @returns {Sample}
347
+ */
348
+ function readSample(index, sampleHeaderData, smplArrayData) {
349
+
350
+ // read the sample name
351
+ let sampleName = readBytesAsString(sampleHeaderData, 20);
352
+
353
+ // read the sample start index
354
+ let sampleStartIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
355
+
356
+ // read the sample end index
357
+ let sampleEndIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
358
+
359
+ // read the sample looping start index
360
+ let sampleLoopStartIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
361
+
362
+ // read the sample looping end index
363
+ let sampleLoopEndIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
364
+
365
+ // read the sample rate
366
+ let sampleRate = readBytesAsUintLittleEndian(sampleHeaderData, 4);
367
+
368
+ // read the original sample pitch
369
+ let samplePitch = sampleHeaderData[sampleHeaderData.currentIndex++];
370
+ if(samplePitch === 255)
371
+ {
372
+ // if it's 255, then default to 60
373
+ samplePitch = 60;
374
+ }
375
+
376
+ // readt the sample pitch correction
377
+ let samplePitchCorrection = signedInt8(sampleHeaderData[sampleHeaderData.currentIndex++]);
378
+
379
+
380
+ // read the link to the other channel
381
+ let sampleLink = readBytesAsUintLittleEndian(sampleHeaderData, 2);
382
+ let sampleType = readBytesAsUintLittleEndian(sampleHeaderData, 2);
383
+
384
+
385
+
386
+ return new Sample(sampleName,
387
+ sampleStartIndex,
388
+ sampleEndIndex,
389
+ sampleLoopStartIndex,
390
+ sampleLoopEndIndex,
391
+ sampleRate,
392
+ samplePitch,
393
+ samplePitchCorrection,
394
+ sampleLink,
395
+ sampleType,
396
+ smplArrayData,
397
+ index);
398
+ }