2019-07-25 04:10:46 +00:00
|
|
|
import { CrossFade } from "../component/channel/CrossFade";
|
|
|
|
import { Gain } from "../core/context/Gain";
|
2019-10-31 19:43:16 +00:00
|
|
|
import { ToneAudioNode, ToneAudioNodeOptions } from "../core/context/ToneAudioNode";
|
2019-07-30 19:35:27 +00:00
|
|
|
import { NormalRange } from "../core/type/Units";
|
2019-07-25 04:10:46 +00:00
|
|
|
import { readOnly } from "../core/util/Interface";
|
|
|
|
import { Signal } from "../signal/Signal";
|
|
|
|
|
|
|
|
export interface EffectOptions extends ToneAudioNodeOptions {
|
|
|
|
wet: NormalRange;
|
|
|
|
}
|
|
|
|
/**
|
2019-08-27 16:00:59 +00:00
|
|
|
* Effect is the base class for effects. Connect the effect between
|
|
|
|
* the effectSend and effectReturn GainNodes, then control the amount of
|
|
|
|
* effect which goes to the output using the wet control.
|
2019-07-25 04:10:46 +00:00
|
|
|
*/
|
|
|
|
export abstract class Effect<Options extends EffectOptions>
|
2019-09-14 22:12:44 +00:00
|
|
|
extends ToneAudioNode<Options> {
|
2019-07-25 04:10:46 +00:00
|
|
|
|
2019-08-03 01:09:35 +00:00
|
|
|
readonly name: string = "Effect";
|
2019-07-25 04:10:46 +00:00
|
|
|
|
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* the drywet knob to control the amount of effect
|
2019-07-25 04:10:46 +00:00
|
|
|
*/
|
2019-09-14 22:12:44 +00:00
|
|
|
private _dryWet: CrossFade = new CrossFade({ context: this.context });
|
2019-07-25 04:10:46 +00:00
|
|
|
|
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* The wet control is how much of the effected
|
|
|
|
* will pass through to the output. 1 = 100% effected
|
|
|
|
* signal, 0 = 100% dry signal.
|
2019-07-25 04:10:46 +00:00
|
|
|
*/
|
2019-10-28 15:37:53 +00:00
|
|
|
wet: Signal<"normalRange"> = this._dryWet.fade;
|
2019-07-25 04:10:46 +00:00
|
|
|
|
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* connect the effectSend to the input of hte effect
|
2019-07-25 04:10:46 +00:00
|
|
|
*/
|
2019-09-14 22:12:44 +00:00
|
|
|
protected effectSend: Gain = new Gain({ context: this.context });
|
2019-07-25 04:10:46 +00:00
|
|
|
|
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* connect the output of the effect to the effectReturn
|
2019-07-25 04:10:46 +00:00
|
|
|
*/
|
2019-09-14 22:12:44 +00:00
|
|
|
protected effectReturn: Gain = new Gain({ context: this.context });
|
2019-07-25 04:10:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The effect input node
|
|
|
|
*/
|
2019-09-14 22:12:44 +00:00
|
|
|
input: Gain = new Gain({ context: this.context });
|
2019-07-25 04:10:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The effect output
|
|
|
|
*/
|
|
|
|
output = this._dryWet;
|
|
|
|
|
|
|
|
constructor(options: EffectOptions) {
|
|
|
|
super(options);
|
|
|
|
|
|
|
|
// connections
|
|
|
|
this.input.fan(this._dryWet.a, this.effectSend);
|
|
|
|
this.effectReturn.connect(this._dryWet.b);
|
|
|
|
this.wet.setValueAtTime(options.wet, 0);
|
2019-08-03 16:00:14 +00:00
|
|
|
this._internalChannels = [this.effectReturn, this.effectSend];
|
2019-07-25 04:10:46 +00:00
|
|
|
readOnly(this, "wet");
|
|
|
|
}
|
|
|
|
|
|
|
|
static getDefaults(): EffectOptions {
|
|
|
|
return Object.assign(ToneAudioNode.getDefaults(), {
|
2019-09-14 22:12:44 +00:00
|
|
|
wet: 1,
|
2019-07-25 04:10:46 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-09-14 20:39:18 +00:00
|
|
|
* chains the effect in between the effectSend and effectReturn
|
2019-07-25 04:10:46 +00:00
|
|
|
*/
|
2019-08-03 16:00:14 +00:00
|
|
|
protected connectEffect(effect: ToneAudioNode | AudioNode): this {
|
|
|
|
// add it to the internal channels
|
|
|
|
this._internalChannels.push(effect);
|
2019-07-25 04:10:46 +00:00
|
|
|
this.effectSend.chain(effect, this.effectReturn);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
dispose(): this {
|
|
|
|
super.dispose();
|
|
|
|
this._dryWet.dispose();
|
|
|
|
this.effectSend.dispose();
|
|
|
|
this.effectReturn.dispose();
|
|
|
|
this.wet.dispose();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|