spessasynth_lib 3.24.2 → 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 (66) hide show
  1. package/@types/synthetizer/audio_effects/effects_config.d.ts +20 -8
  2. package/@types/synthetizer/synthetizer.d.ts +17 -23
  3. package/LICENSE +0 -0
  4. package/README.md +0 -0
  5. package/external_midi/README.md +0 -0
  6. package/external_midi/midi_handler.js +0 -0
  7. package/external_midi/web_midi_link.js +0 -0
  8. package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -0
  9. package/externals/stbvorbis_sync/LICENSE +0 -0
  10. package/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -0
  11. package/midi_parser/README.md +0 -0
  12. package/midi_parser/midi_message.js +0 -0
  13. package/midi_parser/midi_writer.js +0 -0
  14. package/midi_parser/used_keys_loaded.js +0 -0
  15. package/package.json +1 -1
  16. package/sequencer/README.md +0 -0
  17. package/soundfont/README.md +0 -0
  18. package/soundfont/basic_soundfont/basic_instrument.js +0 -0
  19. package/soundfont/basic_soundfont/write_sf2/ibag.js +0 -0
  20. package/soundfont/basic_soundfont/write_sf2/imod.js +0 -0
  21. package/soundfont/basic_soundfont/write_sf2/inst.js +0 -0
  22. package/soundfont/basic_soundfont/write_sf2/pbag.js +0 -0
  23. package/soundfont/basic_soundfont/write_sf2/phdr.js +0 -0
  24. package/soundfont/basic_soundfont/write_sf2/pmod.js +0 -0
  25. package/soundfont/basic_soundfont/write_sf2/sdta.js +0 -0
  26. package/soundfont/basic_soundfont/write_sf2/shdr.js +0 -0
  27. package/soundfont/basic_soundfont/write_sf2/soundfont_trimmer.js +0 -0
  28. package/soundfont/dls/dls_destinations.js +0 -0
  29. package/soundfont/dls/dls_preset.js +0 -0
  30. package/soundfont/dls/dls_sources.js +0 -0
  31. package/soundfont/dls/read_instrument_list.js +0 -0
  32. package/soundfont/load_soundfont.js +0 -0
  33. package/soundfont/read_sf2/generators.js +0 -0
  34. package/soundfont/read_sf2/instruments.js +0 -0
  35. package/soundfont/read_sf2/modulators.js +0 -0
  36. package/soundfont/read_sf2/presets.js +0 -0
  37. package/soundfont/read_sf2/zones.js +0 -0
  38. package/synthetizer/README.md +0 -0
  39. package/synthetizer/audio_effects/effects_config.js +10 -6
  40. package/synthetizer/audio_effects/fancy_chorus.js +9 -16
  41. package/synthetizer/audio_effects/reverb.js +1 -1
  42. package/synthetizer/synthetizer.js +43 -37
  43. package/synthetizer/worklet_processor.min.js +6 -6
  44. package/synthetizer/worklet_system/README.md +0 -0
  45. package/synthetizer/worklet_system/message_protocol/message_sending.js +0 -0
  46. package/synthetizer/worklet_system/snapshot/snapshot.js +1 -1
  47. package/synthetizer/worklet_system/worklet_methods/data_entry.js +0 -0
  48. package/synthetizer/worklet_system/worklet_methods/note_on.js +5 -2
  49. package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +0 -0
  50. package/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -0
  51. package/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -0
  52. package/synthetizer/worklet_system/worklet_methods/worklet_soundfont_manager/sfman_message.js +0 -0
  53. package/synthetizer/worklet_system/worklet_processor.js +0 -0
  54. package/synthetizer/worklet_system/worklet_utilities/controller_tables.js +0 -0
  55. package/synthetizer/worklet_system/worklet_utilities/lfo.js +0 -0
  56. package/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +0 -0
  57. package/synthetizer/worklet_system/worklet_utilities/unit_converter.js +0 -0
  58. package/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +0 -0
  59. package/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +0 -0
  60. package/synthetizer/worklet_url.js +0 -0
  61. package/utils/README.md +0 -0
  62. package/utils/byte_functions/big_endian.js +0 -0
  63. package/utils/byte_functions/little_endian.js +0 -0
  64. package/utils/byte_functions/variable_length_quantity.js +0 -0
  65. package/utils/indexed_array.js +0 -0
  66. package/utils/loggin.js +0 -0
