1 | import { Effect, EffectOptions } from "./Effect.js";
|
2 | import { ToneOscillatorType } from "../source/oscillator/OscillatorInterface.js";
|
3 | import { Frequency, NormalRange, Seconds } from "../core/type/Units.js";
|
4 | import { optionsFromArguments } from "../core/util/Defaults.js";
|
5 | import { LFO } from "../source/oscillator/LFO.js";
|
6 | import { Delay } from "../core/context/Delay.js";
|
7 | import { Signal } from "../signal/Signal.js";
|
8 | import { Param } from "../core/context/Param.js";
|
9 | import { readOnly } from "../core/util/Interface.js";
|
10 |
|
11 | export interface VibratoOptions extends EffectOptions {
|
12 | maxDelay: Seconds;
|
13 | frequency: Frequency;
|
14 | depth: NormalRange;
|
15 | type: ToneOscillatorType;
|
16 | }
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | export class Vibrato extends Effect<VibratoOptions> {
|
23 | readonly name: string = "Vibrato";
|
24 | |
25 |
|
26 |
|
27 | private _delayNode: Delay;
|
28 |
|
29 | |
30 |
|
31 |
|
32 | private _lfo: LFO;
|
33 |
|
34 | |
35 |
|
36 |
|
37 | readonly frequency: Signal<"frequency">;
|
38 |
|
39 | |
40 |
|
41 |
|
42 | readonly depth: Param<"normalRange">;
|
43 |
|
44 | |
45 |
|
46 |
|
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,
|
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 | }
|