spessasynth_lib 3.25.22 → 3.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/README.md +29 -114
  2. package/index.js +33 -33
  3. package/package.json +16 -6
  4. package/external_midi/README.md +0 -4
  5. package/external_midi/midi_handler.js +0 -130
  6. package/external_midi/web_midi_link.js +0 -43
  7. package/externals/fflate/LICENSE +0 -21
  8. package/externals/fflate/fflate.min.js +0 -1
  9. package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
  10. package/externals/stbvorbis_sync/LICENSE +0 -202
  11. package/externals/stbvorbis_sync/NOTICE +0 -6
  12. package/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
  13. package/midi/README.md +0 -32
  14. package/midi/basic_midi.js +0 -565
  15. package/midi/midi_builder.js +0 -202
  16. package/midi/midi_data.js +0 -63
  17. package/midi/midi_loader.js +0 -324
  18. package/midi/midi_message.js +0 -254
  19. package/midi/midi_sequence.js +0 -225
  20. package/midi/midi_tools/get_note_times.js +0 -154
  21. package/midi/midi_tools/midi_editor.js +0 -611
  22. package/midi/midi_tools/midi_writer.js +0 -99
  23. package/midi/midi_tools/rmidi_writer.js +0 -567
  24. package/midi/midi_tools/used_keys_loaded.js +0 -238
  25. package/midi/xmf_loader.js +0 -454
  26. package/sequencer/README.md +0 -32
  27. package/sequencer/sequencer_engine/events.js +0 -207
  28. package/sequencer/sequencer_engine/play.js +0 -353
  29. package/sequencer/sequencer_engine/process_event.js +0 -169
  30. package/sequencer/sequencer_engine/process_tick.js +0 -106
  31. package/sequencer/sequencer_engine/sequencer_engine.js +0 -337
  32. package/sequencer/sequencer_engine/song_control.js +0 -229
  33. package/sequencer/worklet_wrapper/default_sequencer_options.js +0 -8
  34. package/sequencer/worklet_wrapper/sequencer.js +0 -807
  35. package/sequencer/worklet_wrapper/sequencer_message.js +0 -53
  36. package/soundfont/README.md +0 -13
  37. package/soundfont/basic_soundfont/basic_instrument.js +0 -77
  38. package/soundfont/basic_soundfont/basic_preset.js +0 -336
  39. package/soundfont/basic_soundfont/basic_sample.js +0 -197
  40. package/soundfont/basic_soundfont/basic_soundfont.js +0 -565
  41. package/soundfont/basic_soundfont/basic_zone.js +0 -64
  42. package/soundfont/basic_soundfont/basic_zones.js +0 -43
  43. package/soundfont/basic_soundfont/generator.js +0 -220
  44. package/soundfont/basic_soundfont/modulator.js +0 -378
  45. package/soundfont/basic_soundfont/riff_chunk.js +0 -149
  46. package/soundfont/basic_soundfont/write_dls/art2.js +0 -173
  47. package/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
  48. package/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -400
  49. package/soundfont/basic_soundfont/write_dls/ins.js +0 -103
  50. package/soundfont/basic_soundfont/write_dls/lins.js +0 -18
  51. package/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
  52. package/soundfont/basic_soundfont/write_dls/rgn2.js +0 -121
  53. package/soundfont/basic_soundfont/write_dls/wave.js +0 -94
  54. package/soundfont/basic_soundfont/write_dls/write_dls.js +0 -119
  55. package/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
  56. package/soundfont/basic_soundfont/write_dls/wvpl.js +0 -32
  57. package/soundfont/basic_soundfont/write_sf2/ibag.js +0 -39
  58. package/soundfont/basic_soundfont/write_sf2/igen.js +0 -80
  59. package/soundfont/basic_soundfont/write_sf2/imod.js +0 -46
  60. package/soundfont/basic_soundfont/write_sf2/inst.js +0 -34
  61. package/soundfont/basic_soundfont/write_sf2/pbag.js +0 -39
  62. package/soundfont/basic_soundfont/write_sf2/pgen.js +0 -82
  63. package/soundfont/basic_soundfont/write_sf2/phdr.js +0 -42
  64. package/soundfont/basic_soundfont/write_sf2/pmod.js +0 -46
  65. package/soundfont/basic_soundfont/write_sf2/sdta.js +0 -80
  66. package/soundfont/basic_soundfont/write_sf2/shdr.js +0 -55
  67. package/soundfont/basic_soundfont/write_sf2/write.js +0 -222
  68. package/soundfont/dls/articulator_converter.js +0 -396
  69. package/soundfont/dls/dls_destinations.js +0 -38
  70. package/soundfont/dls/dls_preset.js +0 -44
  71. package/soundfont/dls/dls_sample.js +0 -75
  72. package/soundfont/dls/dls_soundfont.js +0 -186
  73. package/soundfont/dls/dls_sources.js +0 -62
  74. package/soundfont/dls/dls_zone.js +0 -95
  75. package/soundfont/dls/read_articulation.js +0 -299
  76. package/soundfont/dls/read_instrument.js +0 -121
  77. package/soundfont/dls/read_instrument_list.js +0 -17
  78. package/soundfont/dls/read_lart.js +0 -35
  79. package/soundfont/dls/read_region.js +0 -152
  80. package/soundfont/dls/read_samples.js +0 -270
  81. package/soundfont/load_soundfont.js +0 -21
  82. package/soundfont/read_sf2/generators.js +0 -46
  83. package/soundfont/read_sf2/instruments.js +0 -66
  84. package/soundfont/read_sf2/modulators.js +0 -36
  85. package/soundfont/read_sf2/presets.js +0 -80
  86. package/soundfont/read_sf2/samples.js +0 -304
  87. package/soundfont/read_sf2/soundfont.js +0 -305
  88. package/soundfont/read_sf2/zones.js +0 -263
  89. package/synthetizer/README.md +0 -10
  90. package/synthetizer/audio_effects/effects_config.js +0 -25
  91. package/synthetizer/audio_effects/fancy_chorus.js +0 -162
  92. package/synthetizer/audio_effects/rb_compressed.min.js +0 -1
  93. package/synthetizer/audio_effects/reverb.js +0 -35
  94. package/synthetizer/audio_effects/reverb_as_binary.js +0 -18
  95. package/synthetizer/audio_engine/README.md +0 -25
  96. package/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -266
  97. package/synthetizer/audio_engine/engine_components/controller_tables.js +0 -88
  98. package/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -149
  99. package/synthetizer/audio_engine/engine_components/lfo.js +0 -26
  100. package/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
  101. package/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -471
  102. package/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
  103. package/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
  104. package/synthetizer/audio_engine/engine_components/soundfont_manager/sfman_message.js +0 -9
  105. package/synthetizer/audio_engine/engine_components/soundfont_manager/soundfont_manager.js +0 -254
  106. package/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -120
  107. package/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
  108. package/synthetizer/audio_engine/engine_components/voice.js +0 -519
  109. package/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -401
  110. package/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -263
  111. package/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -132
  112. package/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
  113. package/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -241
  114. package/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -27
  115. package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -253
  116. package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -66
  117. package/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
  118. package/synthetizer/audio_engine/engine_methods/note_on.js +0 -174
  119. package/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
  120. package/synthetizer/audio_engine/engine_methods/program_change.js +0 -61
  121. package/synthetizer/audio_engine/engine_methods/render_voice.js +0 -196
  122. package/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +0 -30
  123. package/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -22
  124. package/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +0 -40
  125. package/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +0 -34
  126. package/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +0 -21
  127. package/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -20
  128. package/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -55
  129. package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
  130. package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
  131. package/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
  132. package/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -744
  133. package/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -24
  134. package/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -33
  135. package/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -31
  136. package/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
  137. package/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
  138. package/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
  139. package/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
  140. package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
  141. package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
  142. package/synthetizer/audio_engine/main_processor.js +0 -765
  143. package/synthetizer/audio_engine/message_protocol/README.md +0 -13
  144. package/synthetizer/audio_engine/message_protocol/message_sending.js +0 -22
  145. package/synthetizer/audio_engine/message_protocol/worklet_message.js +0 -107
  146. package/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -14
  147. package/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
  148. package/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -122
  149. package/synthetizer/synth_constants.js +0 -20
  150. package/synthetizer/worklet_processor.min.js +0 -21
  151. package/synthetizer/worklet_wrapper/key_modifier_manager.js +0 -104
  152. package/synthetizer/worklet_wrapper/synth_event_handler.js +0 -214
  153. package/synthetizer/worklet_wrapper/synth_soundfont_manager.js +0 -111
  154. package/synthetizer/worklet_wrapper/synthetizer.js +0 -1027
  155. package/synthetizer/worklet_wrapper/worklet_processor.js +0 -340
  156. package/synthetizer/worklet_wrapper/worklet_url.js +0 -16
  157. package/utils/README.md +0 -5
  158. package/utils/buffer_to_wav.js +0 -186
  159. package/utils/byte_functions/big_endian.js +0 -32
  160. package/utils/byte_functions/little_endian.js +0 -77
  161. package/utils/byte_functions/string.js +0 -107
  162. package/utils/byte_functions/variable_length_quantity.js +0 -42
  163. package/utils/fill_with_defaults.js +0 -21
  164. package/utils/indexed_array.js +0 -52
  165. package/utils/loggin.js +0 -79
  166. package/utils/other.js +0 -92
  167. package/utils/sysex_detector.js +0 -58
  168. package/utils/xg_hacks.js +0 -193
