spessasynth_core 1.1.3 → 1.1.4

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 (189) hide show
  1. package/LICENSE +3 -26
  2. package/README.md +156 -474
  3. package/index.js +73 -8
  4. package/package.json +21 -8
  5. package/src/externals/fflate/LICENSE +21 -0
  6. package/src/externals/fflate/fflate.min.js +1 -0
  7. package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +12 -0
  8. package/src/externals/stbvorbis_sync/LICENSE +202 -0
  9. package/src/externals/stbvorbis_sync/NOTICE +6 -0
  10. package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +1 -0
  11. package/src/midi/README.md +32 -0
  12. package/src/midi/basic_midi.js +567 -0
  13. package/src/midi/midi_builder.js +202 -0
  14. package/src/midi/midi_loader.js +324 -0
  15. package/{spessasynth_core/midi_parser → src/midi}/midi_message.js +58 -35
  16. package/src/midi/midi_sequence.js +224 -0
  17. package/src/midi/midi_tools/get_note_times.js +154 -0
  18. package/src/midi/midi_tools/midi_editor.js +611 -0
  19. package/src/midi/midi_tools/midi_writer.js +99 -0
  20. package/src/midi/midi_tools/rmidi_writer.js +567 -0
  21. package/src/midi/midi_tools/used_keys_loaded.js +238 -0
  22. package/src/midi/xmf_loader.js +454 -0
  23. package/src/sequencer/README.md +5 -0
  24. package/src/sequencer/events.js +81 -0
  25. package/src/sequencer/play.js +349 -0
  26. package/src/sequencer/process_event.js +165 -0
  27. package/{spessasynth_core/sequencer/worklet_sequencer → src/sequencer}/process_tick.js +103 -84
  28. package/src/sequencer/sequencer_engine.js +367 -0
  29. package/src/sequencer/song_control.js +201 -0
  30. package/src/soundfont/README.md +13 -0
  31. package/src/soundfont/basic_soundfont/basic_instrument.js +77 -0
  32. package/src/soundfont/basic_soundfont/basic_preset.js +336 -0
  33. package/src/soundfont/basic_soundfont/basic_sample.js +206 -0
  34. package/src/soundfont/basic_soundfont/basic_soundfont.js +565 -0
  35. package/src/soundfont/basic_soundfont/basic_zone.js +64 -0
  36. package/src/soundfont/basic_soundfont/basic_zones.js +43 -0
  37. package/src/soundfont/basic_soundfont/generator.js +220 -0
  38. package/src/soundfont/basic_soundfont/modulator.js +378 -0
  39. package/src/soundfont/basic_soundfont/riff_chunk.js +149 -0
  40. package/src/soundfont/basic_soundfont/write_dls/art2.js +173 -0
  41. package/src/soundfont/basic_soundfont/write_dls/articulator.js +49 -0
  42. package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +400 -0
  43. package/src/soundfont/basic_soundfont/write_dls/ins.js +103 -0
  44. package/src/soundfont/basic_soundfont/write_dls/lins.js +18 -0
  45. package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +330 -0
  46. package/src/soundfont/basic_soundfont/write_dls/rgn2.js +121 -0
  47. package/src/soundfont/basic_soundfont/write_dls/wave.js +94 -0
  48. package/src/soundfont/basic_soundfont/write_dls/write_dls.js +119 -0
  49. package/src/soundfont/basic_soundfont/write_dls/wsmp.js +78 -0
  50. package/src/soundfont/basic_soundfont/write_dls/wvpl.js +32 -0
  51. package/src/soundfont/basic_soundfont/write_sf2/ibag.js +39 -0
  52. package/src/soundfont/basic_soundfont/write_sf2/igen.js +80 -0
  53. package/src/soundfont/basic_soundfont/write_sf2/imod.js +46 -0
  54. package/src/soundfont/basic_soundfont/write_sf2/inst.js +34 -0
  55. package/src/soundfont/basic_soundfont/write_sf2/pbag.js +39 -0
  56. package/src/soundfont/basic_soundfont/write_sf2/pgen.js +82 -0
  57. package/src/soundfont/basic_soundfont/write_sf2/phdr.js +42 -0
  58. package/src/soundfont/basic_soundfont/write_sf2/pmod.js +46 -0
  59. package/src/soundfont/basic_soundfont/write_sf2/sdta.js +80 -0
  60. package/src/soundfont/basic_soundfont/write_sf2/shdr.js +55 -0
  61. package/src/soundfont/basic_soundfont/write_sf2/write.js +222 -0
  62. package/src/soundfont/dls/articulator_converter.js +396 -0
  63. package/src/soundfont/dls/dls_destinations.js +38 -0
  64. package/src/soundfont/dls/dls_preset.js +44 -0
  65. package/src/soundfont/dls/dls_sample.js +75 -0
  66. package/src/soundfont/dls/dls_soundfont.js +186 -0
  67. package/src/soundfont/dls/dls_sources.js +62 -0
  68. package/src/soundfont/dls/dls_zone.js +95 -0
  69. package/src/soundfont/dls/read_articulation.js +299 -0
  70. package/src/soundfont/dls/read_instrument.js +121 -0
  71. package/src/soundfont/dls/read_instrument_list.js +17 -0
  72. package/src/soundfont/dls/read_lart.js +35 -0
  73. package/src/soundfont/dls/read_region.js +152 -0
  74. package/src/soundfont/dls/read_samples.js +270 -0
  75. package/src/soundfont/load_soundfont.js +21 -0
  76. package/src/soundfont/read_sf2/generators.js +46 -0
  77. package/{spessasynth_core/soundfont/chunk → src/soundfont/read_sf2}/instruments.js +20 -14
  78. package/src/soundfont/read_sf2/modulators.js +36 -0
  79. package/src/soundfont/read_sf2/presets.js +80 -0
  80. package/src/soundfont/read_sf2/samples.js +304 -0
  81. package/src/soundfont/read_sf2/soundfont.js +305 -0
  82. package/{spessasynth_core/soundfont/chunk → src/soundfont/read_sf2}/zones.js +68 -69
  83. package/src/synthetizer/README.md +7 -0
  84. package/src/synthetizer/audio_engine/README.md +9 -0
  85. package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +266 -0
  86. package/src/synthetizer/audio_engine/engine_components/controller_tables.js +88 -0
  87. package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +150 -0
  88. package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/lfo.js +9 -6
  89. package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +282 -0
  90. package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +467 -0
  91. package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +181 -0
  92. package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/modulator_curves.js +33 -30
  93. package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +221 -0
  94. package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +120 -0
  95. package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/unit_converter.js +11 -4
  96. package/src/synthetizer/audio_engine/engine_components/voice.js +519 -0
  97. package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +401 -0
  98. package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +263 -0
  99. package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +132 -0
  100. package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +48 -0
  101. package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +241 -0
  102. package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +27 -0
  103. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +253 -0
  104. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +66 -0
  105. package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +17 -0
  106. package/src/synthetizer/audio_engine/engine_methods/note_on.js +175 -0
  107. package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +92 -0
  108. package/src/synthetizer/audio_engine/engine_methods/program_change.js +61 -0
  109. package/src/synthetizer/audio_engine/engine_methods/render_voice.js +196 -0
  110. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +30 -0
  111. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +22 -0
  112. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +28 -0
  113. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +31 -0
  114. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +21 -0
  115. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +20 -0
  116. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +55 -0
  117. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +16 -0
  118. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +30 -0
  119. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +63 -0
  120. package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +776 -0
  121. package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +24 -0
  122. package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +33 -0
  123. package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +31 -0
  124. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +15 -0
  125. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +27 -0
  126. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +19 -0
  127. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +27 -0
  128. package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +15 -0
  129. package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +34 -0
  130. package/src/synthetizer/audio_engine/main_processor.js +804 -0
  131. package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +15 -0
  132. package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +175 -0
  133. package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +116 -0
  134. package/src/synthetizer/synth_constants.js +22 -0
  135. package/{spessasynth_core → src}/utils/README.md +1 -0
  136. package/src/utils/buffer_to_wav.js +185 -0
  137. package/src/utils/byte_functions/big_endian.js +32 -0
  138. package/src/utils/byte_functions/little_endian.js +77 -0
  139. package/src/utils/byte_functions/string.js +107 -0
  140. package/src/utils/byte_functions/variable_length_quantity.js +42 -0
  141. package/src/utils/fill_with_defaults.js +21 -0
  142. package/src/utils/indexed_array.js +52 -0
  143. package/{spessasynth_core → src}/utils/loggin.js +70 -78
  144. package/src/utils/other.js +92 -0
  145. package/src/utils/sysex_detector.js +58 -0
  146. package/src/utils/xg_hacks.js +193 -0
  147. package/.idea/inspectionProfiles/Project_Default.xml +0 -10
  148. package/.idea/jsLibraryMappings.xml +0 -6
  149. package/.idea/modules.xml +0 -8
  150. package/.idea/spessasynth_core.iml +0 -12
  151. package/.idea/vcs.xml +0 -6
  152. package/spessasynth_core/midi_parser/README.md +0 -3
  153. package/spessasynth_core/midi_parser/midi_loader.js +0 -386
  154. package/spessasynth_core/sequencer/sequencer.js +0 -202
  155. package/spessasynth_core/sequencer/worklet_sequencer/play.js +0 -209
  156. package/spessasynth_core/sequencer/worklet_sequencer/process_event.js +0 -120
  157. package/spessasynth_core/sequencer/worklet_sequencer/song_control.js +0 -112
  158. package/spessasynth_core/soundfont/README.md +0 -4
  159. package/spessasynth_core/soundfont/chunk/generators.js +0 -205
  160. package/spessasynth_core/soundfont/chunk/modulators.js +0 -232
  161. package/spessasynth_core/soundfont/chunk/presets.js +0 -264
  162. package/spessasynth_core/soundfont/chunk/riff_chunk.js +0 -46
  163. package/spessasynth_core/soundfont/chunk/samples.js +0 -250
  164. package/spessasynth_core/soundfont/soundfont_parser.js +0 -301
  165. package/spessasynth_core/synthetizer/README.md +0 -6
  166. package/spessasynth_core/synthetizer/synthesizer.js +0 -313
  167. package/spessasynth_core/synthetizer/worklet_system/README.md +0 -3
  168. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/controller_control.js +0 -290
  169. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/data_entry.js +0 -280
  170. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_off.js +0 -102
  171. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_on.js +0 -77
  172. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/program_control.js +0 -140
  173. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/system_exclusive.js +0 -266
  174. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -104
  175. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -29
  176. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/voice_control.js +0 -223
  177. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +0 -133
  178. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +0 -73
  179. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +0 -76
  180. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +0 -272
  181. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +0 -83
  182. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_modulator.js +0 -175
  183. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +0 -106
  184. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +0 -285
  185. package/spessasynth_core/utils/buffer_to_wav.js +0 -70
  186. package/spessasynth_core/utils/byte_functions.js +0 -141
  187. package/spessasynth_core/utils/other.js +0 -49
  188. package/spessasynth_core/utils/shiftable_array.js +0 -26
  189. package/spessasynth_core/utils/stbvorbis_sync.js +0 -1877
