spessasynth_lib 3.24.0 → 3.24.3

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 (72) hide show
  1. package/@types/sequencer/sequencer.d.ts +63 -28
  2. package/@types/sequencer/worklet_sequencer/sequencer_message.d.ts +1 -0
  3. package/@types/synthetizer/audio_effects/effects_config.d.ts +20 -8
  4. package/@types/synthetizer/synthetizer.d.ts +17 -23
  5. package/LICENSE +0 -0
  6. package/README.md +0 -0
  7. package/external_midi/README.md +0 -0
  8. package/external_midi/midi_handler.js +0 -0
  9. package/external_midi/web_midi_link.js +0 -0
  10. package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -0
  11. package/externals/stbvorbis_sync/LICENSE +0 -0
  12. package/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -0
  13. package/midi_parser/README.md +0 -0
  14. package/midi_parser/midi_message.js +0 -0
  15. package/midi_parser/midi_writer.js +0 -0
  16. package/midi_parser/used_keys_loaded.js +0 -0
  17. package/package.json +1 -1
  18. package/sequencer/README.md +0 -0
  19. package/sequencer/sequencer.js +134 -77
  20. package/sequencer/worklet_sequencer/process_event.js +4 -1
  21. package/sequencer/worklet_sequencer/process_tick.js +4 -4
  22. package/sequencer/worklet_sequencer/sequencer_message.js +2 -1
  23. package/soundfont/README.md +0 -0
  24. package/soundfont/basic_soundfont/basic_instrument.js +0 -0
  25. package/soundfont/basic_soundfont/write_sf2/ibag.js +0 -0
  26. package/soundfont/basic_soundfont/write_sf2/imod.js +0 -0
  27. package/soundfont/basic_soundfont/write_sf2/inst.js +0 -0
  28. package/soundfont/basic_soundfont/write_sf2/pbag.js +0 -0
  29. package/soundfont/basic_soundfont/write_sf2/phdr.js +0 -0
  30. package/soundfont/basic_soundfont/write_sf2/pmod.js +0 -0
  31. package/soundfont/basic_soundfont/write_sf2/sdta.js +0 -0
  32. package/soundfont/basic_soundfont/write_sf2/shdr.js +0 -0
  33. package/soundfont/basic_soundfont/write_sf2/soundfont_trimmer.js +0 -0
  34. package/soundfont/dls/dls_destinations.js +0 -0
  35. package/soundfont/dls/dls_preset.js +0 -0
  36. package/soundfont/dls/dls_sources.js +0 -0
  37. package/soundfont/dls/read_instrument_list.js +0 -0
  38. package/soundfont/load_soundfont.js +0 -0
  39. package/soundfont/read_sf2/generators.js +0 -0
  40. package/soundfont/read_sf2/instruments.js +0 -0
  41. package/soundfont/read_sf2/modulators.js +0 -0
  42. package/soundfont/read_sf2/presets.js +0 -0
  43. package/soundfont/read_sf2/zones.js +0 -0
  44. package/synthetizer/README.md +0 -0
  45. package/synthetizer/audio_effects/effects_config.js +10 -6
  46. package/synthetizer/audio_effects/fancy_chorus.js +9 -16
  47. package/synthetizer/audio_effects/reverb.js +1 -1
  48. package/synthetizer/synthetizer.js +43 -37
  49. package/synthetizer/worklet_processor.min.js +8 -8
  50. package/synthetizer/worklet_system/README.md +0 -0
  51. package/synthetizer/worklet_system/message_protocol/message_sending.js +0 -0
  52. package/synthetizer/worklet_system/snapshot/snapshot.js +1 -1
  53. package/synthetizer/worklet_system/worklet_methods/data_entry.js +0 -0
  54. package/synthetizer/worklet_system/worklet_methods/note_on.js +5 -2
  55. package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +0 -0
  56. package/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -0
  57. package/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -0
  58. package/synthetizer/worklet_system/worklet_methods/worklet_soundfont_manager/sfman_message.js +0 -0
  59. package/synthetizer/worklet_system/worklet_processor.js +0 -0
  60. package/synthetizer/worklet_system/worklet_utilities/controller_tables.js +0 -0
  61. package/synthetizer/worklet_system/worklet_utilities/lfo.js +0 -0
  62. package/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +0 -0
  63. package/synthetizer/worklet_system/worklet_utilities/unit_converter.js +0 -0
  64. package/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +0 -0
  65. package/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +0 -0
  66. package/synthetizer/worklet_url.js +0 -0
  67. package/utils/README.md +0 -0
  68. package/utils/byte_functions/big_endian.js +0 -0
  69. package/utils/byte_functions/little_endian.js +0 -0
  70. package/utils/byte_functions/variable_length_quantity.js +0 -0
  71. package/utils/indexed_array.js +0 -0
  72. package/utils/loggin.js +0 -0
