1 | import { PhaseShiftAllpass } from "../component/filter/PhaseShiftAllpass.js";
|
2 | import { optionsFromArguments } from "../core/util/Defaults.js";
|
3 | import { Effect } from "../effect/Effect.js";
|
4 | import { Add } from "../signal/Add.js";
|
5 | import { Multiply } from "../signal/Multiply.js";
|
6 | import { Negate } from "../signal/Negate.js";
|
7 | import { Signal } from "../signal/Signal.js";
|
8 | import { Oscillator } from "../source/oscillator/Oscillator.js";
|
9 | import { ToneOscillatorNode } from "../source/oscillator/ToneOscillatorNode.js";
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | export class FrequencyShifter extends Effect {
|
29 | constructor() {
|
30 | const options = optionsFromArguments(FrequencyShifter.getDefaults(), arguments, ["frequency"]);
|
31 | super(options);
|
32 | this.name = "FrequencyShifter";
|
33 | this.frequency = new Signal({
|
34 | context: this.context,
|
35 | units: "frequency",
|
36 | value: options.frequency,
|
37 | minValue: -this.context.sampleRate / 2,
|
38 | maxValue: this.context.sampleRate / 2,
|
39 | });
|
40 | this._sine = new ToneOscillatorNode({
|
41 | context: this.context,
|
42 | type: "sine",
|
43 | });
|
44 | this._cosine = new Oscillator({
|
45 | context: this.context,
|
46 | phase: -90,
|
47 | type: "sine",
|
48 | });
|
49 | this._sineMultiply = new Multiply({ context: this.context });
|
50 | this._cosineMultiply = new Multiply({ context: this.context });
|
51 | this._negate = new Negate({ context: this.context });
|
52 | this._add = new Add({ context: this.context });
|
53 | this._phaseShifter = new PhaseShiftAllpass({ context: this.context });
|
54 | this.effectSend.connect(this._phaseShifter);
|
55 |
|
56 | this.frequency.fan(this._sine.frequency, this._cosine.frequency);
|
57 | this._phaseShifter.offset90.connect(this._cosineMultiply);
|
58 | this._cosine.connect(this._cosineMultiply.factor);
|
59 | this._phaseShifter.connect(this._sineMultiply);
|
60 | this._sine.connect(this._sineMultiply.factor);
|
61 | this._sineMultiply.connect(this._negate);
|
62 | this._cosineMultiply.connect(this._add);
|
63 | this._negate.connect(this._add.addend);
|
64 | this._add.connect(this.effectReturn);
|
65 |
|
66 | const now = this.immediate();
|
67 | this._sine.start(now);
|
68 | this._cosine.start(now);
|
69 | }
|
70 | static getDefaults() {
|
71 | return Object.assign(Effect.getDefaults(), {
|
72 | frequency: 0,
|
73 | });
|
74 | }
|
75 | dispose() {
|
76 | super.dispose();
|
77 | this.frequency.dispose();
|
78 | this._add.dispose();
|
79 | this._cosine.dispose();
|
80 | this._cosineMultiply.dispose();
|
81 | this._negate.dispose();
|
82 | this._phaseShifter.dispose();
|
83 | this._sine.dispose();
|
84 | this._sineMultiply.dispose();
|
85 | return this;
|
86 | }
|
87 | }
|
88 |
|
\ | No newline at end of file |