@@ -1,264 +0,0 @@
1
- import {RiffChunk} from "./riff_chunk.js";
2
- import {PresetZone} from "./zones.js";
3
- import {readBytesAsString, readBytesAsUintLittleEndian} from "../../utils/byte_functions.js";
4
- import {Sample} from "./samples.js";
5
- import { Generator, generatorTypes } from './generators.js'
6
- import { defaultModulators } from './modulators.js'
7
-
8
- /**
9
- * parses soundfont presets, also includes function for getting the generators and samples from midi note and velocity
10
- */
11
-
12
- export class Preset {
13
- /**
14
- * Creates a preset
15
- * @param presetChunk {RiffChunk}
16
- */
17
- constructor(presetChunk) {
18
- this.presetName = readBytesAsString(presetChunk.chunkData, 20)
19
- .trim()
20
- .replace(/\d{3}:\d{3}/, ""); // remove those pesky "000:001"
21
-
22
- this.program = readBytesAsUintLittleEndian(presetChunk.chunkData, 2);
23
- this.bank = readBytesAsUintLittleEndian(presetChunk.chunkData, 2);
24
- this.presetZoneStartIndex = readBytesAsUintLittleEndian(presetChunk.chunkData, 2);
25
- this.presetZonesAmount = 0;
26
- /**
27
- * @type {PresetZone[]}
28
- */
29
- this.presetZones = [];
30
-
31
- /**
32
- * Stores already found getSamplesAndGenerators for reuse
33
- * @type {SampleAndGenerators[][][]}
34
- */
35
- this.foundSamplesAndGenerators = [];
36
- for(let i = 0; i < 128; i++)
37
- {
38
- this.foundSamplesAndGenerators[i] = [];
39
- }
40
-
41
- // skip the DWORDs (4bytes times 3)
42
- readBytesAsUintLittleEndian(presetChunk.chunkData, 12);
43
- }
44
-
45
- /**
46
- * Loads all the preset zones, given the amount
47
- * @param amount {number}
48
- * @param zones {PresetZone[]}
49
- */
50
- getPresetZones(amount, zones) {
51
- this.presetZonesAmount = amount;
52
- for (let i = this.presetZoneStartIndex; i < this.presetZonesAmount + this.presetZoneStartIndex; i++) {
53
- this.presetZones.push(zones[i]);
54
- }
55
- }
56
-
57
- /**
58
- * Preloads all samples (async)
59
- */
60
- preload(keyMin, keyMax)
61
- {
62
- for (let key = keyMin; key < keyMax + 1; key++)
63
- {
64
- for (let velocity = 0; velocity < 128; velocity++)
65
- {
66
- setTimeout(() => {
67
- this.getSamplesAndGenerators(key, velocity).forEach(samandgen => {
68
- if(!samandgen.sample.isSampleLoaded) {
69
- samandgen.sample.loadBufferData().then();
70
- }
71
- })
72
- });
73
- }
74
- }
75
- }
76
-
77
- /**
78
- * @typedef {{
79
- * instrumentGenerators: Generator[],
80
- * presetGenerators: Generator[],
81
- * modulators: Modulator[],
82
- * sample: Sample,
83
- * sampleID: number,
84
- * }} SampleAndGenerators
85
- */
86
-
87
- /**
88
- * Returns generatorTranslator and generators for given note
89
- * @param midiNote {number}
90
- * @param velocity {number}
91
- * @returns {SampleAndGenerators[]}
92
- */
93
- getSamplesAndGenerators(midiNote, velocity)
94
- {
95
- const memorized = this.foundSamplesAndGenerators[midiNote][velocity];
96
- if(memorized)
97
- {
98
- return memorized;
99
- }
100
-
101
- function isInRange(min, max, number) {
102
- return number >= min && number <= max;
103
- }
104
-
105
- /**
106
- * @param mod1 {Modulator}
107
- * @param mod2 {Modulator}
108
- * @returns {boolean}
109
- */
110
- function identicalMod(mod1, mod2)
111
- {
112
- return (mod1.modulatorSource === mod2.modulatorSource)
113
- && (mod1.modulatorDestination === mod2.modulatorDestination)
114
- && (mod1.modulationSecondarySrc === mod2.modulationSecondarySrc)
115
- && (mod1.transformType === mod2.transformType);
116
- }
117
-
118
- /**
119
- * @param main {Generator[]}
120
- * @param adder {Generator[]}
121
- */
122
- function addUnique(main, adder)
123
- {
124
- main.push(...adder.filter(g => !main.find(mg => mg.generatorType === g.generatorType)));
125
- }
126
-
127
- /**
128
- * @param main {Modulator[]}
129
- * @param adder {Modulator[]}
130
- */
131
- function addUniqueMods(main, adder)
132
- {
133
- main.push(...adder.filter(m => !main.find(mm => identicalMod(m, mm))));
134
- }
135
-
136
- /**
137
- * @type {SampleAndGenerators[]}
138
- */
139
- let parsedGeneratorsAndSamples = [];
140
-
141
- /**
142
- * global zone is always first, so it or nothing
143
- * @type {Generator[]}
144
- */
145
- let globalPresetGenerators = this.presetZones[0].isGlobal ? [...this.presetZones[0].generators] : [];
146
-
147
- let globalPresetModulators = this.presetZones[0].isGlobal ? [...this.presetZones[0].modulators] : [];
148
-
149
- // find the preset zones in range
150
- let presetZonesInRange = this.presetZones.filter(currentZone =>
151
- (
152
- isInRange(currentZone.keyRange.min, currentZone.keyRange.max, midiNote)
153
- &&
154
- isInRange(currentZone.velRange.min, currentZone.velRange.max, velocity)
155
- ) && !currentZone.isGlobal);
156
-
157
- presetZonesInRange.forEach(zone =>
158
- {
159
- let presetGenerators = zone.generators;
160
- let presetModulators = zone.modulators;
161
- /**
162
- * global zone is always first, so it or nothing
163
- * @type {Generator[]}
164
- */
165
- let globalInstrumentGenerators = zone.instrument.instrumentZones[0].isGlobal ? [...zone.instrument.instrumentZones[0].generators] : [];
166
- let globalInstrumentModulators = zone.instrument.instrumentZones[0].isGlobal ? [...zone.instrument.instrumentZones[0].modulators] : [];
167
-
168
- let instrumentZonesInRange = zone.instrument.instrumentZones
169
- .filter(currentZone =>
170
- (
171
- isInRange(currentZone.keyRange.min,
172
- currentZone.keyRange.max,
173
- midiNote)
174
- &&
175
- isInRange(currentZone.velRange.min,
176
- currentZone.velRange.max,
177
- velocity)
178
- ) && !currentZone.isGlobal
179
- );
180
-
181
- instrumentZonesInRange.forEach(instrumentZone =>
182
- {
183
- let instrumentGenerators = [...instrumentZone.generators];
184
- let instrumentModulators = [...instrumentZone.modulators];
185
-
186
- addUnique(presetGenerators, globalPresetGenerators);
187
- // add the unique global preset generators (local replace global(
188
-
189
-
190
- // add the unique global instrument generators (local replace global)
191
- addUnique(instrumentGenerators, globalInstrumentGenerators);
192
-
193
- addUniqueMods(presetModulators, globalPresetModulators);
194
- addUniqueMods(instrumentModulators, globalInstrumentModulators);
195
-
196
- // default mods
197
- addUniqueMods(instrumentModulators, defaultModulators);
198
-
199
- /**
200
- * sum preset modulators to instruments (amount) sf spec page 54
201
- * @type {Modulator[]}
202
- */
203
- const finalModulatorList = [...instrumentModulators];
204
- for(let i = 0; i < presetModulators.length; i++)
205
- {
206
- let mod = presetModulators[i];
207
- const identicalInstrumentModulator = finalModulatorList.findIndex(m => identicalMod(mod, m));
208
- if(identicalInstrumentModulator !== -1)
209
- {
210
- // sum the amounts (this makes a new modulator because otherwise it would overwrite the one in the soundfont!!!
211
- finalModulatorList[identicalInstrumentModulator] = finalModulatorList[identicalInstrumentModulator].sumTransform(mod);
212
- }
213
- else
214
- {
215
- finalModulatorList.push(mod);
216
- }
217
- }
218
-
219
-
220
- // combine both generators and add to the final result
221
- parsedGeneratorsAndSamples.push({
222
- instrumentGenerators: instrumentGenerators,
223
- presetGenerators: presetGenerators,
224
- modulators: finalModulatorList,
225
- sample: instrumentZone.sample,
226
- sampleID: instrumentZone.generators.find(g => g.generatorType === generatorTypes.sampleID).generatorValue
227
- });
228
- });
229
- });
230
-
231
- // save and return
232
- this.foundSamplesAndGenerators[midiNote][velocity] = parsedGeneratorsAndSamples;
233
- return parsedGeneratorsAndSamples;
234
- }
235
- }
236
-
237
- /**
238
- * Reads the presets
239
- * @param presetChunk {RiffChunk}
240
- * @param presetZones {PresetZone[]}
241
- * @returns {Preset[]}
242
- */
243
- export function readPresets(presetChunk, presetZones)
244
- {
245
- /**
246
- * @type {Preset[]}
247
- */
248
- let presets = [];
249
- while(presetChunk.chunkData.length > presetChunk.chunkData.currentIndex)
250
- {
251
- let preset = new Preset(presetChunk);
252
- if(presets.length > 0)
253
- {
254
- let presetZonesAmount = preset.presetZoneStartIndex - presets[presets.length - 1].presetZoneStartIndex;
255
- presets[presets.length - 1].getPresetZones(presetZonesAmount, presetZones);
256
- }
257
- presets.push(preset);
258
- }
259
- // remove EOP
260
- if (presets.length > 1) {
261
- presets.pop();
262
- }
263
- return presets;
264
- }
@@ -1,46 +0,0 @@
1
- import { ShiftableByteArray } from '../../utils/shiftable_array.js'
2
- import { readBytesAsString, readBytesAsUintLittleEndian } from '../../utils/byte_functions.js'
3
-
4
- /**
5
- * riff_chunk.js
6
- * reads a riff chunk and stores it as a class
7
- */
8
-
9
- export class RiffChunk
10
- {
11
- /**
12
- * Creates a new riff chunk
13
- * @constructor
14
- * @param header {string}
15
- * @param size {number}
16
- * @param data {ShiftableByteArray}
17
- */
18
- constructor(header, size, data) {
19
- this.header = header;
20
- this.size = size;
21
- this.chunkData = data;
22
- }
23
-
24
- }
25
-
26
- /**
27
- * @param dataArray {ShiftableByteArray}
28
- * @param readData {boolean}
29
- * @returns {RiffChunk}
30
- */
31
- export function readRIFFChunk(dataArray, readData = true) {
32
- let header = readBytesAsString(dataArray, 4)
33
-
34
- let size = readBytesAsUintLittleEndian(dataArray, 4)
35
- let chunkData = undefined
36
- if (readData) {
37
- chunkData = new ShiftableByteArray(size)
38
- chunkData.set(dataArray.slice(dataArray.currentIndex, dataArray.currentIndex + size))
39
- dataArray.currentIndex += size
40
- // for (let i = 0; i < size; i++) {
41
- // chunkData[i] = readByte(dataArray);
42
- // }
43
- }
44
-
45
- return new RiffChunk(header, size, chunkData)
46
- }
@@ -1,250 +0,0 @@
1
- import {RiffChunk} from "./riff_chunk.js";
2
- import {ShiftableByteArray} from "../../utils/shiftable_array.js";
3
- import {readByte, readBytesAsUintLittleEndian, readBytesAsString, signedInt8} from "../../utils/byte_functions.js";
4
- import { stbvorbis } from '../../utils/stbvorbis_sync.js'
5
- import { SpessaSynthWarn } from '../../utils/loggin.js'
6
-
7
- /**
8
- * samples.js
9
- * purpose: parses soundfont samples, resamples if needed.
10
- * loads sample data, handles async loading of sf3 compressed samples
11
- */
12
-
13
- /**
14
- * Reads the generatorTranslator from the shdr chunk
15
- * @param sampleHeadersChunk {RiffChunk}
16
- * @param smplChunkData {ShiftableByteArray}
17
- * @returns {Sample[]}
18
- */
19
- export function readSamples(sampleHeadersChunk, smplChunkData)
20
- {
21
- /**
22
- * @type {Sample[]}
23
- */
24
- let samples = [];
25
- while(sampleHeadersChunk.chunkData.length > sampleHeadersChunk.chunkData.currentIndex)
26
- {
27
- const sample = readSample(sampleHeadersChunk.chunkData, smplChunkData);
28
- samples.push(sample);
29
- }
30
- return samples;
31
- }
32
-
33
- /**
34
- * Reads it into a sample
35
- * @param sampleHeaderData {ShiftableByteArray}
36
- * @param smplArrayData {ShiftableByteArray}
37
- * @returns {Sample}
38
- */
39
- function readSample(sampleHeaderData, smplArrayData) {
40
-
41
- // read the sample name
42
- let sampleName = readBytesAsString(sampleHeaderData, 20);
43
-
44
- // read the sample start index
45
- let sampleStartIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
46
-
47
- // read the sample end index
48
- let sampleEndIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
49
-
50
- // read the sample looping start index
51
- let sampleLoopStartIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
52
-
53
- // read the sample looping end index
54
- let sampleLoopEndIndex = readBytesAsUintLittleEndian(sampleHeaderData, 4) * 2;
55
-
56
- // read the sample rate
57
- let sampleRate = readBytesAsUintLittleEndian(sampleHeaderData, 4);
58
-
59
- // read the original sample pitch
60
- let samplePitch = readByte(sampleHeaderData);
61
- if(samplePitch === 255)
62
- {
63
- // if it's 255, then default to 60
64
- samplePitch = 60;
65
- }
66
-
67
- // readt the sample pitch correction
68
- let samplePitchCorrection = signedInt8(readByte(sampleHeaderData));
69
-
70
-
71
- // read the link to the other channel
72
- let sampleLink = readBytesAsUintLittleEndian(sampleHeaderData, 2);
73
- let sampleType = readBytesAsUintLittleEndian(sampleHeaderData, 2);
74
-
75
-
76
-
77
- return new Sample(sampleName,
78
- sampleStartIndex,
79
- sampleEndIndex,
80
- sampleLoopStartIndex,
81
- sampleLoopEndIndex,
82
- sampleRate,
83
- samplePitch,
84
- samplePitchCorrection,
85
- sampleLink,
86
- sampleType,
87
- smplArrayData);
88
- }
89
-
90
- export class Sample {
91
- /**
92
- * Creates a sample
93
- * @param sampleName {string}
94
- * @param sampleStartIndex {number}
95
- * @param sampleEndIndex {number}
96
- * @param sampleLoopStartIndex {number}
97
- * @param sampleLoopEndIndex {number}
98
- * @param sampleRate {number}
99
- * @param samplePitch {number}
100
- * @param samplePitchCorrection {number}
101
- * @param sampleLink {number}
102
- * @param sampleType {number}
103
- * @param smplArr {ShiftableByteArray}
104
- */
105
- constructor(sampleName,
106
- sampleStartIndex,
107
- sampleEndIndex,
108
- sampleLoopStartIndex,
109
- sampleLoopEndIndex,
110
- sampleRate,
111
- samplePitch,
112
- samplePitchCorrection,
113
- sampleLink,
114
- sampleType,
115
- smplArr) {
116
- this.sampleName = sampleName
117
- // in bytes
118
- this.sampleStartIndex = sampleStartIndex;
119
- this.sampleEndIndex = sampleEndIndex;
120
- this.isSampleLoaded = false;
121
-
122
- this.sampleLoopStartIndex = sampleLoopStartIndex - sampleStartIndex;
123
- this.sampleLoopEndIndex = sampleLoopEndIndex - sampleStartIndex;
124
- this.sampleRate = sampleRate;
125
- this.samplePitch = samplePitch;
126
- this.samplePitchCorrection = samplePitchCorrection;
127
- this.sampleLink = sampleLink;
128
- this.sampleType = sampleType;
129
- // in bytes
130
- this.sampleLength = this.sampleEndIndex - this.sampleStartIndex;
131
- this.indexRatio = 1;
132
- this.sampleDataArray = smplArr;
133
- this.sampleData = new Float32Array(0);
134
- this.sampleLengthSeconds = this.sampleLength / (this.sampleRate * 2);
135
- this.loopAllowed = this.sampleLoopStartIndex !== this.sampleLoopEndIndex;
136
- this.isCompressed = (this.sampleType & 0x10) > 0;
137
-
138
- if (this.sampleLength < 1 || this.sampleName.substring(0, 3).toLowerCase() === "eos") {
139
- return;
140
- }
141
-
142
- if(this.isCompressed)
143
- {
144
- // correct loop points
145
- this.sampleLoopStartIndex += this.sampleStartIndex;
146
- this.sampleLoopEndIndex += this.sampleStartIndex;
147
- this.sampleLength = 99999999; // set to 999999 before we decode it
148
- }
149
-
150
- }
151
-
152
- /**
153
- * @param smplArr {ShiftableByteArray}
154
- */
155
- decodeVorbis(smplArr)
156
- {
157
- if (this.sampleLength < 1) {
158
- // eos, do not do anything
159
- return;
160
- }
161
- // get the compressed byte stream
162
- const smplStart = smplArr.currentIndex;
163
- const buff = smplArr.slice(this.sampleStartIndex / 2 + smplStart, this.sampleEndIndex / 2 + smplStart);
164
- // reset array and being decoding
165
- this.sampleData = new Float32Array(0);
166
- /**
167
- * @type {{data: Float32Array[], error: (string|null), sampleRate: number, eof: boolean}}
168
- */
169
- const vorbis = stbvorbis.decode(buff.buffer);
170
- this.sampleData = vorbis.data[0];
171
- }
172
-
173
- /**
174
- * creates a sample sampleData and stores it for reuse
175
- * @param startAddrOffset {number}
176
- * @param endAddrOffset {number}
177
- * @returns {Float32Array} The audioData
178
- */
179
- getAudioData(startAddrOffset = 0, endAddrOffset = 0) {
180
- if (!this.isSampleLoaded) {
181
- // start loading data if not loaded
182
- return this.loadBufferData();
183
- }
184
- // if no offset, return saved sampleData
185
- if (this.sampleData && startAddrOffset === 0 && endAddrOffset === 0) {
186
- return this.sampleData;
187
- }
188
-
189
- return this.getOffsetData(startAddrOffset, endAddrOffset);
190
- }
191
-
192
- /**
193
- * @param smplArr {ShiftableByteArray}
194
- * @returns {Float32Array}
195
- */
196
- loadUncompressedData(smplArr)
197
- {
198
- if(this.isCompressed)
199
- {
200
- SpessaSynthWarn("Trying to load a compressed sample via loadUncompressedData()... aborting!");
201
- return new Float32Array(0);
202
- }
203
-
204
- // read the sample data
205
- let audioData = new Float32Array(this.sampleLength / 2 + 1);
206
- const dataStartIndex = smplArr.currentIndex;
207
- let convertedSigned16 = new Int16Array(
208
- smplArr.slice(dataStartIndex + this.sampleStartIndex, dataStartIndex + this.sampleEndIndex)
209
- .buffer
210
- );
211
-
212
- // convert to float
213
- for(let i = 0; i < convertedSigned16.length; i++)
214
- {
215
- audioData[i] = convertedSigned16[i] / 32768;
216
- }
217
-
218
- this.sampleData = audioData;
219
- this.isSampleLoaded = true;
220
- return audioData;
221
- }
222
-
223
- /**
224
- * @returns {Float32Array}
225
- */
226
- loadBufferData() {
227
- if (this.sampleLength < 1) {
228
- // eos, do not do anything
229
- return new Float32Array(1);
230
- }
231
-
232
- if(this.isCompressed)
233
- {
234
- this.decodeVorbis(this.sampleDataArray);
235
- this.isSampleLoaded = true;
236
- return this.sampleData;
237
- }
238
- return this.loadUncompressedData(this.sampleDataArray);
239
- }
240
-
241
- /**
242
- * Creates a sample sampleData
243
- * @param startOffset {number}
244
- * @param endOffset {number}
245
- * @returns {Float32Array}
246
- */
247
- getOffsetData(startOffset, endOffset) {
248
- return this.sampleData.subarray(startOffset, this.sampleData.length - endOffset + 1);
249
- }
250
- }