UNPKG

4.07 kBJavaScriptView Raw
1import { StereoEffect } from "./StereoEffect.js";
2import { optionsFromArguments } from "../core/util/Defaults.js";
3import { LFO } from "../source/oscillator/LFO.js";
4import { Signal } from "../signal/Signal.js";
5import { readOnly } from "../core/util/Interface.js";
6/**
7 * Phaser is a phaser effect. Phasers work by changing the phase
8 * of different frequency components of an incoming signal. Read more on
9 * [Wikipedia](https://en.wikipedia.org/wiki/Phaser_(effect)).
10 * Inspiration for this phaser comes from [Tuna.js](https://github.com/Dinahmoe/tuna/).
11 * @example
12 * const phaser = new Tone.Phaser({
13 * frequency: 15,
14 * octaves: 5,
15 * baseFrequency: 1000
16 * }).toDestination();
17 * const synth = new Tone.FMSynth().connect(phaser);
18 * synth.triggerAttackRelease("E3", "2n");
19 * @category Effect
20 */
21export class Phaser extends StereoEffect {
22 constructor() {
23 const options = optionsFromArguments(Phaser.getDefaults(), arguments, [
24 "frequency",
25 "octaves",
26 "baseFrequency",
27 ]);
28 super(options);
29 this.name = "Phaser";
30 this._lfoL = new LFO({
31 context: this.context,
32 frequency: options.frequency,
33 min: 0,
34 max: 1,
35 });
36 this._lfoR = new LFO({
37 context: this.context,
38 frequency: options.frequency,
39 min: 0,
40 max: 1,
41 phase: 180,
42 });
43 this._baseFrequency = this.toFrequency(options.baseFrequency);
44 this._octaves = options.octaves;
45 this.Q = new Signal({
46 context: this.context,
47 value: options.Q,
48 units: "positive",
49 });
50 this._filtersL = this._makeFilters(options.stages, this._lfoL);
51 this._filtersR = this._makeFilters(options.stages, this._lfoR);
52 this.frequency = this._lfoL.frequency;
53 this.frequency.value = options.frequency;
54 // connect them up
55 this.connectEffectLeft(...this._filtersL);
56 this.connectEffectRight(...this._filtersR);
57 // control the frequency with one LFO
58 this._lfoL.frequency.connect(this._lfoR.frequency);
59 // set the options
60 this.baseFrequency = options.baseFrequency;
61 this.octaves = options.octaves;
62 // start the lfo
63 this._lfoL.start();
64 this._lfoR.start();
65 readOnly(this, ["frequency", "Q"]);
66 }
67 static getDefaults() {
68 return Object.assign(StereoEffect.getDefaults(), {
69 frequency: 0.5,
70 octaves: 3,
71 stages: 10,
72 Q: 10,
73 baseFrequency: 350,
74 });
75 }
76 _makeFilters(stages, connectToFreq) {
77 const filters = [];
78 // make all the filters
79 for (let i = 0; i < stages; i++) {
80 const filter = this.context.createBiquadFilter();
81 filter.type = "allpass";
82 this.Q.connect(filter.Q);
83 connectToFreq.connect(filter.frequency);
84 filters.push(filter);
85 }
86 return filters;
87 }
88 /**
89 * The number of octaves the phase goes above the baseFrequency
90 */
91 get octaves() {
92 return this._octaves;
93 }
94 set octaves(octaves) {
95 this._octaves = octaves;
96 const max = this._baseFrequency * Math.pow(2, octaves);
97 this._lfoL.max = max;
98 this._lfoR.max = max;
99 }
100 /**
101 * The the base frequency of the filters.
102 */
103 get baseFrequency() {
104 return this._baseFrequency;
105 }
106 set baseFrequency(freq) {
107 this._baseFrequency = this.toFrequency(freq);
108 this._lfoL.min = this._baseFrequency;
109 this._lfoR.min = this._baseFrequency;
110 this.octaves = this._octaves;
111 }
112 dispose() {
113 super.dispose();
114 this.Q.dispose();
115 this._lfoL.dispose();
116 this._lfoR.dispose();
117 this._filtersL.forEach((f) => f.disconnect());
118 this._filtersR.forEach((f) => f.disconnect());
119 this.frequency.dispose();
120 return this;
121 }
122}
123//# sourceMappingURL=Phaser.js.map
\No newline at end of file