@@ -1,15 +1,18 @@
1
1
  /**
2
- * @typedef {Object} EffectsConfig
2
+ * @typedef {Object} SynthConfig
3
3
  * @property {boolean} chorusEnabled - indicates if the chorus effect is enabled.
4
- * @property {ChorusConfig} chorusConfig - the configuration for chorus. Pass undefined to use defaults
4
+ * @property {ChorusConfig?} chorusConfig - the configuration for chorus. Pass undefined to use defaults
5
5
  * @property {boolean} reverbEnabled - indicates if the reverb effect is enabled.
6
- * @property {AudioBuffer} reverbImpulseResponse - the impulse response for the reverb. Pass undefined to use defaults
6
+ * @property {AudioBuffer?} reverbImpulseResponse - the impulse response for the reverb. Pass undefined to use defaults
7
+ * @property {{
8
+ * worklet: function(context: object, name: string, options?: Object)
9
+ * }} audioNodeCreators - custom audio node creation functions for Web Audio wrappers.
7
10
  */
8
11
  /**
9
- * @type {EffectsConfig}
12
+ * @type {SynthConfig}
10
13
  */
11
- export const DEFAULT_EFFECTS_CONFIG: EffectsConfig;
12
- export type EffectsConfig = {
14
+ export const DEFAULT_SYNTH_CONFIG: SynthConfig;
15
+ export type SynthConfig = {
13
16
  /**
14
17
  * - indicates if the chorus effect is enabled.
15
18
  */
@@ -17,7 +20,7 @@ export type EffectsConfig = {
17
20
  /**
18
21
  * - the configuration for chorus. Pass undefined to use defaults
19
22
  */
20
- chorusConfig: ChorusConfig;
23
+ chorusConfig: ChorusConfig | null;
21
24
  /**
22
25
  * - indicates if the reverb effect is enabled.
23
26
  */
@@ -25,5 +28,14 @@ export type EffectsConfig = {
25
28
  /**
26
29
  * - the impulse response for the reverb. Pass undefined to use defaults
27
30
  */
28
- reverbImpulseResponse: AudioBuffer;
31
+ reverbImpulseResponse: AudioBuffer | null;
32
+ /**
33
+ * )
34
+ * }} audioNodeCreators - custom audio node creation functions for Web Audio wrappers.
35
+ */
36
+ "": {
37
+ worklet: (arg0: context) => object;
38
+ name: string;
39
+ options?: any;
40
+ };
29
41
  };
@@ -6,7 +6,8 @@
6
6
  * @typedef {Object} StartRenderingDataConfig
7
7
  * @property {BasicMIDI} parsedMIDI - the MIDI to render
8
8
  * @property {SynthesizerSnapshot} snapshot - the snapshot to apply
9
- * @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.
9
+ * @property {boolean|undefined} oneOutput - if synth should use one output with 32 channels (2 audio channels for each midi channel).
10
+ * this disabled chorus and reverb.
10
11
  * @property {number|undefined} loopCount - the times to loop the song
11
12
  */
12
13
  export const WORKLET_PROCESSOR_NAME: "spessasynth-worklet-system";
@@ -14,14 +15,6 @@ export const VOICE_CAP: 350;
14
15
  export const DEFAULT_PERCUSSION: 9;
15
16
  export const MIDI_CHANNEL_COUNT: 16;
16
17
  export const DEFAULT_SYNTH_MODE: "gs";
17
- /**
18
- * Creates a new instance of the SpessaSynth synthesizer
19
- * @param targetNode {AudioNode}
20
- * @param soundFontBuffer {ArrayBuffer} the soundfont file array buffer
21
- * @param enableEventSystem {boolean} enables the event system. Defaults to true
22
- * @param startRenderingData {StartRenderingDataConfig} if set, starts playing this immediately and restores the values
23
- * @param effectsConfig {EffectsConfig} optional configuration for the audio effects.
24
- */
25
18
  export class Synthetizer {
26
19
  /**
27
20
  * Creates a new instance of the SpessaSynth synthesizer
@@ -29,13 +22,13 @@ export class Synthetizer {
29
22
  * @param soundFontBuffer {ArrayBuffer} the soundfont file array buffer
30
23
  * @param enableEventSystem {boolean} enables the event system. Defaults to true
31
24
  * @param startRenderingData {StartRenderingDataConfig} if set, starts playing this immediately and restores the values
32
- * @param effectsConfig {EffectsConfig} optional configuration for the audio effects.
25
+ * @param synthConfig {SynthConfig} optional configuration for the synthesizer.
33
26
  */
34
- constructor(targetNode: AudioNode, soundFontBuffer: ArrayBuffer, enableEventSystem?: boolean, startRenderingData?: StartRenderingDataConfig, effectsConfig?: EffectsConfig);
27
+ constructor(targetNode: AudioNode, soundFontBuffer: ArrayBuffer, enableEventSystem?: boolean, startRenderingData?: StartRenderingDataConfig, synthConfig?: SynthConfig);
35
28
  context: BaseAudioContext;
36
29
  targetNode: AudioNode;
37
30
  /**
38
- * Allows to set up custom event listeners for the synthesizer
31
+ * Allows setting up custom event listeners for the synthesizer
39
32
  * @type {EventHandler}
40
33
  */
41
34
  eventHandler: EventHandler;
@@ -43,13 +36,13 @@ export class Synthetizer {
43
36
  _destroyed: boolean;
44
37
  /**
45
38
  * the new channels will have their audio sent to the moduled output by this constant.
46
- * what does that mean? e.g. if outputsAmount is 16, then channel's 16 audio will be sent to channel 0
39
+ * what does that mean? e.g., if outputsAmount is 16, then channel's 16 audio data will be sent to channel 0
47
40
  * @type {number}
48
41
  * @private
49
42
  */
50
43
  private _outputsAmount;
51
44
  /**
52
- * the amount of midi channels
45
+ * the number of midi channels
53
46
  * @type {number}
54
47
  */
55
48
  channelsAmount: number;
@@ -74,10 +67,10 @@ export class Synthetizer {
74
67
  */
75
68
  _highPerformanceMode: boolean;
76
69
  /**
77
- * @type {EffectsConfig}
70
+ * @type {SynthConfig}
78
71
  */
79
- effectsConfig: EffectsConfig;
80
- worklet: AudioWorkletNode;
72
+ effectsConfig: SynthConfig;
73
+ worklet: any;
81
74
  /**
82
75
  * The synth's soundfont manager
83
76
  * @type {SoundfontManager}
@@ -101,12 +94,12 @@ export class Synthetizer {
101
94
  reverbProcessor: ConvolverNode;
102
95
  chorusProcessor: FancyChorus;
103
96
  /**
104
- * The maximum amount of voices allowed at once
97
+ * The maximum number of voices allowed at once
105
98
  * @param value {number}
106
99
  */
107
100
  set voiceCap(value: number);
108
101
  /**
109
- * The maximum amount of voices allowed at once
102
+ * The maximum number of voices allowed at once
110
103
  * @returns {number}
111
104
  */
112
105
  get voiceCap(): number;
@@ -121,7 +114,7 @@ export class Synthetizer {
121
114
  */
122
115
  get currentTime(): number;
123
116
  /**
124
- * @returns {number} the current amount of voices playing
117
+ * @returns {number} the current number of voices playing
125
118
  */
126
119
  get voicesAmount(): number;
127
120
  /**
@@ -171,7 +164,7 @@ export class Synthetizer {
171
164
  rate: number;
172
165
  }): void;
173
166
  /**
174
- * Connects the individual audio outputs to the given audio nodes. In the app it's used by the renderer.
167
+ * Connects the individual audio outputs to the given audio nodes. In the app, it's used by the renderer.
175
168
  * @param audioNodes {AudioNode[]}
176
169
  */
177
170
  connectIndividualOutputs(audioNodes: AudioNode[]): void;
@@ -237,7 +230,7 @@ export class Synthetizer {
237
230
  */
238
231
  pitchWheel(channel: number, MSB: number, LSB: number): void;
239
232
  /**
240
- * Transposes the synthetizer's pitch by given semitones amount (percussion channels do not get affected)
233
+ * Transposes the synthetizer's pitch by given semitones amount (percussion channels don’t get affected)
241
234
  * @param semitones {number} the semitones to transpose by. Can be a floating point number for more precision
242
235
  */
243
236
  transpose(semitones: number): void;
@@ -350,7 +343,8 @@ export type StartRenderingDataConfig = {
350
343
  */
351
344
  snapshot: SynthesizerSnapshot;
352
345
  /**
353
- * - if synth should use one output with 32 channels (2 audio channels for each midi channel). this disables chorus and reverb.
346
+ * - if synth should use one output with 32 channels (2 audio channels for each midi channel).
347
+ * this disabled chorus and reverb.
354
348
  */
355
349
  oneOutput: boolean | undefined;
356
350
  /**
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spessasynth_lib",
3
- "version": "3.24.2",
3
+ "version": "3.24.3",
4
4
  "description": "MIDI and SoundFont2/DLS library with no compromises",
5
5
  "browser": "index.js",
6
6
  "types": "@types/index.d.ts",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,21 +1,25 @@
1
1
  import { DEFAULT_CHORUS_CONFIG } from "./fancy_chorus.js";
2
2
 
3
3
  /**
4
- * @typedef {Object} EffectsConfig
4
+ * @typedef {Object} SynthConfig
5
5
  * @property {boolean} chorusEnabled - indicates if the chorus effect is enabled.
6
- * @property {ChorusConfig} chorusConfig - the configuration for chorus. Pass undefined to use defaults
6
+ * @property {ChorusConfig?} chorusConfig - the configuration for chorus. Pass undefined to use defaults
7
7
  * @property {boolean} reverbEnabled - indicates if the reverb effect is enabled.
8
- * @property {AudioBuffer} reverbImpulseResponse - the impulse response for the reverb. Pass undefined to use defaults
8
+ * @property {AudioBuffer?} reverbImpulseResponse - the impulse response for the reverb. Pass undefined to use defaults
9
+ * @property {{
10
+ * worklet: function(context: object, name: string, options?: Object)
11
+ * }} audioNodeCreators - custom audio node creation functions for Web Audio wrappers.
9
12
  */
10
13
 
11
14
 
12
15
  /**
13
- * @type {EffectsConfig}
16
+ * @type {SynthConfig}
14
17
  */
15
- export const DEFAULT_EFFECTS_CONFIG = {
18
+ export const DEFAULT_SYNTH_CONFIG = {
16
19
  chorusEnabled: true,
17
20
  chorusConfig: DEFAULT_CHORUS_CONFIG,
18
21
 
19
22
  reverbEnabled: true,
20
- reverbImpulseResponse: undefined // will load the integrated one
23
+ reverbImpulseResponse: undefined, // will load the integrated one
24
+ audioNodeCreators: undefined
21
25
  };
@@ -52,13 +52,9 @@ export class FancyChorus
52
52
  {
53
53
  const context = output.context;
54
54
 
55
- this.input = new ChannelSplitterNode(context, {
56
- numberOfOutputs: 2
57
- });
55
+ this.input = context.createChannelSplitter(2);
58
56
 
59
- const merger = new ChannelMergerNode(context, {
60
- numberOfInputs: 2
61
- });
57
+ const merger = context.createChannelMerger(2);
62
58
 
63
59
  /**
64
60
  * @type {ChorusNode[]}
@@ -142,16 +138,13 @@ export class FancyChorus
142
138
  */
143
139
  createChorusNode(freq, delay, list, input, output, outputNum, context, config)
144
140
  {
145
- const oscillator = new OscillatorNode(context, {
146
- type: "sine",
147
- frequency: freq
148
- });
149
- const gainNode = new GainNode(context, {
150
- gain: config.oscillatorGain
151
- });
152
- const delayNode = new DelayNode(context, {
153
- delayTime: delay
154
- });
141
+ const oscillator = context.createOscillator();
142
+ oscillator.type = "sine";
143
+ oscillator.frequency.value = freq;
144
+ const gainNode = context.createGain();
145
+ gainNode.gain.value = config.oscillatorGain;
146
+ const delayNode = context.createDelay();
147
+ delayNode.delayTime.value = delay;
155
148
 
156
149
  oscillator.connect(gainNode);
157
150
  gainNode.connect(delayNode.delayTime);
@@ -6,7 +6,7 @@
6
6
  */
7
7
  export function getReverbProcessor(context, reverbBuffer = undefined)
8
8
  {
9
- const convolver = new ConvolverNode(context);
9
+ const convolver = context.createConvolver();
10
10
  if (reverbBuffer)
11
11
  {
12
12
  convolver.buffer = reverbBuffer;
@@ -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)