From 8a75061a192ffda9b2037086ce4fa8c47581bde5 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Wed, 6 Jun 2018 14:38:26 -0400 Subject: [PATCH 1/3] fix Effect bugs --- src/AudioPlayer.js | 1 + src/effects/Effect.js | 8 ++++++-- src/effects/PanEffect.js | 8 -------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/AudioPlayer.js b/src/AudioPlayer.js index 9f3a3db..868282e 100644 --- a/src/AudioPlayer.js +++ b/src/AudioPlayer.js @@ -142,6 +142,7 @@ class AudioPlayer { * @param {object} target - target whose node to should be connected */ connect (target) { + this.outputNode.disconnect(); this.outputNode.connect(target.getInputNode()); } diff --git a/src/effects/Effect.js b/src/effects/Effect.js index a607128..66bcd39 100644 --- a/src/effects/Effect.js +++ b/src/effects/Effect.js @@ -38,7 +38,7 @@ class Effect { * @return {boolean} is the effect affecting the graph? */ get _isPatch () { - return this.initialized; + return this.initialized && this.value !== this.DEFAULT_VALUE; } /** @@ -46,7 +46,7 @@ class Effect { * @return {AudioNode} - audio node that is the input for this effect */ getInputNode () { - if (this.initialized) { + if (this._isPatch) { return this.inputNode; } return this.target.getInputNode(); @@ -117,6 +117,10 @@ class Effect { return; } + if (this.outputNode !== null) { + this.outputNode.disconnect(); + } + let nextTarget = target; if (this._isPatch) { nextTarget = this; diff --git a/src/effects/PanEffect.js b/src/effects/PanEffect.js index 58ccf10..340dcf0 100644 --- a/src/effects/PanEffect.js +++ b/src/effects/PanEffect.js @@ -20,14 +20,6 @@ class PanEffect extends Effect { this.channelMerger = null; } - /** - * Should the effect be connected to the audio graph? - * @return {boolean} is the effect affecting the graph? - */ - get _isPatch () { - return this.initialized && this.value !== 0; - } - /** * Initialize the Effect. * Effects start out uninitialized. Then initialize when they are first set From 1d9e530df2c2cba47522d2ee0a6b3d498a9ac742 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Wed, 6 Jun 2018 14:40:21 -0400 Subject: [PATCH 2/3] add VolumeEffect --- src/effects/VolumeEffect.js | 54 +++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/effects/VolumeEffect.js diff --git a/src/effects/VolumeEffect.js b/src/effects/VolumeEffect.js new file mode 100644 index 0000000..0d79052 --- /dev/null +++ b/src/effects/VolumeEffect.js @@ -0,0 +1,54 @@ +const Effect = require('./Effect'); + +/** + * Affect the volume of an effect chain. + */ +class VolumeEffect extends Effect { + /** + * Default value to set the Effect to when constructed and when clear'ed. + * @const {number} + */ + get DEFAULT_VALUE () { + return 100; + } + + /** + * Initialize the Effect. + * Effects start out uninitialized. Then initialize when they are first set + * with some value. + * @throws {Error} throws when left unimplemented + */ + initialize () { + this.inputNode = this.audioEngine.audioContext.createGain(); + this.outputNode = this.inputNode; + + this.initialized = true; + } + + /** + * Set the effects value. + * @private + * @param {number} value - new value to set effect to + */ + _set (value) { + this.value = value; + // A gain of 1 is normal. Scale down scratch's volume value. Apply the + // change over a tiny period of time. + this.outputNode.gain.setTargetAtTime(value / 100, 0, this.audioEngine.DECAY_TIME); + } + + /** + * Clean up and disconnect audio nodes. + */ + dispose () { + this.outputNode.disconnect(); + + this.inputNode = null; + this.outputNode = null; + this.target = null; + + this.initialized = false; + } +} + +module.exports = VolumeEffect; From 65702e7722c8df561fbec03014d87a618fcfa754 Mon Sep 17 00:00:00 2001 From: "Michael \"Z\" Goddard" Date: Wed, 6 Jun 2018 14:42:05 -0400 Subject: [PATCH 3/3] use VolumeEffect in AudioPlayer --- src/AudioPlayer.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/AudioPlayer.js b/src/AudioPlayer.js index 868282e..1619e4c 100644 --- a/src/AudioPlayer.js +++ b/src/AudioPlayer.js @@ -1,5 +1,6 @@ -const PitchEffect = require('./effects/PitchEffect'); const PanEffect = require('./effects/PanEffect'); +const PitchEffect = require('./effects/PitchEffect'); +const VolumeEffect = require('./effects/VolumeEffect'); const SoundPlayer = require('./SoundPlayer'); @@ -17,9 +18,11 @@ class AudioPlayer { this.outputNode = this.audioEngine.audioContext.createGain(); // Create the audio effects - const pitchEffect = new PitchEffect(this.audioEngine, this, null); + const volumeEffect = new VolumeEffect(this.audioEngine, this, null); + const pitchEffect = new PitchEffect(this.audioEngine, this, volumeEffect); const panEffect = new PanEffect(this.audioEngine, this, pitchEffect); this.effects = { + volume: volumeEffect, pitch: pitchEffect, pan: panEffect }; @@ -28,6 +31,7 @@ class AudioPlayer { // outputNode -> "pitchEffect" -> panEffect -> audioEngine.input panEffect.connect(this.audioEngine); pitchEffect.connect(panEffect); + volumeEffect.connect(pitchEffect); // reset effects to their default parameters this.clearEffects(); @@ -123,9 +127,6 @@ class AudioPlayer { for (const effectName in this.effects) { this.effects[effectName].clear(); } - - if (this.audioEngine === null) return; - this.outputNode.gain.setTargetAtTime(1.0, 0, this.audioEngine.DECAY_TIME); } /** @@ -133,8 +134,7 @@ class AudioPlayer { * @param {number} value - the volume in range 0-100 */ setVolume (value) { - if (this.audioEngine === null) return; - this.outputNode.gain.setTargetAtTime(value / 100, 0, this.audioEngine.DECAY_TIME); + this.setEffect('volume', value); } /** @@ -150,6 +150,7 @@ class AudioPlayer { * Clean up and disconnect audio nodes. */ dispose () { + this.effects.volume.dispose(); this.effects.pitch.dispose(); this.effects.pan.dispose();