@@ -11,7 +11,7 @@ import {
11
11
  workletMessageType
12
12
  } from "./worklet_system/message_protocol/worklet_message.js";
13
13
  import { SpessaSynthInfo, SpessaSynthWarn } from "../utils/loggin.js";
14
- import { DEFAULT_EFFECTS_CONFIG } from "./audio_effects/effects_config.js";
14
+ import { DEFAULT_SYNTH_CONFIG } from "./audio_effects/effects_config.js";
15
15
  import { SoundfontManager } from "./synth_soundfont_manager.js";
16
16
  import { channelConfiguration } from "./worklet_system/worklet_utilities/worklet_processor_channel.js";
17
17
  import { KeyModifierManager } from "./key_modifier_manager.js";
@@ -26,7 +26,8 @@ import { KeyModifierManager } from "./key_modifier_manager.js";
26
26
  * @typedef {Object} StartRenderingDataConfig
27
27
  * @property {BasicMIDI} parsedMIDI - the MIDI to render
28
28
  * @property {SynthesizerSnapshot} snapshot - the snapshot to apply
29
- * @property {boolean|undefined} oneOutput - if synth should use one output with 32 channels (2 audio channels for each midi channel). this disables chorus and reverb.
29
+ * @property {boolean|undefined} oneOutput - if synth should use one output with 32 channels (2 audio channels for each midi channel).
30
+ * this disabled chorus and reverb.
30
31
  * @property {number|undefined} loopCount - the times to loop the song
31
32
  */
32
33
 
@@ -38,14 +39,7 @@ export const DEFAULT_PERCUSSION = 9;
38
39
  export const MIDI_CHANNEL_COUNT = 16;
39
40
  export const DEFAULT_SYNTH_MODE = "gs";
40
41
 
41
- /**
42
- * Creates a new instance of the SpessaSynth synthesizer
43
- * @param targetNode {AudioNode}
44
- * @param soundFontBuffer {ArrayBuffer} the soundfont file array buffer
45
- * @param enableEventSystem {boolean} enables the event system. Defaults to true
46
- * @param startRenderingData {StartRenderingDataConfig} if set, starts playing this immediately and restores the values
47
- * @param effectsConfig {EffectsConfig} optional configuration for the audio effects.
48
- */
42
+
49
43
  export class Synthetizer
