spessasynth_lib 3.25.23 → 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 -104
  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 -335
  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.js +0 -228
  105. package/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -120
  106. package/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
  107. package/synthetizer/audio_engine/engine_components/voice.js +0 -519
  108. package/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -401
  109. package/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -263
  110. package/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -132
  111. package/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
  112. package/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -241
  113. package/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -27
  114. package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -253
  115. package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -66
  116. package/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
  117. package/synthetizer/audio_engine/engine_methods/note_on.js +0 -175
  118. package/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
  119. package/synthetizer/audio_engine/engine_methods/program_change.js +0 -61
  120. package/synthetizer/audio_engine/engine_methods/render_voice.js +0 -196
  121. package/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +0 -30
  122. package/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -22
  123. package/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +0 -40
  124. package/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +0 -34
  125. package/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +0 -21
  126. package/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -20
  127. package/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -55
  128. package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
  129. package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
  130. package/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
  131. package/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -776
  132. package/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -24
  133. package/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -33
  134. package/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -31
  135. package/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
  136. package/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
  137. package/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
  138. package/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
  139. package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
  140. package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
  141. package/synthetizer/audio_engine/main_processor.js +0 -765
  142. package/synthetizer/audio_engine/message_protocol/README.md +0 -13
  143. package/synthetizer/audio_engine/message_protocol/message_sending.js +0 -22
  144. package/synthetizer/audio_engine/message_protocol/worklet_message.js +0 -107
  145. package/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -14
  146. package/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
  147. package/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -122
  148. package/synthetizer/synth_constants.js +0 -20
  149. package/synthetizer/worklet_processor.min.js +0 -21
  150. package/synthetizer/worklet_wrapper/key_modifier_manager.js +0 -104
  151. package/synthetizer/worklet_wrapper/sfman_message.js +0 -9
  152. package/synthetizer/worklet_wrapper/synth_event_handler.js +0 -214
  153. package/synthetizer/worklet_wrapper/synth_soundfont_manager.js +0 -109
  154. package/synthetizer/worklet_wrapper/synthetizer.js +0 -1027
  155. package/synthetizer/worklet_wrapper/worklet_processor.js +0 -454
  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,454 +0,0 @@
