spessasynth_lib 3.25.23 → 3.26.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 (162) hide show
  1. package/README.md +29 -114
  2. package/external_midi/midi_handler.js +14 -14
  3. package/external_midi/web_midi_link.js +3 -3
  4. package/index.js +33 -33
  5. package/package.json +19 -6
  6. package/{midi → sequencer}/midi_data.js +1 -1
  7. package/sequencer/{worklet_wrapper/sequencer.js → sequencer.js} +13 -12
  8. package/sequencer/{worklet_wrapper/sequencer_message.js → sequencer_message.js} +1 -1
  9. package/synthetizer/README.md +29 -1
  10. package/synthetizer/audio_effects/reverb_as_binary.js +2 -2
  11. package/synthetizer/{worklet_wrapper/key_modifier_manager.js → key_modifier_manager.js} +11 -2
  12. package/synthetizer/{worklet_wrapper/synth_event_handler.js → synth_event_handler.js} +16 -13
  13. package/synthetizer/{worklet_wrapper/synth_soundfont_manager.js → synth_soundfont_manager.js} +8 -5
  14. package/synthetizer/{worklet_wrapper/synthetizer.js → synthetizer.js} +29 -23
  15. package/synthetizer/{audio_engine/message_protocol/worklet_message.js → worklet_message.js} +15 -2
  16. package/synthetizer/{worklet_wrapper/worklet_processor.js → worklet_processor.js} +214 -31
  17. package/synthetizer/worklet_processor.min.js +13 -12
  18. package/synthetizer/worklet_processor.min.js.map +7 -0
  19. package/synthetizer/{worklet_wrapper/worklet_url.js → worklet_url.js} +2 -0
  20. package/utils/buffer_to_wav.js +7 -165
  21. package/utils/other.js +3 -84
  22. package/externals/fflate/LICENSE +0 -21
  23. package/externals/fflate/fflate.min.js +0 -1
  24. package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
  25. package/externals/stbvorbis_sync/LICENSE +0 -202
  26. package/externals/stbvorbis_sync/NOTICE +0 -6
  27. package/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
  28. package/midi/README.md +0 -32
  29. package/midi/basic_midi.js +0 -565
  30. package/midi/midi_builder.js +0 -202
  31. package/midi/midi_loader.js +0 -324
  32. package/midi/midi_message.js +0 -254
  33. package/midi/midi_sequence.js +0 -225
  34. package/midi/midi_tools/get_note_times.js +0 -154
  35. package/midi/midi_tools/midi_editor.js +0 -611
  36. package/midi/midi_tools/midi_writer.js +0 -99
  37. package/midi/midi_tools/rmidi_writer.js +0 -567
  38. package/midi/midi_tools/used_keys_loaded.js +0 -238
  39. package/midi/xmf_loader.js +0 -454
  40. package/sequencer/sequencer_engine/events.js +0 -104
  41. package/sequencer/sequencer_engine/play.js +0 -353
  42. package/sequencer/sequencer_engine/process_event.js +0 -169
  43. package/sequencer/sequencer_engine/process_tick.js +0 -106
  44. package/sequencer/sequencer_engine/sequencer_engine.js +0 -335
  45. package/sequencer/sequencer_engine/song_control.js +0 -229
  46. package/soundfont/README.md +0 -13
  47. package/soundfont/basic_soundfont/basic_instrument.js +0 -77
  48. package/soundfont/basic_soundfont/basic_preset.js +0 -336
  49. package/soundfont/basic_soundfont/basic_sample.js +0 -197
  50. package/soundfont/basic_soundfont/basic_soundfont.js +0 -565
  51. package/soundfont/basic_soundfont/basic_zone.js +0 -64
  52. package/soundfont/basic_soundfont/basic_zones.js +0 -43
  53. package/soundfont/basic_soundfont/generator.js +0 -220
  54. package/soundfont/basic_soundfont/modulator.js +0 -378
  55. package/soundfont/basic_soundfont/riff_chunk.js +0 -149
  56. package/soundfont/basic_soundfont/write_dls/art2.js +0 -173
  57. package/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
  58. package/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -400
  59. package/soundfont/basic_soundfont/write_dls/ins.js +0 -103
  60. package/soundfont/basic_soundfont/write_dls/lins.js +0 -18
  61. package/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
  62. package/soundfont/basic_soundfont/write_dls/rgn2.js +0 -121
  63. package/soundfont/basic_soundfont/write_dls/wave.js +0 -94
  64. package/soundfont/basic_soundfont/write_dls/write_dls.js +0 -119
  65. package/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
  66. package/soundfont/basic_soundfont/write_dls/wvpl.js +0 -32
  67. package/soundfont/basic_soundfont/write_sf2/ibag.js +0 -39
  68. package/soundfont/basic_soundfont/write_sf2/igen.js +0 -80
  69. package/soundfont/basic_soundfont/write_sf2/imod.js +0 -46
  70. package/soundfont/basic_soundfont/write_sf2/inst.js +0 -34
  71. package/soundfont/basic_soundfont/write_sf2/pbag.js +0 -39
  72. package/soundfont/basic_soundfont/write_sf2/pgen.js +0 -82
  73. package/soundfont/basic_soundfont/write_sf2/phdr.js +0 -42
  74. package/soundfont/basic_soundfont/write_sf2/pmod.js +0 -46
  75. package/soundfont/basic_soundfont/write_sf2/sdta.js +0 -80
  76. package/soundfont/basic_soundfont/write_sf2/shdr.js +0 -55
  77. package/soundfont/basic_soundfont/write_sf2/write.js +0 -222
  78. package/soundfont/dls/articulator_converter.js +0 -396
  79. package/soundfont/dls/dls_destinations.js +0 -38
  80. package/soundfont/dls/dls_preset.js +0 -44
  81. package/soundfont/dls/dls_sample.js +0 -75
  82. package/soundfont/dls/dls_soundfont.js +0 -186
  83. package/soundfont/dls/dls_sources.js +0 -62
  84. package/soundfont/dls/dls_zone.js +0 -95
  85. package/soundfont/dls/read_articulation.js +0 -299
  86. package/soundfont/dls/read_instrument.js +0 -121
  87. package/soundfont/dls/read_instrument_list.js +0 -17
  88. package/soundfont/dls/read_lart.js +0 -35
  89. package/soundfont/dls/read_region.js +0 -152
  90. package/soundfont/dls/read_samples.js +0 -270
  91. package/soundfont/load_soundfont.js +0 -21
  92. package/soundfont/read_sf2/generators.js +0 -46
  93. package/soundfont/read_sf2/instruments.js +0 -66
  94. package/soundfont/read_sf2/modulators.js +0 -36
  95. package/soundfont/read_sf2/presets.js +0 -80
  96. package/soundfont/read_sf2/samples.js +0 -304
  97. package/soundfont/read_sf2/soundfont.js +0 -305
  98. package/soundfont/read_sf2/zones.js +0 -263
  99. package/synthetizer/audio_engine/README.md +0 -25
  100. package/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -266
  101. package/synthetizer/audio_engine/engine_components/controller_tables.js +0 -88
  102. package/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -149
  103. package/synthetizer/audio_engine/engine_components/lfo.js +0 -26
  104. package/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
  105. package/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -471
  106. package/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
  107. package/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
  108. package/synthetizer/audio_engine/engine_components/soundfont_manager.js +0 -228
  109. package/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -120
  110. package/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
  111. package/synthetizer/audio_engine/engine_components/voice.js +0 -519
  112. package/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -401
  113. package/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -263
  114. package/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -132
  115. package/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
  116. package/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -241
  117. package/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -27
  118. package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -253
  119. package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -66
  120. package/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
  121. package/synthetizer/audio_engine/engine_methods/note_on.js +0 -175
  122. package/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
  123. package/synthetizer/audio_engine/engine_methods/program_change.js +0 -61
  124. package/synthetizer/audio_engine/engine_methods/render_voice.js +0 -196
  125. package/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +0 -30
  126. package/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -22
  127. package/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +0 -40
  128. package/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +0 -34
  129. package/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +0 -21
  130. package/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -20
  131. package/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -55
  132. package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
  133. package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
  134. package/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
  135. package/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -776
  136. package/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -24
  137. package/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -33
  138. package/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -31
  139. package/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
  140. package/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
  141. package/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
  142. package/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
  143. package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
  144. package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
  145. package/synthetizer/audio_engine/main_processor.js +0 -765
  146. package/synthetizer/audio_engine/message_protocol/README.md +0 -13
  147. package/synthetizer/audio_engine/message_protocol/message_sending.js +0 -22
  148. package/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -14
  149. package/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
  150. package/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -122
  151. package/synthetizer/synth_constants.js +0 -20
  152. package/utils/README.md +0 -5
  153. package/utils/byte_functions/big_endian.js +0 -32
  154. package/utils/byte_functions/little_endian.js +0 -77
  155. package/utils/byte_functions/string.js +0 -107
  156. package/utils/byte_functions/variable_length_quantity.js +0 -42
  157. package/utils/indexed_array.js +0 -52
  158. package/utils/loggin.js +0 -79
  159. package/utils/sysex_detector.js +0 -58
  160. package/utils/xg_hacks.js +0 -193
  161. /package/sequencer/{worklet_wrapper/default_sequencer_options.js → default_sequencer_options.js} +0 -0
  162. /package/synthetizer/{worklet_wrapper/sfman_message.js → sfman_message.js} +0 -0
