UNPKG

2.74 kBPlain TextView Raw
1import { Effect, EffectOptions } from "./Effect.js";
2import { ToneOscillatorType } from "../source/oscillator/OscillatorInterface.js";
3import { Frequency, NormalRange, Seconds } from "../core/type/Units.js";
4import { optionsFromArguments } from "../core/util/Defaults.js";
5import { LFO } from "../source/oscillator/LFO.js";
6import { Delay } from "../core/context/Delay.js";
7import { Signal } from "../signal/Signal.js";
8import { Param } from "../core/context/Param.js";
9import { readOnly } from "../core/util/Interface.js";
10
11export interface VibratoOptions extends EffectOptions {
12 maxDelay: Seconds;
13 frequency: Frequency;
14 depth: NormalRange;
15 type: ToneOscillatorType;
16}
17/**
18 * A Vibrato effect composed of a Tone.Delay and a Tone.LFO. The LFO
19 * modulates the delayTime of the delay, causing the pitch to rise and fall.
20 * @category Effect
21 */
22export class Vibrato extends Effect<VibratoOptions> {
23 readonly name: string = "Vibrato";
24 /**
25 * The delay node used for the vibrato effect
26 */
27 private _delayNode: Delay;
28
29 /**
30 * The LFO used to control the vibrato
31 */
32 private _lfo: LFO;
33
34 /**
35 * The frequency of the vibrato
36 */
37 readonly frequency: Signal<"frequency">;
38
39 /**
40 * The depth of the vibrato.
41 */
42 readonly depth: Param<"normalRange">;
43
44 /**
45 * @param frequency The frequency of the vibrato.
46 * @param depth The amount the pitch is modulated.
47 */
48 constructor(frequency?: Frequency, depth?: NormalRange);
49 constructor(options?: Partial<VibratoOptions>);
50 constructor() {
51 const options = optionsFromArguments(Vibrato.getDefaults(), arguments, [
52 "frequency",
53 "depth",
54 ]);
55 super(options);
56
57 this._delayNode = new Delay({
58 context: this.context,
59 delayTime: 0,
60 maxDelay: options.maxDelay,
61 });
62 this._lfo = new LFO({
63 context: this.context,
64 type: options.type,
65 min: 0,
66 max: options.maxDelay,
67 frequency: options.frequency,
68 phase: -90, // offse the phase so the resting position is in the center
69 })
70 .start()
71 .connect(this._delayNode.delayTime);
72 this.frequency = this._lfo.frequency;
73 this.depth = this._lfo.amplitude;
74
75 this.depth.value = options.depth;
76 readOnly(this, ["frequency", "depth"]);
77 this.effectSend.chain(this._delayNode, this.effectReturn);
78 }
79
80 static getDefaults(): VibratoOptions {
81 return Object.assign(Effect.getDefaults(), {
82 maxDelay: 0.005,
83 frequency: 5,
84 depth: 0.1,
85 type: "sine" as const,
86 });
87 }
88
89 /**
90 * Type of oscillator attached to the Vibrato.
91 */
92 get type(): ToneOscillatorType {
93 return this._lfo.type;
94 }
95 set type(type) {
96 this._lfo.type = type;
97 }
98
99 dispose(): this {
100 super.dispose();
101 this._delayNode.dispose();
102 this._lfo.dispose();
103 this.frequency.dispose();
104 this.depth.dispose();
105 return this;
106 }
107}