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.
- package/@types/synthetizer/audio_effects/effects_config.d.ts +20 -8
- package/@types/synthetizer/synthetizer.d.ts +17 -23
- package/LICENSE +0 -0
- package/README.md +0 -0
- package/external_midi/README.md +0 -0
- package/external_midi/midi_handler.js +0 -0
- package/external_midi/web_midi_link.js +0 -0
- package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -0
- package/externals/stbvorbis_sync/LICENSE +0 -0
- package/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -0
- package/midi_parser/README.md +0 -0
- package/midi_parser/midi_message.js +0 -0
- package/midi_parser/midi_writer.js +0 -0
- package/midi_parser/used_keys_loaded.js +0 -0
- package/package.json +1 -1
- package/sequencer/README.md +0 -0
- package/soundfont/README.md +0 -0
- package/soundfont/basic_soundfont/basic_instrument.js +0 -0
- package/soundfont/basic_soundfont/write_sf2/ibag.js +0 -0
- package/soundfont/basic_soundfont/write_sf2/imod.js +0 -0
- package/soundfont/basic_soundfont/write_sf2/inst.js +0 -0
- package/soundfont/basic_soundfont/write_sf2/pbag.js +0 -0
- package/soundfont/basic_soundfont/write_sf2/phdr.js +0 -0
- package/soundfont/basic_soundfont/write_sf2/pmod.js +0 -0
- package/soundfont/basic_soundfont/write_sf2/sdta.js +0 -0
- package/soundfont/basic_soundfont/write_sf2/shdr.js +0 -0
- package/soundfont/basic_soundfont/write_sf2/soundfont_trimmer.js +0 -0
- package/soundfont/dls/dls_destinations.js +0 -0
- package/soundfont/dls/dls_preset.js +0 -0
- package/soundfont/dls/dls_sources.js +0 -0
- package/soundfont/dls/read_instrument_list.js +0 -0
- package/soundfont/load_soundfont.js +0 -0
- package/soundfont/read_sf2/generators.js +0 -0
- package/soundfont/read_sf2/instruments.js +0 -0
- package/soundfont/read_sf2/modulators.js +0 -0
- package/soundfont/read_sf2/presets.js +0 -0
- package/soundfont/read_sf2/zones.js +0 -0
- package/synthetizer/README.md +0 -0
- package/synthetizer/audio_effects/effects_config.js +10 -6
- package/synthetizer/audio_effects/fancy_chorus.js +9 -16
- package/synthetizer/audio_effects/reverb.js +1 -1
- package/synthetizer/synthetizer.js +43 -37
- package/synthetizer/worklet_processor.min.js +6 -6
- package/synthetizer/worklet_system/README.md +0 -0
- package/synthetizer/worklet_system/message_protocol/message_sending.js +0 -0
- package/synthetizer/worklet_system/snapshot/snapshot.js +1 -1
- package/synthetizer/worklet_system/worklet_methods/data_entry.js +0 -0
- package/synthetizer/worklet_system/worklet_methods/note_on.js +5 -2
- package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +0 -0
- package/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -0
- package/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -0
- package/synthetizer/worklet_system/worklet_methods/worklet_soundfont_manager/sfman_message.js +0 -0
- package/synthetizer/worklet_system/worklet_processor.js +0 -0
- package/synthetizer/worklet_system/worklet_utilities/controller_tables.js +0 -0
- package/synthetizer/worklet_system/worklet_utilities/lfo.js +0 -0
- package/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +0 -0
- package/synthetizer/worklet_system/worklet_utilities/unit_converter.js +0 -0
- package/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +0 -0
- package/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +0 -0
- package/synthetizer/worklet_url.js +0 -0
- package/utils/README.md +0 -0
- package/utils/byte_functions/big_endian.js +0 -0
- package/utils/byte_functions/little_endian.js +0 -0
- package/utils/byte_functions/variable_length_quantity.js +0 -0
- package/utils/indexed_array.js +0 -0
- package/utils/loggin.js +0 -0
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @typedef {Object}
|
|
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 {
|
|
12
|
+
* @type {SynthConfig}
|
|
10
13
|
*/
|
|
11
|
-
export const
|
|
12
|
-
export type
|
|
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).
|
|
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
|
|
25
|
+
* @param synthConfig {SynthConfig} optional configuration for the synthesizer.
|
|
33
26
|
*/
|
|
34
|
-
constructor(targetNode: AudioNode, soundFontBuffer: ArrayBuffer, enableEventSystem?: boolean, startRenderingData?: StartRenderingDataConfig,
|
|
27
|
+
constructor(targetNode: AudioNode, soundFontBuffer: ArrayBuffer, enableEventSystem?: boolean, startRenderingData?: StartRenderingDataConfig, synthConfig?: SynthConfig);
|
|
35
28
|
context: BaseAudioContext;
|
|
36
29
|
targetNode: AudioNode;
|
|
37
30
|
/**
|
|
38
|
-
* Allows
|
|
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
|
|
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
|
|
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 {
|
|
70
|
+
* @type {SynthConfig}
|
|
78
71
|
*/
|
|
79
|
-
effectsConfig:
|
|
80
|
-
worklet:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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).
|
|
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
|
package/external_midi/README.md
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/midi_parser/README.md
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
package/sequencer/README.md
CHANGED
|
File without changes
|
package/soundfont/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
|
|
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
|
package/synthetizer/README.md
CHANGED
|
File without changes
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import { DEFAULT_CHORUS_CONFIG } from "./fancy_chorus.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @typedef {Object}
|
|
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 {
|
|
16
|
+
* @type {SynthConfig}
|
|
14
17
|
*/
|
|
15
|
-
export const
|
|
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 =
|
|
56
|
-
numberOfOutputs: 2
|
|
57
|
-
});
|
|
55
|
+
this.input = context.createChannelSplitter(2);
|
|
58
56
|
|
|
59
|
-
const merger =
|
|
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 =
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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);
|
|
@@ -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 {
|
|
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).
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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 {
|
|
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 {
|
|
139
|
+
* @type {SynthConfig}
|
|
146
140
|
*/
|
|
147
|
-
this.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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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)
|