2024-05-03 18:31:14 +00:00
|
|
|
import { Effect, EffectOptions } from "./Effect.js";
|
|
|
|
import { ToneOscillatorType } from "../source/oscillator/OscillatorInterface.js";
|
|
|
|
import { Frequency, NormalRange, Seconds } from "../core/type/Units.js";
|
|
|
|
import { optionsFromArguments } from "../core/util/Defaults.js";
|
|
|
|
import { LFO } from "../source/oscillator/LFO.js";
|
|
|
|
import { Delay } from "../core/context/Delay.js";
|
|
|
|
import { Signal } from "../signal/Signal.js";
|
|
|
|
import { Param } from "../core/context/Param.js";
|
|
|
|
import { readOnly } from "../core/util/Interface.js";
|
2019-11-04 03:44:49 +00:00
|
|
|
|
|
|
|
export interface VibratoOptions extends EffectOptions {
|
|
|
|
maxDelay: Seconds;
|
|
|
|
frequency: Frequency;
|
|
|
|
depth: NormalRange;
|
|
|
|
type: ToneOscillatorType;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* A Vibrato effect composed of a Tone.Delay and a Tone.LFO. The LFO
|
2024-05-03 18:31:14 +00:00
|
|
|
* modulates the delayTime of the delay, causing the pitch to rise and fall.
|
2019-11-05 03:29:14 +00:00
|
|
|
* @category Effect
|
2019-11-04 03:44:49 +00:00
|
|
|
*/
|
|
|
|
export class Vibrato extends Effect<VibratoOptions> {
|
|
|
|
readonly name: string = "Vibrato";
|
|
|
|
/**
|
|
|
|
* The delay node used for the vibrato effect
|
|
|
|
*/
|
|
|
|
private _delayNode: Delay;
|
2024-05-03 18:31:14 +00:00
|
|
|
|
2019-11-04 03:44:49 +00:00
|
|
|
/**
|
|
|
|
* The LFO used to control the vibrato
|
|
|
|
*/
|
|
|
|
private _lfo: LFO;
|
2024-05-03 18:31:14 +00:00
|
|
|
|
2019-11-04 03:44:49 +00:00
|
|
|
/**
|
|
|
|
* The frequency of the vibrato
|
|
|
|
*/
|
|
|
|
readonly frequency: Signal<"frequency">;
|
2024-05-03 18:31:14 +00:00
|
|
|
|
2019-11-04 03:44:49 +00:00
|
|
|
/**
|
2024-05-03 18:31:14 +00:00
|
|
|
* The depth of the vibrato.
|
2019-11-04 03:44:49 +00:00
|
|
|
*/
|
|
|
|
readonly depth: Param<"normalRange">;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param frequency The frequency of the vibrato.
|
|
|
|
* @param depth The amount the pitch is modulated.
|
|
|
|
*/
|
|
|
|
constructor(frequency?: Frequency, depth?: NormalRange);
|
|
|
|
constructor(options?: Partial<VibratoOptions>);
|
|
|
|
constructor() {
|
2024-05-03 18:31:14 +00:00
|
|
|
super(
|
|
|
|
optionsFromArguments(Vibrato.getDefaults(), arguments, [
|
|
|
|
"frequency",
|
|
|
|
"depth",
|
|
|
|
])
|
|
|
|
);
|
|
|
|
const options = optionsFromArguments(Vibrato.getDefaults(), arguments, [
|
|
|
|
"frequency",
|
|
|
|
"depth",
|
|
|
|
]);
|
2019-11-04 03:44:49 +00:00
|
|
|
|
|
|
|
this._delayNode = new Delay({
|
|
|
|
context: this.context,
|
|
|
|
delayTime: 0,
|
|
|
|
maxDelay: options.maxDelay,
|
|
|
|
});
|
|
|
|
this._lfo = new LFO({
|
|
|
|
context: this.context,
|
|
|
|
type: options.type,
|
|
|
|
min: 0,
|
2024-05-03 18:31:14 +00:00
|
|
|
max: options.maxDelay,
|
2019-11-04 03:44:49 +00:00
|
|
|
frequency: options.frequency,
|
2024-05-03 18:31:14 +00:00
|
|
|
phase: -90, // offse the phase so the resting position is in the center
|
|
|
|
})
|
|
|
|
.start()
|
|
|
|
.connect(this._delayNode.delayTime);
|
2019-11-04 03:44:49 +00:00
|
|
|
this.frequency = this._lfo.frequency;
|
|
|
|
this.depth = this._lfo.amplitude;
|
|
|
|
|
|
|
|
this.depth.value = options.depth;
|
|
|
|
readOnly(this, ["frequency", "depth"]);
|
|
|
|
this.effectSend.chain(this._delayNode, this.effectReturn);
|
|
|
|
}
|
|
|
|
|
|
|
|
static getDefaults(): VibratoOptions {
|
|
|
|
return Object.assign(Effect.getDefaults(), {
|
|
|
|
maxDelay: 0.005,
|
|
|
|
frequency: 5,
|
|
|
|
depth: 0.1,
|
2024-05-03 18:31:14 +00:00
|
|
|
type: "sine" as const,
|
2019-11-04 03:44:49 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Type of oscillator attached to the Vibrato.
|
|
|
|
*/
|
|
|
|
get type(): ToneOscillatorType {
|
|
|
|
return this._lfo.type;
|
|
|
|
}
|
|
|
|
set type(type) {
|
|
|
|
this._lfo.type = type;
|
|
|
|
}
|
2024-05-03 18:31:14 +00:00
|
|
|
|
2019-11-04 03:44:49 +00:00
|
|
|
dispose(): this {
|
|
|
|
super.dispose();
|
|
|
|
this._delayNode.dispose();
|
|
|
|
this._lfo.dispose();
|
|
|
|
this.frequency.dispose();
|
|
|
|
this.depth.dispose();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|