Merge pull request #55 from LLK/feature/panner

Implement panning without panner node
This commit is contained in:
Eric Rosenbaum 2017-07-25 11:34:51 -04:00 committed by GitHub
commit 5cb4146aa7
2 changed files with 27 additions and 25 deletions

View file

@ -2,7 +2,6 @@
* A pan effect, which moves the sound to the left or right between the speakers * A pan effect, which moves the sound to the left or right between the speakers
* Effect value of -100 puts the audio entirely on the left channel, * Effect value of -100 puts the audio entirely on the left channel,
* 0 centers it, 100 puts it on the right. * 0 centers it, 100 puts it on the right.
* Clamped -100 to 100
*/ */
class PanEffect { class PanEffect {
/** /**
@ -11,8 +10,19 @@ class PanEffect {
*/ */
constructor (audioContext) { constructor (audioContext) {
this.audioContext = audioContext; this.audioContext = audioContext;
this.panner = this.audioContext.createStereoPanner();
this.value = 0; this.value = 0;
this.input = this.audioContext.createGain();
this.leftGain = this.audioContext.createGain();
this.rightGain = this.audioContext.createGain();
this.channelMerger = this.audioContext.createChannelMerger(2);
this.input.connect(this.leftGain);
this.input.connect(this.rightGain);
this.leftGain.connect(this.channelMerger, 0, 0);
this.rightGain.connect(this.channelMerger, 0, 1);
this.set(this.value);
} }
/** /**
@ -20,31 +30,23 @@ class PanEffect {
* @param {number} val - the new value to set the effect to * @param {number} val - the new value to set the effect to
*/ */
set (val) { set (val) {
this.value = this.clamp(val, -100, 100); this.value = val;
this.panner.pan.value = this.value / 100;
// Map the scratch effect value (-100 to 100) to (0 to 1)
const p = (val + 100) / 200;
// Use trig functions for equal-loudness panning
// See e.g. https://docs.cycling74.com/max7/tutorials/13_panningchapter01
this.leftGain.gain.value = Math.cos(p * Math.PI / 2);
this.rightGain.gain.value = Math.sin(p * Math.PI / 2);
} }
/**
* Connnect this effect's output to another audio node
* @param {AudioNode} node - the node to connect to
*/
connect (node) { connect (node) {
this.panner.connect(node); this.channelMerger.connect(node);
}
/**
* Change the effect value
* @param {number} val - the value to change the effect by
*/
changeBy (val) {
this.set(this.value + val);
}
/**
* Clamp the input to a range
* @param {number} input - the input to clamp
* @param {number} min - the min value to clamp to
* @param {number} max - the max value to clamp to
* @return {number} the clamped value
*/
clamp (input, min, max) {
return Math.min(Math.max(input, min), max);
} }
} }

View file

@ -33,7 +33,7 @@ class AudioPlayer {
// Chain the audio effects together // Chain the audio effects together
// effectsNode -> panEffect -> audioEngine.input // effectsNode -> panEffect -> audioEngine.input
this.effectsNode = this.audioEngine.audioContext.createGain(); this.effectsNode = this.audioEngine.audioContext.createGain();
this.effectsNode.connect(this.panEffect.panner); this.effectsNode.connect(this.panEffect.input);
this.panEffect.connect(this.audioEngine.input); this.panEffect.connect(this.audioEngine.input);
// reset effects to their default parameters // reset effects to their default parameters