50
44
  {
51
45
  /**
@@ -54,13 +48,13 @@ export class Synthetizer
54
48
  * @param soundFontBuffer {ArrayBuffer} the soundfont file array buffer
55
49
  * @param enableEventSystem {boolean} enables the event system. Defaults to true
56
50
  * @param startRenderingData {StartRenderingDataConfig} if set, starts playing this immediately and restores the values
57
- * @param effectsConfig {EffectsConfig} optional configuration for the audio effects.
51
+ * @param synthConfig {SynthConfig} optional configuration for the synthesizer.
58
52
  */
59
53
  constructor(targetNode,
60
54
  soundFontBuffer,
61
55
  enableEventSystem = true,
62
56
  startRenderingData = undefined,
63
- effectsConfig = DEFAULT_EFFECTS_CONFIG)
57
+ synthConfig = DEFAULT_SYNTH_CONFIG)
64
58
  {
65
59
  SpessaSynthInfo("%cInitializing SpessaSynth synthesizer...", consoleColors.info);
66
60
  this.context = targetNode.context;
@@ -68,7 +62,7 @@ export class Synthetizer
68
62
  const oneOutputMode = startRenderingData?.oneOutput === true;
69
63
 
70
64
  /**
71
- * Allows to set up custom event listeners for the synthesizer
65
+ * Allows setting up custom event listeners for the synthesizer
72
66
  * @type {EventHandler}
73
67
  */
74
68
  this.eventHandler = new EventHandler();
@@ -78,14 +72,14 @@ export class Synthetizer
78
72
 
79
73
  /**
80
74
  * the new channels will have their audio sent to the moduled output by this constant.
81
- * what does that mean? e.g. if outputsAmount is 16, then channel's 16 audio will be sent to channel 0
75
+ * what does that mean? e.g., if outputsAmount is 16, then channel's 16 audio data will be sent to channel 0
82
76
  * @type {number}
83
77
  * @private
84
78
  */
85
79
  this._outputsAmount = MIDI_CHANNEL_COUNT;
86
80
 
87
81
  /**
88
- * the amount of midi channels
82
+ * the number of midi channels
89
83
  * @type {number}
90
84
  */
91
85
  this.channelsAmount = this._outputsAmount;
@@ -133,7 +127,7 @@ export class Synthetizer
133
127
  if (startRenderingData?.snapshot?.effectsConfig !== undefined)
134
128
  {
135
129
  /**
136
- * @type {EffectsConfig}
130
+ * @type {SynthConfig}
137
131
  */
138
132
  this.effectsConfig = startRenderingData.snapshot.effectsConfig;
139
133
  // remove from config as it can't be cloned
@@ -142,15 +136,24 @@ export class Synthetizer
142
136
  else
143
137
  {
144
138
  /**
145
- * @type {EffectsConfig}
139
+ * @type {SynthConfig}
146
140
  */
147
- this.effectsConfig = effectsConfig;
141
+ this.effectsConfig = synthConfig;
148
142
  }
149
143
 
150
144
  // first two outputs: reverb, chorsu, the others are the channel outputs
151
145
  try
152
146
  {
153
- this.worklet = new AudioWorkletNode(this.context, WORKLET_PROCESSOR_NAME, {
147
+ let workletConstructor = synthConfig?.audioNodeCreators?.worklet;
148
+ if (!workletConstructor)
149
+ {
150
+ workletConstructor = (ctx, name, opts) =>
151
+ {
152
+ // noinspection JSCheckFunctionSignatures
153
+ return new AudioWorkletNode(ctx, name, opts);
154
+ };
155
+ }
156
+ this.worklet = workletConstructor(this.context, WORKLET_PROCESSOR_NAME, {
154
157
  outputChannelCount: processorChannelCount,
155
158
  numberOfOutputs: processorOutputsCount,
156
159
  processorOptions: {
@@ -202,19 +205,6 @@ export class Synthetizer
202
205
  * @type {function(WorkletSequencerReturnMessageType, any)}
203
206
  */
204
207
  this.sequencerCallbackFunction = undefined;
205
- // add reverb
206
- if (this.effectsConfig.reverbEnabled && !oneOutputMode)
207
- {
208
- this.reverbProcessor = getReverbProcessor(this.context, this.effectsConfig.reverbImpulseResponse);
209
- this.reverbProcessor.connect(targetNode);
210
- this.worklet.connect(this.reverbProcessor, 0);
211
- }
212
-
213
- if (this.effectsConfig.chorusEnabled && !oneOutputMode)
214
- {
215
- this.chorusProcessor = new FancyChorus(targetNode, this.effectsConfig.chorusConfig);
216
- this.worklet.connect(this.chorusProcessor.input, 1);
217
- }
218
208
 
219
209
  if (oneOutputMode)
220
210
  {
@@ -223,6 +213,22 @@ export class Synthetizer
223
213
  }
224
214
  else
225
215
  {
216
+ // add reverb and chorus processors
217
+ const reverbOn = this.effectsConfig?.reverbEnabled ?? true;
218
+ const chorusOn = this.effectsConfig?.chorusEnabled ?? true;
219
+ if (reverbOn)
220
+ {
221
+ this.reverbProcessor = getReverbProcessor(this.context, this.effectsConfig.reverbImpulseResponse);
222
+ this.reverbProcessor.connect(targetNode);
223
+ this.worklet.connect(this.reverbProcessor, 0);
224
+ }
225
+
226
+ if (chorusOn)
227
+ {
228
+ this.chorusProcessor = new FancyChorus(targetNode, this.effectsConfig.chorusConfig);
229
+ this.worklet.connect(this.chorusProcessor.input, 1);
230
+ }
231
+
226
232
  // connect all outputs to the output node
227
233
  for (let i = 2; i < this.channelsAmount + 2; i++)
228
234
  {
@@ -238,7 +244,7 @@ export class Synthetizer
238
244
  }
239
245
 
240
246
  /**
241
- * The maximum amount of voices allowed at once
247
+ * The maximum number of voices allowed at once
242
248
  * @returns {number}
243
249
  */
244
250
  get voiceCap()
@@ -247,7 +253,7 @@ export class Synthetizer
247
253
  }
248
254
 
249
255
  /**
250
- * The maximum amount of voices allowed at once
256
+ * The maximum number of voices allowed at once
251
257
  * @param value {number}
252
258
  */
253
259
  set voiceCap(value)
@@ -280,7 +286,7 @@ export class Synthetizer
280
286
  }
281
287
 
282
288
  /**
283
- * @returns {number} the current amount of voices playing
289
+ * @returns {number} the current number of voices playing
284
290
  */
285
291
  get voicesAmount()
286
292
  {
@@ -436,7 +442,7 @@ export class Synthetizer
436
442
  }
437
443
 
438
444
  /**
439
- * Connects the individual audio outputs to the given audio nodes. In the app it's used by the renderer.
445
+ * Connects the individual audio outputs to the given audio nodes. In the app, it's used by the renderer.
440
446
  * @param audioNodes {AudioNode[]}
441
447
  */
442
448
  connectIndividualOutputs(audioNodes)
@@ -623,7 +629,7 @@ export class Synthetizer
623
629
  }
624
630
 
625
631
  /**
626
- * Transposes the synthetizer's pitch by given semitones amount (percussion channels do not get affected)
632
+ * Transposes the synthetizer's pitch by given semitones amount (percussion channels don’t get affected)
627
633
  * @param semitones {number} the semitones to transpose by. Can be a floating point number for more precision
628
634
  */
629
635
  transpose(semitones)