From d40564d61a6de36d6e1174de333cde4b0424657c Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Mon, 18 Jun 2018 11:59:45 -0400 Subject: [PATCH] make EffectChain standalone - EffectChain knows of audioEngine so it can create Effects - EffectChain connects to the target specified by .connect(target) - EffectChain can connect to other Effects or EffectChains - EffectChain can clone itself and connect to the original's target - Add EffectChain.update to mirror Effects API - Use deepest setting first in setEffectsFromTarget --- src/effects/EffectChain.js | 52 ++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/src/effects/EffectChain.js b/src/effects/EffectChain.js index 41c08d5..fa874ef 100644 --- a/src/effects/EffectChain.js +++ b/src/effects/EffectChain.js @@ -1,32 +1,35 @@ class EffectChain { - constructor (audioEngine) { + constructor (audioEngine, effects) { this.audioEngine = audioEngine; - this.outputNode = this.audioEngine.audioContext.createGain(); + this.inputNode = this.audioEngine.audioContext.createGain(); + + this.effects = effects; this.lastEffect = null; - this._effects = audioEngine.effects.map(Effect => { + this._effects = effects.map(Effect => { const effect = new Effect(audioEngine, this, this.lastEffect); this[effect.name] = effect; this.lastEffect = effect; return effect; }); - // Walk backwards through effects connecting the last output to audio engine, - // then each effect's output to the input of the next effect. - this._effects.reduceRight((nextNode, effect) => { - effect.connect(nextNode); - return effect; - }, this.audioEngine); - this._soundPlayers = new Set(); } + clone () { + const chain = new EffectChain(this.audioEngine, this.effects); + if (this.target === target) { + chain.connect(target); + } + return chain; + } + addSoundPlayer (soundPlayer) { if (!this._soundPlayers.has(soundPlayer)) { this._soundPlayers.add(soundPlayer); - this._effects.forEach(effect => effect.update()); + this.update(); } } @@ -35,7 +38,7 @@ class EffectChain { } getInputNode () { - return this.outputNode; + return this.inputNode; } /** @@ -43,8 +46,17 @@ class EffectChain { * @param {object} target - target whose node to should be connected */ connect (target) { - this.outputNode.disconnect(); - this.outputNode.connect(target.getInputNode()); + const {lastEffect} = this; + if (target === lastEffect) { + this.inputNode.disconnect(); + this.inputNode.connect(lastEffect.getInputNode()); + + return; + } + + this.target = target; + + this._effects[0].connect(target); } @@ -54,12 +66,10 @@ class EffectChain { setEffectsFromTarget (target) { this._effects.forEach(effect => { - if (effect.name in target) { - effect.set(target[effect.name]); - } else if ('soundEffects' in target && effect.name in target.soundEffects) { + if ('soundEffects' in target && effect.name in target.soundEffects) { effect.set(target.soundEffects[effect.name]); - } else { - effect.set(effect.DEFAULT_VALUE); + } else if (effect.name in target) { + effect.set(target[effect.name]); } }); } @@ -70,6 +80,10 @@ class EffectChain { } } + update () { + this._effects.forEach(effect => effect.update()); + } + clear () { this._effects.forEach(effect => effect.clear()); }