1 | import { AmplitudeEnvelope } from "../component/envelope/AmplitudeEnvelope.js";
|
2 | import { Envelope } from "../component/envelope/Envelope.js";
|
3 | import { ToneAudioNode, } from "../core/context/ToneAudioNode.js";
|
4 | import { omitFromObject, optionsFromArguments } from "../core/util/Defaults.js";
|
5 | import { readOnly } from "../core/util/Interface.js";
|
6 | import { OmniOscillator } from "../source/oscillator/OmniOscillator.js";
|
7 | import { Source } from "../source/Source.js";
|
8 | import { Monophonic } from "./Monophonic.js";
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | export 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 |
|
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 |
|
59 |
|
60 |
|
61 |
|
62 | _triggerEnvelopeAttack(time, velocity) {
|
63 |
|
64 | this.envelope.triggerAttack(time, velocity);
|
65 | this.oscillator.start(time);
|
66 |
|
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 |
|
75 |
|
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 |
|
87 |
|
88 | dispose() {
|
89 | super.dispose();
|
90 | this.oscillator.dispose();
|
91 | this.envelope.dispose();
|
92 | return this;
|
93 | }
|
94 | }
|
95 |
|
\ | No newline at end of file |