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.
- package/@types/sequencer/sequencer.d.ts +63 -28
- package/@types/sequencer/worklet_sequencer/sequencer_message.d.ts +1 -0
- 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/sequencer/sequencer.js +134 -77
- package/sequencer/worklet_sequencer/process_event.js +4 -1
- package/sequencer/worklet_sequencer/process_tick.js +4 -4
- package/sequencer/worklet_sequencer/sequencer_message.js +2 -1
- 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 +8 -8
- 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
package/sequencer/sequencer.js
CHANGED
|
@@ -12,7 +12,8 @@ import { BasicMIDI } from "../midi_parser/basic_midi.js";
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* sequencer.js
|
|
15
|
-
* purpose: plays back the midi file decoded by midi_loader.js, including support for
|
|
15
|
+
* purpose: plays back the midi file decoded by midi_loader.js, including support for multichannel midis
|
|
16
|
+
* (adding channels when more than one midi port is detected)
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -63,7 +64,7 @@ export class Sequencer
|
|
|
63
64
|
* Fires on text event
|
|
64
65
|
* @type {function}
|
|
65
66
|
* @param data {Uint8Array} the data text
|
|
66
|
-
* @param type {number} the status byte of the message (the meta
|
|
67
|
+
* @param type {number} the status byte of the message (the meta-status byte)
|
|
67
68
|
* @param lyricsIndex {number} if the text is a lyric, the index of the lyric in midiData.lyrics, otherwise -1
|
|
68
69
|
*/
|
|
69
70
|
onTextEvent;
|
|
@@ -79,6 +80,51 @@ export class Sequencer
|
|
|
79
80
|
*/
|
|
80
81
|
onSongEnded = {};
|
|
81
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Fires on tempo change
|
|
85
|
+
* @type {Object<string, function(number)>}
|
|
86
|
+
*/
|
|
87
|
+
onTempoChange = {};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Current song's tempo in BPM
|
|
91
|
+
* @type {number}
|
|
92
|
+
*/
|
|
93
|
+
currentTempo = 120;
|
|
94
|
+
/**
|
|
95
|
+
* Current song index
|
|
96
|
+
* @type {number}
|
|
97
|
+
*/
|
|
98
|
+
songIndex = 0;
|
|
99
|
+
/**
|
|
100
|
+
* @type {function(BasicMIDI)}
|
|
101
|
+
* @private
|
|
102
|
+
*/
|
|
103
|
+
_getMIDIResolve = undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Indicates if the current midiData property has fake data in it (not yet loaded)
|
|
106
|
+
* @type {boolean}
|
|
107
|
+
*/
|
|
108
|
+
hasDummyData = true;
|
|
109
|
+
/**
|
|
110
|
+
* Indicates whether the sequencer has finished playing a sequence
|
|
111
|
+
* @type {boolean}
|
|
112
|
+
*/
|
|
113
|
+
isFinished = false;
|
|
114
|
+
/**
|
|
115
|
+
* The current sequence's length, in seconds
|
|
116
|
+
* @type {number}
|
|
117
|
+
*/
|
|
118
|
+
duration = 0;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Indicates if the sequencer is paused.
|
|
122
|
+
* Paused if a number, undefined if playing
|
|
123
|
+
* @type {undefined|number}
|
|
124
|
+
* @private
|
|
125
|
+
*/
|
|
126
|
+
pausedTime = undefined;
|
|
127
|
+
|
|
82
128
|
/**
|
|
83
129
|
* Creates a new Midi sequencer for playing back MIDI files
|
|
84
130
|
* @param midiBinaries {MIDIFile[]} List of the buffers of the MIDI files
|
|
@@ -97,47 +143,6 @@ export class Sequencer
|
|
|
97
143
|
*/
|
|
98
144
|
this.absoluteStartTime = this.synth.currentTime;
|
|
99
145
|
|
|
100
|
-
/**
|
|
101
|
-
* @type {function(BasicMIDI)}
|
|
102
|
-
* @private
|
|
103
|
-
*/
|
|
104
|
-
this._getMIDIResolve = undefined;
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Controls the playback's rate
|
|
108
|
-
* @type {number}
|
|
109
|
-
*/
|
|
110
|
-
this._playbackRate = 1;
|
|
111
|
-
|
|
112
|
-
this.songIndex = 0;
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Indicates if the current midiData property has dummy data in it (not yet loaded)
|
|
116
|
-
* @type {boolean}
|
|
117
|
-
*/
|
|
118
|
-
this.hasDummyData = true;
|
|
119
|
-
|
|
120
|
-
this._loop = true;
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Indicates whether the sequencer has finished playing a sequence
|
|
124
|
-
* @type {boolean}
|
|
125
|
-
*/
|
|
126
|
-
this.isFinished = false;
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Indicates if the sequencer is paused.
|
|
130
|
-
* Paused if a number, undefined if playing
|
|
131
|
-
* @type {undefined|number}
|
|
132
|
-
*/
|
|
133
|
-
this.pausedTime = undefined;
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* The current sequence's length, in seconds
|
|
137
|
-
* @type {number}
|
|
138
|
-
*/
|
|
139
|
-
this.duration = 0;
|
|
140
|
-
|
|
141
146
|
this.synth.sequencerCallbackFunction = this._handleMessage.bind(this);
|
|
142
147
|
|
|
143
148
|
/**
|
|
@@ -167,6 +172,49 @@ export class Sequencer
|
|
|
167
172
|
window.addEventListener("beforeunload", this.resetMIDIOut.bind(this));
|
|
168
173
|
}
|
|
169
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Internal loop marker
|
|
177
|
+
* @type {boolean}
|
|
178
|
+
* @private
|
|
179
|
+
*/
|
|
180
|
+
_loop = true;
|
|
181
|
+
|
|
182
|
+
get loop()
|
|
183
|
+
{
|
|
184
|
+
return this._loop;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
set loop(value)
|
|
188
|
+
{
|
|
189
|
+
this._sendMessage(WorkletSequencerMessageType.setLoop, value);
|
|
190
|
+
this._loop = value;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Controls the playback's rate
|
|
195
|
+
* @type {number}
|
|
196
|
+
* @private
|
|
197
|
+
*/
|
|
198
|
+
_playbackRate = 1;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @returns {number}
|
|
202
|
+
*/
|
|
203
|
+
get playbackRate()
|
|
204
|
+
{
|
|
205
|
+
return this._playbackRate;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @param value {number}
|
|
210
|
+
*/
|
|
211
|
+
set playbackRate(value)
|
|
212
|
+
{
|
|
213
|
+
this._sendMessage(WorkletSequencerMessageType.setPlaybackRate, value);
|
|
214
|
+
this.highResTimeOffset *= (value / this._playbackRate);
|
|
215
|
+
this._playbackRate = value;
|
|
216
|
+
}
|
|
217
|
+
|
|
170
218
|
/**
|
|
171
219
|
* Indicates if the sequencer should skip to first note on
|
|
172
220
|
* @return {boolean}
|
|
@@ -230,17 +278,6 @@ export class Sequencer
|
|
|
230
278
|
this._sendMessage(WorkletSequencerMessageType.setTime, time);
|
|
231
279
|
}
|
|
232
280
|
|
|
233
|
-
get loop()
|
|
234
|
-
{
|
|
235
|
-
return this._loop;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
set loop(value)
|
|
239
|
-
{
|
|
240
|
-
this._sendMessage(WorkletSequencerMessageType.setLoop, value);
|
|
241
|
-
this._loop = value;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
281
|
/**
|
|
245
282
|
* Use for visualization as it's not affected by the audioContext stutter
|
|
246
283
|
* @returns {number}
|
|
@@ -271,24 +308,6 @@ export class Sequencer
|
|
|
271
308
|
return currentPerformanceTime;
|
|
272
309
|
}
|
|
273
310
|
|
|
274
|
-
/**
|
|
275
|
-
* @returns {number}
|
|
276
|
-
*/
|
|
277
|
-
get playbackRate()
|
|
278
|
-
{
|
|
279
|
-
return this._playbackRate;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* @param value {number}
|
|
284
|
-
*/
|
|
285
|
-
set playbackRate(value)
|
|
286
|
-
{
|
|
287
|
-
this._sendMessage(WorkletSequencerMessageType.setPlaybackRate, value);
|
|
288
|
-
this.highResTimeOffset *= (value / this._playbackRate);
|
|
289
|
-
this._playbackRate = value;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
311
|
/**
|
|
293
312
|
* true if paused, false if playing or stopped
|
|
294
313
|
* @returns {boolean}
|
|
@@ -328,6 +347,16 @@ export class Sequencer
|
|
|
328
347
|
this.onTimeChange[id] = callback;
|
|
329
348
|
}
|
|
330
349
|
|
|
350
|
+
/**
|
|
351
|
+
* Adds a new event that gets called when the tempo changes
|
|
352
|
+
* @param callback {function(number)} the new tempo, in BPM
|
|
353
|
+
* @param id {string} must be unique
|
|
354
|
+
*/
|
|
355
|
+
addOnTempoChangeEvent(callback, id)
|
|
356
|
+
{
|
|
357
|
+
this.onTempoChange[id] = callback;
|
|
358
|
+
}
|
|
359
|
+
|
|
331
360
|
resetMIDIOut()
|
|
332
361
|
{
|
|
333
362
|
if (!this.MIDIout)
|
|
@@ -369,6 +398,26 @@ export class Sequencer
|
|
|
369
398
|
this._sendMessage(WorkletSequencerMessageType.changeSong, false);
|
|
370
399
|
}
|
|
371
400
|
|
|
401
|
+
/**
|
|
402
|
+
* @param type {Object<string, function>}
|
|
403
|
+
* @param params {any}
|
|
404
|
+
* @private
|
|
405
|
+
*/
|
|
406
|
+
_callEvents(type, params)
|
|
407
|
+
{
|
|
408
|
+
Object.entries(type).forEach((callback) =>
|
|
409
|
+
{
|
|
410
|
+
try
|
|
411
|
+
{
|
|
412
|
+
callback[1](params);
|
|
413
|
+
}
|
|
414
|
+
catch (e)
|
|
415
|
+
{
|
|
416
|
+
SpessaSynthWarn(`Failed to execute callback for ${callback[0]}:`, e);
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
372
421
|
/**
|
|
373
422
|
* @param {WorkletSequencerReturnMessageType} messageType
|
|
374
423
|
* @param {any} messageData
|
|
@@ -411,7 +460,7 @@ export class Sequencer
|
|
|
411
460
|
this.hasDummyData = false;
|
|
412
461
|
this.absoluteStartTime = 0;
|
|
413
462
|
this.duration = this.midiData.duration;
|
|
414
|
-
|
|
463
|
+
this._callEvents(this.onSongChange, songChangeData);
|
|
415
464
|
// if is auto played, unpause
|
|
416
465
|
if (messageData[2] === true)
|
|
417
466
|
{
|
|
@@ -429,7 +478,7 @@ export class Sequencer
|
|
|
429
478
|
case WorkletSequencerReturnMessageType.timeChange:
|
|
430
479
|
// message data is absolute time
|
|
431
480
|
const time = this.synth.currentTime - messageData;
|
|
432
|
-
|
|
481
|
+
this._callEvents(this.onTimeChange, time);
|
|
433
482
|
this._recalculateStartTime(time);
|
|
434
483
|
if (this.paused && this._preservePlaybackState)
|
|
435
484
|
{
|
|
@@ -446,7 +495,7 @@ export class Sequencer
|
|
|
446
495
|
this.isFinished = messageData;
|
|
447
496
|
if (this.isFinished)
|
|
448
497
|
{
|
|
449
|
-
|
|
498
|
+
this._callEvents(this.onSongEnded, undefined);
|
|
450
499
|
}
|
|
451
500
|
break;
|
|
452
501
|
|
|
@@ -466,6 +515,14 @@ export class Sequencer
|
|
|
466
515
|
{
|
|
467
516
|
this._getMIDIResolve(BasicMIDI.copyFrom(messageData));
|
|
468
517
|
}
|
|
518
|
+
break;
|
|
519
|
+
|
|
520
|
+
case WorkletSequencerReturnMessageType.tempoChange:
|
|
521
|
+
this.currentTempo = messageData;
|
|
522
|
+
if (this.onTempoChange)
|
|
523
|
+
{
|
|
524
|
+
this._callEvents(this.onTempoChange, this.currentTempo);
|
|
525
|
+
}
|
|
469
526
|
}
|
|
470
527
|
}
|
|
471
528
|
|
|
@@ -499,7 +556,7 @@ export class Sequencer
|
|
|
499
556
|
loadNewSongList(midiBuffers, autoPlay = true)
|
|
500
557
|
{
|
|
501
558
|
this.pause();
|
|
502
|
-
// add some
|
|
559
|
+
// add some fake data
|
|
503
560
|
this.midiData = DUMMY_MIDI_DATA;
|
|
504
561
|
this.hasDummyData = true;
|
|
505
562
|
this.duration = 99999;
|
|
@@ -549,7 +606,7 @@ export class Sequencer
|
|
|
549
606
|
|
|
550
607
|
/**
|
|
551
608
|
* Starts the playback
|
|
552
|
-
* @param resetTime {boolean} If true, time is set to
|
|
609
|
+
* @param resetTime {boolean} If true, time is set to 0 s
|
|
553
610
|
*/
|
|
554
611
|
play(resetTime = false)
|
|
555
612
|
{
|
|
@@ -90,12 +90,15 @@ export function _processEvent(event, trackIndex)
|
|
|
90
90
|
break;
|
|
91
91
|
|
|
92
92
|
case messageTypes.setTempo:
|
|
93
|
-
|
|
93
|
+
let tempoBPM = getTempo(event);
|
|
94
|
+
this.oneTickToSeconds = 60 / (tempoBPM * this.midiData.timeDivision);
|
|
94
95
|
if (this.oneTickToSeconds === 0)
|
|
95
96
|
{
|
|
96
97
|
this.oneTickToSeconds = 60 / (120 * this.midiData.timeDivision);
|
|
97
98
|
SpessaSynthWarn("invalid tempo! falling back to 120 BPM");
|
|
99
|
+
tempoBPM = 120;
|
|
98
100
|
}
|
|
101
|
+
this.post(WorkletSequencerReturnMessageType.tempoChange, Math.floor(tempoBPM * 100) / 100);
|
|
99
102
|
break;
|
|
100
103
|
|
|
101
104
|
// recongized but ignored
|
|
@@ -8,18 +8,18 @@ export function _processTick()
|
|
|
8
8
|
let current = this.currentTime;
|
|
9
9
|
while (this.playedTime < current)
|
|
10
10
|
{
|
|
11
|
-
// find next event
|
|
11
|
+
// find the next event
|
|
12
12
|
let trackIndex = this._findFirstEventIndex();
|
|
13
13
|
let event = this.tracks[trackIndex][this.eventIndex[trackIndex]];
|
|
14
14
|
this._processEvent(event, trackIndex);
|
|
15
15
|
|
|
16
16
|
this.eventIndex[trackIndex]++;
|
|
17
17
|
|
|
18
|
-
// find next event
|
|
18
|
+
// find the next event
|
|
19
19
|
trackIndex = this._findFirstEventIndex();
|
|
20
20
|
if (this.tracks[trackIndex].length <= this.eventIndex[trackIndex])
|
|
21
21
|
{
|
|
22
|
-
// song has ended
|
|
22
|
+
// the song has ended
|
|
23
23
|
if (this.loop)
|
|
24
24
|
{
|
|
25
25
|
this.setTimeTicks(this.midiData.loop.start);
|
|
@@ -43,7 +43,7 @@ export function _processTick()
|
|
|
43
43
|
this.setTimeTicks(this.midiData.loop.start);
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
// if song has ended
|
|
46
|
+
// if the song has ended
|
|
47
47
|
else if (current >= this.duration)
|
|
48
48
|
{
|
|
49
49
|
if (this.loop && this.currentLoopCount > 0)
|
|
@@ -39,5 +39,6 @@ export const WorkletSequencerReturnMessageType = {
|
|
|
39
39
|
timeChange: 3, // newAbsoluteTime<number>
|
|
40
40
|
pause: 4, // no data
|
|
41
41
|
getMIDI: 5, // midiData<MIDI>
|
|
42
|
-
midiError: 6
|
|
42
|
+
midiError: 6, // errorMSG<string>
|
|
43
|
+
tempoChange: 7 // newTempoBPM<number>
|
|
43
44
|
};
|
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);
|