UNPKG

4.46 kBJavaScriptView Raw
1import { Signal } from "../signal/Signal.js";
2import { Multiply } from "../signal/Multiply.js";
3import { Gain } from "../core/context/Gain.js";
4import { Envelope } from "../component/envelope/Envelope.js";
5import { ToneAudioNode, } from "../core/context/ToneAudioNode.js";
6import { Monophonic } from "./Monophonic.js";
7import { OmniOscillator } from "../source/oscillator/OmniOscillator.js";
8import { Source } from "../source/Source.js";
9import { Synth } from "./Synth.js";
10import { readOnly } from "../core/util/Interface.js";
11import { omitFromObject, optionsFromArguments } from "../core/util/Defaults.js";
12/**
13 * Base class for both AM and FM synths
14 */
15export class ModulationSynth extends Monophonic {
16 constructor() {
17 const options = optionsFromArguments(ModulationSynth.getDefaults(), arguments);
18 super(options);
19 this.name = "ModulationSynth";
20 this._carrier = new Synth({
21 context: this.context,
22 oscillator: options.oscillator,
23 envelope: options.envelope,
24 onsilence: () => this.onsilence(this),
25 volume: -10,
26 });
27 this._modulator = new Synth({
28 context: this.context,
29 oscillator: options.modulation,
30 envelope: options.modulationEnvelope,
31 volume: -10,
32 });
33 this.oscillator = this._carrier.oscillator;
34 this.envelope = this._carrier.envelope;
35 this.modulation = this._modulator.oscillator;
36 this.modulationEnvelope = this._modulator.envelope;
37 this.frequency = new Signal({
38 context: this.context,
39 units: "frequency",
40 });
41 this.detune = new Signal({
42 context: this.context,
43 value: options.detune,
44 units: "cents",
45 });
46 this.harmonicity = new Multiply({
47 context: this.context,
48 value: options.harmonicity,
49 minValue: 0,
50 });
51 this._modulationNode = new Gain({
52 context: this.context,
53 gain: 0,
54 });
55 readOnly(this, [
56 "frequency",
57 "harmonicity",
58 "oscillator",
59 "envelope",
60 "modulation",
61 "modulationEnvelope",
62 "detune",
63 ]);
64 }
65 static getDefaults() {
66 return Object.assign(Monophonic.getDefaults(), {
67 harmonicity: 3,
68 oscillator: Object.assign(omitFromObject(OmniOscillator.getDefaults(), [
69 ...Object.keys(Source.getDefaults()),
70 "frequency",
71 "detune",
72 ]), {
73 type: "sine",
74 }),
75 envelope: Object.assign(omitFromObject(Envelope.getDefaults(), Object.keys(ToneAudioNode.getDefaults())), {
76 attack: 0.01,
77 decay: 0.01,
78 sustain: 1,
79 release: 0.5,
80 }),
81 modulation: Object.assign(omitFromObject(OmniOscillator.getDefaults(), [
82 ...Object.keys(Source.getDefaults()),
83 "frequency",
84 "detune",
85 ]), {
86 type: "square",
87 }),
88 modulationEnvelope: Object.assign(omitFromObject(Envelope.getDefaults(), Object.keys(ToneAudioNode.getDefaults())), {
89 attack: 0.5,
90 decay: 0.0,
91 sustain: 1,
92 release: 0.5,
93 }),
94 });
95 }
96 /**
97 * Trigger the attack portion of the note
98 */
99 _triggerEnvelopeAttack(time, velocity) {
100 // @ts-ignore
101 this._carrier._triggerEnvelopeAttack(time, velocity);
102 // @ts-ignore
103 this._modulator._triggerEnvelopeAttack(time, velocity);
104 }
105 /**
106 * Trigger the release portion of the note
107 */
108 _triggerEnvelopeRelease(time) {
109 // @ts-ignore
110 this._carrier._triggerEnvelopeRelease(time);
111 // @ts-ignore
112 this._modulator._triggerEnvelopeRelease(time);
113 return this;
114 }
115 getLevelAtTime(time) {
116 time = this.toSeconds(time);
117 return this.envelope.getValueAtTime(time);
118 }
119 dispose() {
120 super.dispose();
121 this._carrier.dispose();
122 this._modulator.dispose();
123 this.frequency.dispose();
124 this.detune.dispose();
125 this.harmonicity.dispose();
126 this._modulationNode.dispose();
127 return this;
128 }
129}
130//# sourceMappingURL=ModulationSynth.js.map
\No newline at end of file