1
- import { consoleColors } from "../../utils/other.js";
2
- import { SpessaSynthInfo, SpessaSynthLogging, SpessaSynthWarn } from "../../utils/loggin.js";
3
- import { SpessaSynthProcessor } from "../audio_engine/main_processor.js";
4
- import {
5
- ALL_CHANNELS_OR_DIFFERENT_ACTION,
6
- returnMessageType,
7
- workletMessageType
8
- } from "../audio_engine/message_protocol/worklet_message.js";
9
- import { SynthesizerSnapshot } from "../audio_engine/snapshot/synthesizer_snapshot.js";
10
- import { WORKLET_PROCESSOR_NAME } from "./worklet_url.js";
11
- import { MIDI_CHANNEL_COUNT } from "../synth_constants.js";
12
- import { workletKeyModifierMessageType } from "../audio_engine/engine_components/key_modifier_manager.js";
13
- import { masterParameterType } from "../audio_engine/engine_methods/controller_control/master_parameters.js";
14
- import { WorkletSoundfontManagerMessageType } from "./sfman_message.js";
15
- import {
16
- SongChangeType,
17
- SpessaSynthSequencerMessageType,
18
- SpessaSynthSequencerReturnMessageType
19
- } from "../../sequencer/worklet_wrapper/sequencer_message.js";
20
-
21
-
22
- // a worklet processor wrapper for the synthesizer core
23
- class WorkletSpessaProcessor extends AudioWorkletProcessor
24
- {
25
- /**
26
- * If the worklet is alive
27
- * @type {boolean}
28
- */
29
- alive = true;
30
-
31
- /**
32
- * Instead of 18 stereo outputs, there's one with 32 channels (no effects)
33
- * @type {boolean}
34
- */
35
- oneOutputMode = false;
36
-
37
- /**
38
- * Creates a new worklet synthesis system. contains all channels
39
- * @param options {{
40
- * processorOptions: {
41
- * midiChannels: number,
42
- * soundfont: ArrayBuffer,
43
- * enableEventSystem: boolean,
44
- * startRenderingData: StartRenderingDataConfig
45
- * }}}
46
- */
47
- constructor(options)
48
- {
49
- super();
50
- const opts = options.processorOptions;
51
-
52
-
53
- // one output is indicated by setting midiChannels to 1
54
- this.oneOutputMode = opts.midiChannels === 1;
55
-
56
- // noinspection JSUnresolvedReference
57
- /**
58
- * Initialize the synthesis engine
59
- * @type {SpessaSynthProcessor}
60
- */
61
- this.synthesizer = new SpessaSynthProcessor(
62
- MIDI_CHANNEL_COUNT, // midi channel count (16)
63
- opts.soundfont, // initial sound bank
64
- sampleRate, // AudioWorkletGlobalScope
65
- this.postMessageToMainThread.bind(this), // connect to message port
66
- !this.oneOutputMode, // one output mode disables effects
67
- opts?.enableEventSystem, // enable message port?
68
- opts?.startRenderingData, // start rendering?
69
- currentTime // AudioWorkletGlobalScope, sync with audioContext time
70
- );
71
-
72
- // receive messages from the main thread
73
- this.port.onmessage = e => this.handleMessage(e.data);
74
- }
75
-
76
- /**
77
- * @param data {WorkletReturnMessage}
78
- */
79
- postMessageToMainThread(data)
80
- {
81
- this.port.postMessage(data);
82
- }
83
-
84
- /**
85
- * @this {WorkletSpessaProcessor}
86
- * @param message {WorkletMessage}
87
- */
88
- handleMessage(message)
89
- {
90
- const data = message.messageData;
91
- const channel = message.channelNumber;
92
- /**
93
- * @type {MidiAudioChannel}
94
- */
95
- let channelObject;
96
- if (channel >= 0)
97
- {
98
- channelObject = this.synthesizer.midiAudioChannels[channel];
99
- if (channelObject === undefined)
100
- {
101
- SpessaSynthWarn(`Trying to access channel ${channel} which does not exist... ignoring!`);
102
- return;
103
- }
104
- }
105
- switch (message.messageType)
106
- {
107
- case workletMessageType.midiMessage:
108
- this.synthesizer.processMessage(...data);
109
- break;
110
-
111
- case workletMessageType.customcCcChange:
112
- // custom controller change
113
- channelObject.setCustomController(data[0], data[1]);
114
- channelObject.updateChannelTuning();
115
- break;
116
-
117
- case workletMessageType.ccReset:
118
- if (channel === ALL_CHANNELS_OR_DIFFERENT_ACTION)
119
- {
120
- this.synthesizer.resetAllControllers();
121
- }
122
- else
123
- {
124
- channelObject.resetControllers();
125
- }
126
- break;
127
-
128
- case workletMessageType.setChannelVibrato:
129
- if (channel === ALL_CHANNELS_OR_DIFFERENT_ACTION)
130
- {
131
- for (let i = 0; i < this.synthesizer.midiAudioChannels.length; i++)
132
- {
133
- const chan = this.synthesizer.midiAudioChannels[i];
134
- if (data.rate === ALL_CHANNELS_OR_DIFFERENT_ACTION)
135
- {
136
- chan.disableAndLockGSNRPN();
137
- }
138
- else
139
- {
140
- chan.setVibrato(data.depth, data.rate, data.delay);
141
- }
142
- }
143
- }
144
- else if (data.rate === ALL_CHANNELS_OR_DIFFERENT_ACTION)
145
- {
146
- channelObject.disableAndLockGSNRPN();
147
- }
148
- else
149
- {
150
- channelObject.setVibrato(data.depth, data.rate, data.delay);
151
- }
152
- break;
153
-
154
- case workletMessageType.stopAll:
155
- if (channel === ALL_CHANNELS_OR_DIFFERENT_ACTION)
156
- {
157
- this.synthesizer.stopAllChannels(data === 1);
158
- }
159
- else
160
- {
161
- channelObject.stopAllNotes(data === 1);
162
- }
163
- break;
164
-
165
- case workletMessageType.killNotes:
166
- this.synthesizer.voiceKilling(data);
167
- break;
168
-
169
- case workletMessageType.muteChannel:
170
- channelObject.muteChannel(data);
171
- break;
172
-
173
- case workletMessageType.addNewChannel:
174
- this.synthesizer.createWorkletChannel(true);
175
- break;
176
-
177
- case workletMessageType.debugMessage:
178
- this.synthesizer.debugMessage();
179
- break;
180
-
181
- case workletMessageType.setMasterParameter:
182
- /**
183
- * @type {masterParameterType}
184
- */
185
- const type = data[0];
186
- const value = data[1];
187
- this.synthesizer.setMasterParameter(type, value);
188
- break;
189
-
190
- case workletMessageType.setDrums:
191
- channelObject.setDrums(data);
192
- break;
193
-
194
- case workletMessageType.transpose:
195
- if (channel === ALL_CHANNELS_OR_DIFFERENT_ACTION)
196
- {
197
- this.synthesizer.transposeAllChannels(data[0], data[1]);
198
- }
199
- else
200
- {
201
- channelObject.transposeChannel(data[0], data[1]);
202
- }
203
- break;
204
-
205
- case workletMessageType.highPerformanceMode:
206
- this.synthesizer.highPerformanceMode = data;
207
- break;
208
-
209
- case workletMessageType.lockController:
210
- if (data[0] === ALL_CHANNELS_OR_DIFFERENT_ACTION)
211
- {
212
- channelObject.setPresetLock(data[1]);
213
- }
214
- else
215
- {
216
- channelObject.lockedControllers[data[0]] = data[1];
217
- }
218
- break;
219
-
220
- case workletMessageType.sequencerSpecific:
221
- const seq = this.synthesizer.sequencer;
222
- const messageData = data.messageData;
223
- const messageType = data.messageType;
224
- switch (messageType)
225
- {
226
- default:
227
- break;
228
-
229
- case SpessaSynthSequencerMessageType.loadNewSongList:
230
- seq.loadNewSongList(messageData[0], messageData[1]);
231
- break;
232
-
233
- case SpessaSynthSequencerMessageType.pause:
234
- seq.pause();
235
- break;
236
-
237
- case SpessaSynthSequencerMessageType.play:
238
- seq.play(messageData);
239
- break;
240
-
241
- case SpessaSynthSequencerMessageType.stop:
242
- seq.stop();
243
- break;
244
-
245
- case SpessaSynthSequencerMessageType.setTime:
246
- seq.currentTime = messageData;
247
- break;
248
-
249
- case SpessaSynthSequencerMessageType.changeMIDIMessageSending:
250
- seq.sendMIDIMessages = messageData;
251
- break;
252
-
253
- case SpessaSynthSequencerMessageType.setPlaybackRate:
254
- seq.playbackRate = messageData;
255
- break;
256
-
257
- case SpessaSynthSequencerMessageType.setLoop:
258
- const [loop, count] = messageData;
259
- seq.loop = loop;
260
- if (count === ALL_CHANNELS_OR_DIFFERENT_ACTION)
261
- {
262
- seq.loopCount = Infinity;
263
- }
264
- else
265
- {
266
- seq.loopCount = count;
267
- }
268
- break;
269
-
270
- case SpessaSynthSequencerMessageType.changeSong:
271
- switch (messageData[0])
272
- {
273
- case SongChangeType.forwards:
274
- seq.nextSong();
275
- break;
276
-
277
- case SongChangeType.backwards:
278
- seq.previousSong();
279
- break;
280
-
281
- case SongChangeType.shuffleOff:
282
- seq.shuffleMode = false;
283
- seq.songIndex = seq.shuffledSongIndexes[seq.songIndex];
284
- break;
285
-
286
- case SongChangeType.shuffleOn:
287
- seq.shuffleMode = true;
288
- seq.shuffleSongIndexes();
289
- seq.songIndex = 0;
290
- seq.loadCurrentSong();
291
- break;
292
-
293
- case SongChangeType.index:
294
- seq.songIndex = messageData[1];
295
- seq.loadCurrentSong();
296
- break;
297
- }
298
- break;
299
-
300
- case SpessaSynthSequencerMessageType.getMIDI:
301
- seq.post(SpessaSynthSequencerReturnMessageType.getMIDI, seq.midiData);
302
- break;
303
-
304
- case SpessaSynthSequencerMessageType.setSkipToFirstNote:
305
- seq.skipToFirstNoteOn = messageData;
306
- break;
307
-
308
- case SpessaSynthSequencerMessageType.setPreservePlaybackState:
309
- seq.preservePlaybackState = messageData;
310
- }
311
- break;
312
-
313
- case workletMessageType.soundFontManager:
314
- try
315
- {
316
- const sfman = this.synthesizer.soundfontManager;
317
- const type = data[0];
318
- const messageData = data[1];
319
- switch (type)
320
- {
321
- case WorkletSoundfontManagerMessageType.addNewSoundFont:
322
- sfman.addNewSoundFont(messageData[0], messageData[1], messageData[2]);
323
- break;
324
-
325
- case WorkletSoundfontManagerMessageType.reloadSoundFont:
326
- sfman.reloadManager(messageData);
327
- break;
328
-
329
- case WorkletSoundfontManagerMessageType.deleteSoundFont:
330
- sfman.deleteSoundFont(messageData);
331
- break;
332
-
333
- case WorkletSoundfontManagerMessageType.rearrangeSoundFonts:
334
- sfman.rearrangeSoundFonts(messageData);
335
- }
336
- }
337
- catch (e)
338
- {
339
- this.postMessageToMainThread({
340
- messageType: returnMessageType.soundfontError,
341
- messageData: e
342
- });
343
- }
344
- this.synthesizer.clearSoundFont(true, false);
345
- break;
346
-
347
- case workletMessageType.keyModifierManager:
348
- /**
349
- * @type {workletKeyModifierMessageType}
350
- */
351
- const keyMessageType = data[0];
352
- const man = this.synthesizer.keyModifierManager;
353
- const keyMessageData = data[1];
354
- switch (keyMessageType)
355
- {
356
- default:
357
- return;
358
-
359
- case workletKeyModifierMessageType.addMapping:
360
- man.addMapping(...keyMessageData);
361
- break;
362
-
363
- case workletKeyModifierMessageType.clearMappings:
364
- man.clearMappings();
365
- break;
366
-
367
- case workletKeyModifierMessageType.deleteMapping:
368
- man.deleteMapping(...keyMessageData);
369
- }
370
- break;
371
-
372
- case workletMessageType.requestSynthesizerSnapshot:
373
- const snapshot = SynthesizerSnapshot.createSynthesizerSnapshot(this.synthesizer);
374
- this.postMessageToMainThread({
375
- messageType: returnMessageType.synthesizerSnapshot,
376
- messageData: snapshot
377
- });
378
- break;
379
-
380
- case workletMessageType.setLogLevel:
381
- SpessaSynthLogging(data[0], data[1], data[2], data[3]);
382
- break;
383
-
384
- case workletMessageType.setEffectsGain:
385
- this.synthesizer.reverbGain = data[0];
386
- this.synthesizer.chorusGain = data[1];
387
- break;
388
-
389
- case workletMessageType.destroyWorklet:
390
- this.alive = false;
391
- this.synthesizer.destroySynthProcessor();
392
- break;
393
-
394
- default:
395
- SpessaSynthWarn("Unrecognized event:", data);
396
- break;
397
- }
398
- }
399
-
400
- // noinspection JSUnusedGlobalSymbols
401
- /**
402
- * the audio worklet processing logic
403
- * @param inputs {Float32Array[][]} required by WebAudioAPI
404
- * @param outputs {Float32Array[][]} the outputs to write to, only the first two channels are populated
405
- * @returns {boolean} true unless it's not alive
406
- */
407
- process(inputs, outputs)
408
- {
409
- if (!this.alive)
410
- {
411
- return false;
412
- }
413
- if (this.oneOutputMode)
414
- {
415
- const out = outputs[0];
416
- // 1 output with 32 channels.
417
- // channels are ordered as follows:
418
- // midiChannel1L, midiChannel1R,
419
- // midiChannel2L, midiChannel2R
420
- // and so on
421
- /**
422
- * @type {Float32Array[][]}
423
- */
424
- const channelMap = [];
425
- for (let i = 0; i < 32; i += 2)
426
- {
427
- channelMap.push([out[i], out[i + 1]]);
428
- }
429
- this.synthesizer.renderAudioSplit(
430
- [], [], // effects are disabled
431
- channelMap
432
- );
433
- }
434
- else
435
- {
436
- // 18 outputs, each a stereo one
437
- // 0: reverb
438
- // 1: chorus
439
- // 2: channel 1
440
- // 3: channel 2
441
- // and so on
442
- this.synthesizer.renderAudioSplit(
443
- outputs[0], // reverb
444
- outputs[1], // chorus
445
- outputs.slice(2)
446
- );
447
- }
448
- return true;
449
- }
450
- }
451
-
452
- // noinspection JSUnresolvedReference
453
- registerProcessor(WORKLET_PROCESSOR_NAME, WorkletSpessaProcessor);
454
- SpessaSynthInfo("%cProcessor succesfully registered!", consoleColors.recognized);
@@ -1,16 +0,0 @@
1
- /**
2
- * The absolute path (from the spessasynth_lib folder) to the worklet module
3
- * @type {string}
4
- */
5
- export const WORKLET_URL_ABSOLUTE = "synthetizer/worklet_processor.min.js";
6
- /**
7
- * @typedef {Object} StartRenderingDataConfig
8
- * @property {BasicMIDI} parsedMIDI - the MIDI to render
9
- * @property {SynthesizerSnapshot?} snapshot - the snapshot to apply
10
- * @property {boolean?} oneOutput - if synth should use one output with 32 channels (2 audio channels for each midi channel).
11
- * this disabled chorus and reverb.
12
- * @property {number?} loopCount - the times to loop the song
13
- * @property {SequencerOptions?} sequencerOptions - the options to pass to the sequencer
14
- */
15
-
16
- export const WORKLET_PROCESSOR_NAME = "spessasynth-worklet-processor";
package/utils/README.md DELETED
@@ -1,5 +0,0 @@
1
- ## This is the utility folder.
2
-
3
- There are various utilites here used by the SpessaSynth library.
4
-
5
- ### Note that the stbvorbis_sync.js is licensed under Apache-2.0.
@@ -1,186 +0,0 @@
1
- /**
2
- * @typedef {Object} WaveMetadata
3
- * @property {string|undefined} title - the song's title
4
- * @property {string|undefined} artist - the song's artist
5
- * @property {string|undefined} album - the song's album
6
- * @property {string|undefined} genre - the song's genre
7
- */
8
-
9
- import { combineArrays, IndexedByteArray } from "./indexed_array.js";
10
- import { getStringBytes, writeStringAsBytes } from "./byte_functions/string.js";
11
- import { writeRIFFOddSize } from "../soundfont/basic_soundfont/riff_chunk.js";
12
- import { writeLittleEndian } from "./byte_functions/little_endian.js";
13
-
14
- /**
15
- *
16
- * @param audioBuffer {AudioBuffer}
17
- * @param normalizeAudio {boolean} find the max sample point and set it to 1, and scale others with it
18
- * @param channelOffset {number} channel offset and channel offset + 1 get saved
19
- * @param metadata {WaveMetadata}
20
- * @param loop {{start: number, end: number}} loop start and end points in seconds. Undefined if no loop
21
- * @returns {Blob}
22
- */
23
- export function audioBufferToWav(audioBuffer, normalizeAudio = true, channelOffset = 0, metadata = {}, loop = undefined)
24
- {
25
- const channel1Data = audioBuffer.getChannelData(channelOffset);
26
- const channel2Data = audioBuffer.getChannelData(channelOffset + 1);
27
- const length = channel1Data.length;
28
-
29
- const bytesPerSample = 2; // 16-bit PCM
30
-
31
- // prepare INFO chunk
32
- let infoChunk = new IndexedByteArray(0);
33
- const infoOn = Object.keys(metadata).length > 0;
34
- // INFO chunk
35
- if (infoOn)
36
- {
37
- const encoder = new TextEncoder();
38
- const infoChunks = [
39
- getStringBytes("INFO"),
40
- writeRIFFOddSize("ICMT", encoder.encode("Created with SpessaSynth"), true)
41
- ];
42
- if (metadata.artist)
43
- {
44
- infoChunks.push(
45
- writeRIFFOddSize("IART", encoder.encode(metadata.artist), true)
46
- );
47
- }
48
- if (metadata.album)
49
- {
50
- infoChunks.push(
51
- writeRIFFOddSize("IPRD", encoder.encode(metadata.album), true)
52
- );
53
- }
54
- if (metadata.genre)
55
- {
56
- infoChunks.push(
57
- writeRIFFOddSize("IGNR", encoder.encode(metadata.genre), true)
58
- );
59
- }
60
- if (metadata.title)
61
- {
62
- infoChunks.push(
63
- writeRIFFOddSize("INAM", encoder.encode(metadata.title), true)
64
- );
65
- }
66
- infoChunk = writeRIFFOddSize("LIST", combineArrays(infoChunks));
67
- }
68
-
69
- // prepare CUE chunk
70
- let cueChunk = new IndexedByteArray(0);
71
- const cueOn = loop?.end !== undefined && loop?.start !== undefined;
72
- if (cueOn)
73
- {
74
- const loopStartSamples = Math.floor(loop.start * audioBuffer.sampleRate);
75
- const loopEndSamples = Math.floor(loop.end * audioBuffer.sampleRate);
76
-
77
- const cueStart = new IndexedByteArray(24);
78
- writeLittleEndian(cueStart, 0, 4); // dwIdentifier
79
- writeLittleEndian(cueStart, 0, 4); // dwPosition
80
- writeStringAsBytes(cueStart, "data"); // cue point ID
81
- writeLittleEndian(cueStart, 0, 4); // chunkStart, always 0
82
- writeLittleEndian(cueStart, 0, 4); // BlockStart, always 0
83
- writeLittleEndian(cueStart, loopStartSamples, 4); // sampleOffset
84
-
85
- const cueEnd = new IndexedByteArray(24);
86
- writeLittleEndian(cueEnd, 1, 4); // dwIdentifier
87
- writeLittleEndian(cueEnd, 0, 4); // dwPosition
88
- writeStringAsBytes(cueEnd, "data"); // cue point ID
89
- writeLittleEndian(cueEnd, 0, 4); // chunkStart, always 0
90
- writeLittleEndian(cueEnd, 0, 4); // BlockStart, always 0
91
- writeLittleEndian(cueEnd, loopEndSamples, 4); // sampleOffset
92
-
93
- const out = combineArrays([
94
- new IndexedByteArray([2, 0, 0, 0]), // cue points count,
95
- cueStart,
96
- cueEnd
97
- ]);
98
- cueChunk = writeRIFFOddSize("cue ", out);
99
- }
100
-
101
- // Prepare the header
102
- const headerSize = 44;
103
- const dataSize = length * 2 * bytesPerSample; // 2 channels, 16-bit per channel
104
- const fileSize = headerSize + dataSize + infoChunk.length + cueChunk.length - 8; // total file size minus the first 8 bytes
105
- const header = new Uint8Array(headerSize);
106
-
107
- // 'RIFF'
108
- header.set([82, 73, 70, 70], 0);
109
- // file length
110
- header.set(
111
- new Uint8Array([fileSize & 0xff, (fileSize >> 8) & 0xff, (fileSize >> 16) & 0xff, (fileSize >> 24) & 0xff]),
112
- 4
113
- );
114
- // 'WAVE'
115
- header.set([87, 65, 86, 69], 8);
116
- // 'fmt '
117
- header.set([102, 109, 116, 32], 12);
118
- // fmt chunk length
119
- header.set([16, 0, 0, 0], 16); // 16 for PCM
120
- // audio format (PCM)
121
- header.set([1, 0], 20);
122
- // number of channels (2)
123
- header.set([2, 0], 22);
124
- // sample rate
125
- const sampleRate = audioBuffer.sampleRate;
126
- header.set(
127
- new Uint8Array([sampleRate & 0xff, (sampleRate >> 8) & 0xff, (sampleRate >> 16) & 0xff, (sampleRate >> 24) & 0xff]),
128
- 24
129
- );
130
- // byte rate (sample rate * block align)
131
- const byteRate = sampleRate * 2 * bytesPerSample; // 2 channels, 16-bit per channel
132
- header.set(
133
- new Uint8Array([byteRate & 0xff, (byteRate >> 8) & 0xff, (byteRate >> 16) & 0xff, (byteRate >> 24) & 0xff]),
134
- 28
135
- );
136
- // block align (channels * bytes per sample)
137
- header.set([4, 0], 32); // 2 channels * 16-bit per channel / 8
138
- // bits per sample
139
- header.set([16, 0], 34); // 16-bit
140
-
141
- // data chunk identifier 'data'
142
- header.set([100, 97, 116, 97], 36);
143
- // data chunk length
144
- header.set(
145
- new Uint8Array([dataSize & 0xff, (dataSize >> 8) & 0xff, (dataSize >> 16) & 0xff, (dataSize >> 24) & 0xff]),
146
- 40
147
- );
148
-
149
- let wavData = new Uint8Array(fileSize + 8);
150
- let offset = headerSize;
151
- wavData.set(header, 0);
152
-
153
- // Interleave audio data (combine channels)
154
- let multiplier = 32767;
155
- if (normalizeAudio)
156
- {
157
- // find min and max values to prevent clipping when converting to 16 bits
158
- const maxAbsValue = channel1Data.map((v, i) => Math.max(Math.abs(v), Math.abs(channel2Data[i])))
159
- .reduce((a, b) => Math.max(a, b));
160
- multiplier = maxAbsValue > 0 ? (32767 / maxAbsValue) : 1;
161
- }
162
- for (let i = 0; i < length; i++)
163
- {
164
- // interleave both channels
165
- const sample1 = Math.min(32767, Math.max(-32768, channel1Data[i] * multiplier));
166
- const sample2 = Math.min(32767, Math.max(-32768, channel2Data[i] * multiplier));
167
-
168
- // convert to 16-bit
169
- wavData[offset++] = sample1 & 0xff;
170
- wavData[offset++] = (sample1 >> 8) & 0xff;
171
- wavData[offset++] = sample2 & 0xff;
172
- wavData[offset++] = (sample2 >> 8) & 0xff;
173
- }
174
-
175
- if (infoOn)
176
- {
177
- wavData.set(infoChunk, offset);
178
- offset += infoChunk.length;
179
- }
180
- if (cueOn)
181
- {
182
- wavData.set(cueChunk, offset);
183
- }
184
-
185
- return new Blob([wavData.buffer], { type: "audio/wav" });
186
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * Reads as Big endian
3
- * @param dataArray {IndexedByteArray}
4
- * @param bytesAmount {number}
5
- * @returns {number}
6
- */
7
- export function readBytesAsUintBigEndian(dataArray, bytesAmount)
8
- {
9
- let out = 0;
10
- for (let i = 8 * (bytesAmount - 1); i >= 0; i -= 8)
11
- {
12
- out |= (dataArray[dataArray.currentIndex++] << i);
13
- }
14
- return out >>> 0;
15
- }
16
-
17
- /**
18
- * @param number {number}
19
- * @param bytesAmount {number}
20
- * @returns {number[]}
21
- */
22
- export function writeBytesAsUintBigEndian(number, bytesAmount)
23
- {
24
- const bytes = new Array(bytesAmount).fill(0);
25
- for (let i = bytesAmount - 1; i >= 0; i--)
26
- {
27
- bytes[i] = number & 0xFF;
28
- number >>= 8;
29
- }
30
-
31
- return bytes;
32
- }