UNPKG

3.62 kBJavaScriptView Raw
1import { AmplitudeEnvelope } from "../component/envelope/AmplitudeEnvelope.js";
2import { Envelope } from "../component/envelope/Envelope.js";
3import { ToneAudioNode, } from "../core/context/ToneAudioNode.js";
4import { omitFromObject, optionsFromArguments } from "../core/util/Defaults.js";
5import { readOnly } from "../core/util/Interface.js";
6import { OmniOscillator } from "../source/oscillator/OmniOscillator.js";
7import { Source } from "../source/Source.js";
8import { Monophonic } from "./Monophonic.js";
9/**
10 * Synth is composed simply of a {@link OmniOscillator} routed through an {@link AmplitudeEnvelope}.
11 * ```
12 * +----------------+ +-------------------+
13 * | OmniOscillator +>--> AmplitudeEnvelope +>--> Output
14 * +----------------+ +-------------------+
15 * ```
16 * @example
17 * const synth = new Tone.Synth().toDestination();
18 * synth.triggerAttackRelease("C4", "8n");
19 * @category Instrument
20 */
21export class Synth extends Monophonic {
22 constructor() {
23 const options = optionsFromArguments(Synth.getDefaults(), arguments);
24 super(options);
25 this.name = "Synth";
26 this.oscillator = new OmniOscillator(Object.assign({
27 context: this.context,
28 detune: options.detune,
29 onstop: () => this.onsilence(this),
30 }, options.oscillator));
31 this.frequency = this.oscillator.frequency;
32 this.detune = this.oscillator.detune;
33 this.envelope = new AmplitudeEnvelope(Object.assign({
34 context: this.context,
35 }, options.envelope));
36 // connect the oscillators to the output
37 this.oscillator.chain(this.envelope, this.output);
38 readOnly(this, ["oscillator", "frequency", "detune", "envelope"]);
39 }
40 static getDefaults() {
41 return Object.assign(Monophonic.getDefaults(), {
42 envelope: Object.assign(omitFromObject(Envelope.getDefaults(), Object.keys(ToneAudioNode.getDefaults())), {
43 attack: 0.005,
44 decay: 0.1,
45 release: 1,
46 sustain: 0.3,
47 }),
48 oscillator: Object.assign(omitFromObject(OmniOscillator.getDefaults(), [
49 ...Object.keys(Source.getDefaults()),
50 "frequency",
51 "detune",
52 ]), {
53 type: "triangle",
54 }),
55 });
56 }
57 /**
58 * start the attack portion of the envelope
59 * @param time the time the attack should start
60 * @param velocity the velocity of the note (0-1)
61 */
62 _triggerEnvelopeAttack(time, velocity) {
63 // the envelopes
64 this.envelope.triggerAttack(time, velocity);
65 this.oscillator.start(time);
66 // if there is no release portion, stop the oscillator
67 if (this.envelope.sustain === 0) {
68 const computedAttack = this.toSeconds(this.envelope.attack);
69 const computedDecay = this.toSeconds(this.envelope.decay);
70 this.oscillator.stop(time + computedAttack + computedDecay);
71 }
72 }
73 /**
74 * start the release portion of the envelope
75 * @param time the time the release should start
76 */
77 _triggerEnvelopeRelease(time) {
78 this.envelope.triggerRelease(time);
79 this.oscillator.stop(time + this.toSeconds(this.envelope.release));
80 }
81 getLevelAtTime(time) {
82 time = this.toSeconds(time);
83 return this.envelope.getValueAtTime(time);
84 }
85 /**
86 * clean up
87 */
88 dispose() {
89 super.dispose();
90 this.oscillator.dispose();
91 this.envelope.dispose();
92 return this;
93 }
94}
95//# sourceMappingURL=Synth.js.map
\No newline at end of file