Tone.js/Tone/effect/StereoFeedbackEffect.ts
Yotam Mann a28f1af610 feat: Chorus extends StereoFeedbackEffect
This makes it possible to do flanger-type effects.

fixes #575
2019-11-13 12:58:37 -05:00

101 lines
3.1 KiB
TypeScript

import { StereoEffect, StereoEffectOptions } from "./StereoEffect";
import { NormalRange } from "../core/type/Units";
import { Signal } from "../signal/Signal";
import { Gain } from "../core/context/Gain";
import { readOnly } from "../core/util/Interface";
import { Split } from "../component/channel/Split";
import { Merge } from "../component/channel/Merge";
export interface StereoFeedbackEffectOptions extends StereoEffectOptions {
feedback: NormalRange;
}
/**
* Just like a stereo feedback effect, but the feedback is routed from left to right
* and right to left instead of on the same channel.
* ```
* +--------------------------------+ feedbackL <-----------------------------------+
* | |
* +--> +-----> +----> +---+
* feedbackMerge +--> split (EFFECT) merge +--> feedbackSplit
* +--> +-----> +----> +---+
* | |
* +--------------------------------+ feedbackR <-----------------------------------+
* ```
*/
export class StereoFeedbackEffect<Options extends StereoFeedbackEffectOptions> extends StereoEffect<Options> {
/**
* The amount of feedback from the output
* back into the input of the effect (routed
* across left and right channels).
*/
readonly feedback: Signal<"normalRange">;
/**
* the left side feedback
*/
protected _feedbackL: Gain;
/**
* the right side feedback
*/
protected _feedbackR: Gain;
/**
* Split the channels for feedback
*/
protected _feedbackSplit: Split;
/**
* Merge the channels for feedback
*/
protected _feedbackMerge: Merge;
constructor(options: StereoFeedbackEffectOptions) {
super(options);
this.feedback = new Signal({
context: this.context,
value: options.feedback,
units: "normalRange"
});
this._feedbackL = new Gain({ context: this.context });
this._feedbackR = new Gain({ context: this.context });
this._feedbackSplit = new Split({ context: this.context, channels: 2 });
this._feedbackMerge = new Merge({ context: this.context, channels: 2 });
this._merge.connect(this._feedbackSplit);
this._feedbackMerge.connect(this._split);
// the left output connected to the left input
this._feedbackSplit.connect(this._feedbackL, 0, 0);
this._feedbackL.connect(this._feedbackMerge, 0, 0);
// the right output connected to the right input
this._feedbackSplit.connect(this._feedbackR, 1, 0);
this._feedbackR.connect(this._feedbackMerge, 0, 1);
// the feedback control
this.feedback.fan(this._feedbackL.gain, this._feedbackR.gain);
readOnly(this, ["feedback"]);
}
static getDefaults(): StereoFeedbackEffectOptions {
return Object.assign(StereoEffect.getDefaults(), {
feedback: 0.5,
});
}
dispose(): this {
super.dispose();
this.feedback.dispose();
this._feedbackL.dispose();
this._feedbackR.dispose();
this._feedbackSplit.dispose();
this._feedbackMerge.dispose();
return this;
}
}