UNPKG

5.07 kBJavaScriptView Raw
1import { Monophonic } from "./Monophonic.js";
2import { MonoSynth } from "./MonoSynth.js";
3import { Signal } from "../signal/Signal.js";
4import { readOnly } from "../core/util/Interface.js";
5import { LFO } from "../source/oscillator/LFO.js";
6import { Gain } from "../core/context/Gain.js";
7import { Multiply } from "../signal/Multiply.js";
8import { deepMerge, omitFromObject, optionsFromArguments, } from "../core/util/Defaults.js";
9/**
10 * DuoSynth is a monophonic synth composed of two {@link MonoSynth}s run in parallel with control over the
11 * frequency ratio between the two voices and vibrato effect.
12 * @example
13 * const duoSynth = new Tone.DuoSynth().toDestination();
14 * duoSynth.triggerAttackRelease("C4", "2n");
15 * @category Instrument
16 */
17export class DuoSynth extends Monophonic {
18 constructor() {
19 const options = optionsFromArguments(DuoSynth.getDefaults(), arguments);
20 super(options);
21 this.name = "DuoSynth";
22 this.voice0 = new MonoSynth(Object.assign(options.voice0, {
23 context: this.context,
24 onsilence: () => this.onsilence(this),
25 }));
26 this.voice1 = new MonoSynth(Object.assign(options.voice1, {
27 context: this.context,
28 }));
29 this.harmonicity = new Multiply({
30 context: this.context,
31 units: "positive",
32 value: options.harmonicity,
33 });
34 this._vibrato = new LFO({
35 frequency: options.vibratoRate,
36 context: this.context,
37 min: -50,
38 max: 50,
39 });
40 // start the vibrato immediately
41 this._vibrato.start();
42 this.vibratoRate = this._vibrato.frequency;
43 this._vibratoGain = new Gain({
44 context: this.context,
45 units: "normalRange",
46 gain: options.vibratoAmount,
47 });
48 this.vibratoAmount = this._vibratoGain.gain;
49 this.frequency = new Signal({
50 context: this.context,
51 units: "frequency",
52 value: 440,
53 });
54 this.detune = new Signal({
55 context: this.context,
56 units: "cents",
57 value: options.detune,
58 });
59 // control the two voices frequency
60 this.frequency.connect(this.voice0.frequency);
61 this.frequency.chain(this.harmonicity, this.voice1.frequency);
62 this._vibrato.connect(this._vibratoGain);
63 this._vibratoGain.fan(this.voice0.detune, this.voice1.detune);
64 this.detune.fan(this.voice0.detune, this.voice1.detune);
65 this.voice0.connect(this.output);
66 this.voice1.connect(this.output);
67 readOnly(this, [
68 "voice0",
69 "voice1",
70 "frequency",
71 "vibratoAmount",
72 "vibratoRate",
73 ]);
74 }
75 getLevelAtTime(time) {
76 time = this.toSeconds(time);
77 return (this.voice0.envelope.getValueAtTime(time) +
78 this.voice1.envelope.getValueAtTime(time));
79 }
80 static getDefaults() {
81 return deepMerge(Monophonic.getDefaults(), {
82 vibratoAmount: 0.5,
83 vibratoRate: 5,
84 harmonicity: 1.5,
85 voice0: deepMerge(omitFromObject(MonoSynth.getDefaults(), Object.keys(Monophonic.getDefaults())), {
86 filterEnvelope: {
87 attack: 0.01,
88 decay: 0.0,
89 sustain: 1,
90 release: 0.5,
91 },
92 envelope: {
93 attack: 0.01,
94 decay: 0.0,
95 sustain: 1,
96 release: 0.5,
97 },
98 }),
99 voice1: deepMerge(omitFromObject(MonoSynth.getDefaults(), Object.keys(Monophonic.getDefaults())), {
100 filterEnvelope: {
101 attack: 0.01,
102 decay: 0.0,
103 sustain: 1,
104 release: 0.5,
105 },
106 envelope: {
107 attack: 0.01,
108 decay: 0.0,
109 sustain: 1,
110 release: 0.5,
111 },
112 }),
113 });
114 }
115 /**
116 * Trigger the attack portion of the note
117 */
118 _triggerEnvelopeAttack(time, velocity) {
119 // @ts-ignore
120 this.voice0._triggerEnvelopeAttack(time, velocity);
121 // @ts-ignore
122 this.voice1._triggerEnvelopeAttack(time, velocity);
123 }
124 /**
125 * Trigger the release portion of the note
126 */
127 _triggerEnvelopeRelease(time) {
128 // @ts-ignore
129 this.voice0._triggerEnvelopeRelease(time);
130 // @ts-ignore
131 this.voice1._triggerEnvelopeRelease(time);
132 return this;
133 }
134 dispose() {
135 super.dispose();
136 this.voice0.dispose();
137 this.voice1.dispose();
138 this.frequency.dispose();
139 this.detune.dispose();
140 this._vibrato.dispose();
141 this.vibratoRate.dispose();
142 this._vibratoGain.dispose();
143 this.harmonicity.dispose();
144 return this;
145 }
146}
147//# sourceMappingURL=DuoSynth.js.map
\No newline at end of file