@@ -1,77 +0,0 @@
1
- export class BasicInstrument
2
- {
3
- /**
4
- * The instrument's name
5
- * @type {string}
6
- */
7
- instrumentName = "";
8
-
9
- /**
10
- * The instrument's zones
11
- * @type {BasicInstrumentZone[]}
12
- */
13
- instrumentZones = [];
14
-
15
- /**
16
- * Instrument's use count, used for trimming
17
- * @type {number}
18
- * @private
19
- */
20
- _useCount = 0;
21
-
22
- /**
23
- * @returns {number}
24
- */
25
- get useCount()
26
- {
27
- return this._useCount;
28
- }
29
-
30
- addUseCount()
31
- {
32
- this._useCount++;
33
- this.instrumentZones.forEach(z => z.useCount++);
34
- }
35
-
36
- removeUseCount()
37
- {
38
- this._useCount--;
39
- for (let i = 0; i < this.instrumentZones.length; i++)
40
- {
41
- if (this.safeDeleteZone(i))
42
- {
43
- i--;
44
- }
45
- }
46
- }
47
-
48
- deleteInstrument()
49
- {
50
- this.instrumentZones.forEach(z => z.deleteZone());
51
- this.instrumentZones.length = 0;
52
- }
53
-
54
- /**
55
- * @param index {number}
56
- * @returns {boolean} is the zone has been deleted
57
- */
58
- safeDeleteZone(index)
59
- {
60
- this.instrumentZones[index].useCount--;
61
- if (this.instrumentZones[index].useCount < 1)
62
- {
63
- this.deleteZone(index);
64
- return true;
65
- }
66
- return false;
67
- }
68
-
69
- /**
70
- * @param index {number}
71
- */
72
- deleteZone(index)
73
- {
74
- this.instrumentZones[index].deleteZone();
75
- this.instrumentZones.splice(index, 1);
76
- }
77
- }
@@ -1,336 +0,0 @@
1
- /**
2
- * @typedef {{
3
- * instrumentGenerators: Generator[],
4
- * presetGenerators: Generator[],
5
- * modulators: Modulator[],
6
- * sample: BasicSample,
7
- * sampleID: number,
8
- * }} SampleAndGenerators
9
- */
10
- import { generatorTypes } from "./generator.js";
11
- import { Modulator } from "./modulator.js";
12
- import { isXGDrums } from "../../utils/xg_hacks.js";
13
-
14
- export class BasicPreset
15
- {
16
- /**
17
- * The parent soundbank instance
18
- * Currently used for determining default modulators and XG status
19
- * @type {BasicSoundBank}
20
- */
21
- parentSoundBank;
22
-
23
- /**
24
- * The preset's name
25
- * @type {string}
26
- */
27
- presetName = "";
28
-
29
- /**
30
- * The preset's MIDI program number
31
- * @type {number}
32
- */
33
- program = 0;
34
-
35
- /**
36
- * The preset's MIDI bank number
37
- * @type {number}
38
- */
39
- bank = 0;
40
-
41
- /**
42
- * The preset's zones
43
- * @type {BasicPresetZone[]}
44
- */
45
- presetZones = [];
46
-
47
- /**
48
- * Stores already found getSamplesAndGenerators for reuse
49
- * @type {SampleAndGenerators[][][]}
50
- */
51
- foundSamplesAndGenerators = [];
52
-
53
- /**
54
- * unused metadata
55
- * @type {number}
56
- */
57
- library = 0;
58
- /**
59
- * unused metadata
60
- * @type {number}
61
- */
62
- genre = 0;
63
- /**
64
- * unused metadata
65
- * @type {number}
66
- */
67
- morphology = 0;
68
-
69
- /**
70
- * Creates a new preset representation
71
- * @param parentSoundBank {BasicSoundBank}
72
- */
73
- constructor(parentSoundBank)
74
- {
75
- this.parentSoundBank = parentSoundBank;
76
- for (let i = 0; i < 128; i++)
77
- {
78
- this.foundSamplesAndGenerators[i] = [];
79
- }
80
- }
81
-
82
- /**
83
- * @param allowXG {boolean}
84
- * @param allowSFX {boolean}
85
- * @returns {boolean}
86
- */
87
- isDrumPreset(allowXG, allowSFX = false)
88
- {
89
- const xg = allowXG && this.parentSoundBank.isXGBank;
90
- // sfx is not cool
91
- return this.bank === 128 || (
92
- xg &&
93
- (isXGDrums(this.bank) && (this.bank !== 126 || allowSFX))
94
- );
95
- }
96
-
97
- deletePreset()
98
- {
99
- this.presetZones.forEach(z => z.deleteZone());
100
- this.presetZones.length = 0;
101
- }
102
-
103
- /**
104
- * @param index {number}
105
- */
106
- deleteZone(index)
107
- {
108
- this.presetZones[index].deleteZone();
109
- this.presetZones.splice(index, 1);
110
- }
111
-
112
- // noinspection JSUnusedGlobalSymbols
113
- /**
114
- * Preloads all samples (async)
115
- */
116
- preload(keyMin, keyMax)
117
- {
118
- for (let key = keyMin; key < keyMax + 1; key++)
119
- {
120
- for (let velocity = 0; velocity < 128; velocity++)
121
- {
122
- this.getSamplesAndGenerators(key, velocity).forEach(samandgen =>
123
- {
124
- if (!samandgen.sample.isSampleLoaded)
125
- {
126
- samandgen.sample.getAudioData();
127
- }
128
- });
129
- }
130
- }
131
- }
132
-
133
- /**
134
- * Preloads a specific key/velocity combo
135
- * @param key {number}
136
- * @param velocity {number}
137
- */
138
- preloadSpecific(key, velocity)
139
- {
140
- this.getSamplesAndGenerators(key, velocity).forEach(samandgen =>
141
- {
142
- if (!samandgen.sample.isSampleLoaded)
143
- {
144
- samandgen.sample.getAudioData();
145
- }
146
- });
147
- }
148
-
149
- /**
150
- * Returns generatorTranslator and generators for given note
151
- * @param midiNote {number}
152
- * @param velocity {number}
153
- * @returns {SampleAndGenerators[]}
154
- */
155
- getSamplesAndGenerators(midiNote, velocity)
156
- {
157
- const memorized = this.foundSamplesAndGenerators[midiNote][velocity];
158
- if (memorized)
159
- {
160
- return memorized;
161
- }
162
-
163
- if (this.presetZones.length < 1)
164
- {
165
- return [];
166
- }
167
-
168
- /**
169
- * @param range {SoundFontRange}
170
- * @param number {number}
171
- * @returns {boolean}
172
- */
173
- function isInRange(range, number)
174
- {
175
- return number >= range.min && number <= range.max;
176
- }
177
-
178
- /**
179
- * @param main {Generator[]}
180
- * @param adder {Generator[]}
181
- */
182
- function addUnique(main, adder)
183
- {
184
- main.push(...adder.filter(g => !main.find(mg => mg.generatorType === g.generatorType)));
185
- }
186
-
187
- /**
188
- * @param main {Modulator[]}
189
- * @param adder {Modulator[]}
190
- */
191
- function addUniqueMods(main, adder)
192
- {
193
- main.push(...adder.filter(m => !main.find(mm => Modulator.isIdentical(m, mm))));
194
- }
195
-
196
- /**
197
- * @type {SampleAndGenerators[]}
198
- */
199
- let parsedGeneratorsAndSamples = [];
200
-
201
- /**
202
- * global zone is always first, so it or nothing
203
- * @type {Generator[]}
204
- */
205
- let globalPresetGenerators = this.presetZones[0].isGlobal ? [...this.presetZones[0].generators] : [];
206
-
207
- /**
208
- * @type {Modulator[]}
209
- */
210
- let globalPresetModulators = this.presetZones[0].isGlobal ? [...this.presetZones[0].modulators] : [];
211
- const globalKeyRange = this.presetZones[0].isGlobal ? this.presetZones[0].keyRange : { min: 0, max: 127 };
212
- const globalVelRange = this.presetZones[0].isGlobal ? this.presetZones[0].velRange : { min: 0, max: 127 };
213
-
214
- // find the preset zones in range
215
- let presetZonesInRange = this.presetZones.filter(currentZone =>
216
- (
217
- isInRange(
218
- currentZone.hasKeyRange ? currentZone.keyRange : globalKeyRange,
219
- midiNote
220
- )
221
- &&
222
- isInRange(
223
- currentZone.hasVelRange ? currentZone.velRange : globalVelRange,
224
- velocity
225
- )
226
- ) && !currentZone.isGlobal);
227
-
228
- presetZonesInRange.forEach(zone =>
229
- {
230
- // the global zone is already taken into account earlier
231
- if (zone.instrument.instrumentZones.length < 1)
232
- {
233
- return;
234
- }
235
- let presetGenerators = zone.generators;
236
- let presetModulators = zone.modulators;
237
- const firstZone = zone.instrument.instrumentZones[0];
238
- /**
239
- * global zone is always first, so it or nothing
240
- * @type {Generator[]}
241
- */
242
- let globalInstrumentGenerators = firstZone.isGlobal ? [...firstZone.generators] : [];
243
- let globalInstrumentModulators = firstZone.isGlobal ? [...firstZone.modulators] : [];
244
- const globalKeyRange = firstZone.isGlobal ? firstZone.keyRange : { min: 0, max: 127 };
245
- const globalVelRange = firstZone.isGlobal ? firstZone.velRange : { min: 0, max: 127 };
246
-
247
-
248
- let instrumentZonesInRange = zone.instrument.instrumentZones
249
- .filter(currentZone =>
250
- (
251
- isInRange(
252
- currentZone.hasKeyRange ? currentZone.keyRange : globalKeyRange,
253
- midiNote
254
- )
255
- &&
256
- isInRange(
257
- currentZone.hasVelRange ? currentZone.velRange : globalVelRange,
258
- velocity
259
- )
260
- ) && !currentZone.isGlobal
261
- );
262
-
263
- instrumentZonesInRange.forEach(instrumentZone =>
264
- {
265
- let instrumentGenerators = [...instrumentZone.generators];
266
- let instrumentModulators = [...instrumentZone.modulators];
267
-
268
- addUnique(
269
- presetGenerators,
270
- globalPresetGenerators
271
- );
272
- // add the unique global preset generators (local replace global(
273
-
274
-
275
- // add the unique global instrument generators (local replace global)
276
- addUnique(
277
- instrumentGenerators,
278
- globalInstrumentGenerators
279
- );
280
-
281
- addUniqueMods(
282
- presetModulators,
283
- globalPresetModulators
284
- );
285
- addUniqueMods(
286
- instrumentModulators,
287
- globalInstrumentModulators
288
- );
289
-
290
- // default mods
291
- addUniqueMods(
292
- instrumentModulators,
293
- this.parentSoundBank.defaultModulators
294
- );
295
-
296
- /**
297
- * sum preset modulators to instruments (amount) sf spec page 54
298
- * @type {Modulator[]}
299
- */
300
- const finalModulatorList = [...instrumentModulators];
301
- for (let i = 0; i < presetModulators.length; i++)
302
- {
303
- let mod = presetModulators[i];
304
- const identicalInstrumentModulator = finalModulatorList.findIndex(
305
- m => Modulator.isIdentical(mod, m));
306
- if (identicalInstrumentModulator !== -1)
307
- {
308
- // sum the amounts
309
- // (this makes a new modulator because otherwise it would overwrite the one in the soundfont!
310
- finalModulatorList[identicalInstrumentModulator] = finalModulatorList[identicalInstrumentModulator].sumTransform(
311
- mod);
312
- }
313
- else
314
- {
315
- finalModulatorList.push(mod);
316
- }
317
- }
318
-
319
-
320
- // combine both generators and add to the final result
321
- parsedGeneratorsAndSamples.push({
322
- instrumentGenerators: instrumentGenerators,
323
- presetGenerators: presetGenerators,
324
- modulators: finalModulatorList,
325
- sample: instrumentZone.sample,
326
- sampleID: instrumentZone.generators.find(
327
- g => g.generatorType === generatorTypes.sampleID).generatorValue
328
- });
329
- });
330
- });
331
-
332
- // save and return
333
- this.foundSamplesAndGenerators[midiNote][velocity] = parsedGeneratorsAndSamples;
334
- return parsedGeneratorsAndSamples;
335
- }
336
- }
@@ -1,197 +0,0 @@
1
- /**
2
- * samples.js
3
- * purpose: parses soundfont samples, resamples if needed.
4
- * loads sample data, handles async loading of sf3 compressed samples
5
- */
6
- import { SpessaSynthWarn } from "../../utils/loggin.js";
7
-
8
- // should be reasonable for most cases
9
- const RESAMPLE_RATE = 48000;
10
-
11
- export class BasicSample
12
- {
13
-
14
- /**
15
- * The sample's name
16
- * @type {string}
17
- */
18
- sampleName;
19
-
20
- /**
21
- * Sample rate in Hz
22
- * @type {number}
23
- */
24
- sampleRate;
25
-
26
- /**
27
- * Original pitch of the sample as a MIDI note number
28
- * @type {number}
29
- */
30
- samplePitch;
31
-
32
- /**
33
- * Pitch correction, in cents. Can be negative
34
- * @type {number}
35
- */
36
- samplePitchCorrection;
37
-
38
- /**
39
- * Sample link, currently unused here
40
- * @type {number}
41
- */
42
- sampleLink;
43
-
44
- /**
45
- * Type of the sample, currently only used for SF3
46
- * @type {number}
47
- */
48
- sampleType;
49
-
50
- /**
51
- * Relative to the start of the sample in sample points
52
- * @type {number}
53
- */
54
- sampleLoopStartIndex;
55
-
56
- /**
57
- * Relative to the start of the sample in sample points
58
- * @type {number}
59
- */
60
- sampleLoopEndIndex;
61
-
62
- /**
63
- * Indicates if the sample is compressed
64
- * @type {boolean}
65
- */
66
- isCompressed;
67
-
68
- /**
69
- * The compressed sample data if it was compressed by spessasynth
70
- * @type {Uint8Array}
71
- */
72
- compressedData = undefined;
73
-
74
- /**
75
- * The sample's use count
76
- * @type {number}
77
- */
78
- useCount = 0;
79
-
80
- /**
81
- * The sample's audio data
82
- * @type {Float32Array}
83
- */
84
- sampleData = undefined;
85
-
86
- /**
87
- * The basic representation of a soundfont sample
88
- * @param sampleName {string} The sample's name
89
- * @param sampleRate {number} The sample's rate in Hz
90
- * @param samplePitch {number} The sample's pitch as a MIDI note number
91
- * @param samplePitchCorrection {number} The sample's pitch correction in cents
92
- * @param sampleLink {number} The sample's link, currently unused
93
- * @param sampleType {number} The sample's type, an enum
94
- * @param loopStart {number} The sample's loop start relative to the sample start in sample points
95
- * @param loopEnd {number} The sample's loop end relative to the sample start in sample points
96
- */
97
- constructor(
98
- sampleName,
99
- sampleRate,
100
- samplePitch,
101
- samplePitchCorrection,
102
- sampleLink,
103
- sampleType,
104
- loopStart,
105
- loopEnd
106
- )
107
- {
108
- this.sampleName = sampleName;
109
- this.sampleRate = sampleRate;
110
- this.samplePitch = samplePitch;
111
- this.samplePitchCorrection = samplePitchCorrection;
112
- this.sampleLink = sampleLink;
113
- this.sampleType = sampleType;
114
- this.sampleLoopStartIndex = loopStart;
115
- this.sampleLoopEndIndex = loopEnd;
116
- // https://github.com/FluidSynth/fluidsynth/wiki/SoundFont3Format
117
- this.isCompressed = (sampleType & 0x10) > 0;
118
- }
119
-
120
-
121
- /**
122
- * @returns {Uint8Array|IndexedByteArray}
123
- */
124
- getRawData()
125
- {
126
- const uint8 = new Uint8Array(this.sampleData.length * 2);
127
- for (let i = 0; i < this.sampleData.length; i++)
128
- {
129
- const sample = Math.floor(this.sampleData[i] * 32768);
130
- uint8[i * 2] = sample & 0xFF; // lower byte
131
- uint8[i * 2 + 1] = (sample >> 8) & 0xFF; // upper byte
132
- }
133
- return uint8;
134
- }
135
-
136
- resampleData(newSampleRate)
137
- {
138
- let audioData = this.getAudioData();
139
- const ratio = newSampleRate / this.sampleRate;
140
- const resampled = new Float32Array(Math.floor(audioData.length * ratio));
141
- for (let i = 0; i < resampled.length; i++)
142
- {
143
- resampled[i] = audioData[Math.floor(i * (1 / ratio))];
144
- }
145
- audioData = resampled;
146
- this.sampleRate = newSampleRate;
147
- // adjust loop points
148
- this.sampleLoopStartIndex = Math.floor(this.sampleLoopStartIndex * ratio);
149
- this.sampleLoopEndIndex = Math.floor(this.sampleLoopEndIndex * ratio);
150
- this.sampleData = audioData;
151
- }
152
-
153
- /**
154
- * @param quality {number}
155
- * @param encodeVorbis {EncodeVorbisFunction}
156
- */
157
- compressSample(quality, encodeVorbis)
158
- {
159
- // no need to compress
160
- if (this.isCompressed)
161
- {
162
- return;
163
- }
164
- // compress, always mono!
165
- try
166
- {
167
- // if the sample rate is too low or too high, resample
168
- let audioData = this.getAudioData();
169
- if (this.sampleRate < 8000 || this.sampleRate > 96000)
170
- {
171
- this.resampleData(RESAMPLE_RATE);
172
- audioData = this.getAudioData();
173
- }
174
- this.compressedData = encodeVorbis([audioData], 1, this.sampleRate, quality);
175
- // flag as compressed
176
- this.sampleType |= 0x10;
177
- this.isCompressed = true;
178
- }
179
- catch (e)
180
- {
181
- SpessaSynthWarn(`Failed to compress ${this.sampleName}. Leaving as uncompressed!`);
182
- this.isCompressed = false;
183
- this.compressedData = undefined;
184
- // flag as uncompressed
185
- this.sampleType &= 0xEF;
186
- }
187
-
188
- }
189
-
190
- /**
191
- * @returns {Float32Array}
192
- */
193
- getAudioData()
194
- {
195
- return this.sampleData;
196
- }
197
- }