@@ -1,53 +0,0 @@
1
- export const SongChangeType = {
2
- backwards: 0, // no additional data
3
- forwards: 1, // no additional data
4
- shuffleOn: 2, // no additional data
5
- shuffleOff: 3, // no additional data
6
- index: 4 // songIndex<number>
7
- };
8
-
9
- /**
10
- * @enum {number}
11
- * @property {number} loadNewSongList - 0 -> [...song<MIDI>]
12
- * @property {number} pause - 1 -> isFinished<boolean>
13
- * @property {number} stop - 2 -> (no data)
14
- * @property {number} play - 3 -> resetTime<boolean>
15
- * @property {number} setTime - 4 -> time<number>
16
- * @property {number} changeMIDIMessageSending - 5 -> sendMIDIMessages<boolean>
17
- * @property {number} setPlaybackRate - 6 -> playbackRate<number>
18
- * @property {number} setLoop - 7 -> [loop<boolean>, count<number>]
19
- * @property {number} changeSong - 8 -> [changeType<SongChangeType>, data<number>]
20
- * @property {number} getMIDI - 9 -> (no data)
21
- * @property {number} setSkipToFirstNote -10 -> skipToFirstNoteOn<boolean>
22
- * @property {number} setPreservePlaybackState -11 -> preservePlaybackState<boolean>
23
- */
24
- export const SpessaSynthSequencerMessageType = {
25
- loadNewSongList: 0,
26
- pause: 1,
27
- stop: 2,
28
- play: 3,
29
- setTime: 4,
30
- changeMIDIMessageSending: 5,
31
- setPlaybackRate: 6,
32
- setLoop: 7,
33
- changeSong: 8,
34
- getMIDI: 9,
35
- setSkipToFirstNote: 10,
36
- setPreservePlaybackState: 11
37
- };
38
-
39
- /**
40
- *
41
- * @enum {number}
42
- */
43
- export const SpessaSynthSequencerReturnMessageType = {
44
- midiEvent: 0, // [...midiEventBytes<number>]
45
- songChange: 1, // [songIndex<number>, isAutoPlayed<boolean>]
46
- timeChange: 2, // newAbsoluteTime<number>
47
- pause: 3, // no data
48
- getMIDI: 4, // midiData<MIDI>
49
- midiError: 5, // errorMSG<string>
50
- metaEvent: 6, // [event<MIDIMessage>, trackNum<number>]
51
- loopCountChange: 7, // newLoopCount<number>
52
- songListChange: 8 // songListData<MIDIData[]>
53
- };
@@ -1,13 +0,0 @@
1
- ## This is the SoundFont2 parsing library.
2
-
3
- The code here is responsible for parsing the SoundFont2 file and
4
- providing an easy way to get the data out.
5
- Default modulators are also stored here (in `modulators.js`)
6
-
7
- `basic_soundfont` folder contains the classes that represent the soundfont file.
8
-
9
- `read_sf2` folder contains the code for reading an `.sf2` file.
10
-
11
- `write` folder contains the code for writing out an `.sf2` file.
12
-
13
- `dls` folder contains the code for reading a `.dls` file (and converting in into a soundfont representation).
@@ -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
- }