UNPKG

tone

Version:

A Web Audio framework for making interactive music in the browser.

140 lines 5 kB
import { Monophonic } from "./Monophonic"; import { MonoSynth } from "./MonoSynth"; import { Signal } from "../signal/Signal"; import { readOnly } from "../core/util/Interface"; import { LFO } from "../source/oscillator/LFO"; import { Gain, } from "../core/context/Gain"; import { Multiply } from "../signal/Multiply"; import { deepMerge, omitFromObject, optionsFromArguments } from "../core/util/Defaults"; /** * DuoSynth is a monophonic synth composed of two [[MonoSynths]] run in parallel with control over the * frequency ratio between the two voices and vibrato effect. * @example * const duoSynth = new Tone.DuoSynth().toDestination(); * duoSynth.triggerAttackRelease("C4", "2n"); * @category Instrument */ export class DuoSynth extends Monophonic { constructor() { super(optionsFromArguments(DuoSynth.getDefaults(), arguments)); this.name = "DuoSynth"; const options = optionsFromArguments(DuoSynth.getDefaults(), arguments); this.voice0 = new MonoSynth(Object.assign(options.voice0, { context: this.context, onsilence: () => this.onsilence(this) })); this.voice1 = new MonoSynth(Object.assign(options.voice1, { context: this.context, })); this.harmonicity = new Multiply({ context: this.context, units: "positive", value: options.harmonicity, }); this._vibrato = new LFO({ frequency: options.vibratoRate, context: this.context, min: -50, max: 50 }); // start the vibrato immediately this._vibrato.start(); this.vibratoRate = this._vibrato.frequency; this._vibratoGain = new Gain({ context: this.context, units: "normalRange", gain: options.vibratoAmount }); this.vibratoAmount = this._vibratoGain.gain; this.frequency = new Signal({ context: this.context, units: "frequency", value: 440 }); this.detune = new Signal({ context: this.context, units: "cents", value: options.detune }); // control the two voices frequency this.frequency.connect(this.voice0.frequency); this.frequency.chain(this.harmonicity, this.voice1.frequency); this._vibrato.connect(this._vibratoGain); this._vibratoGain.fan(this.voice0.detune, this.voice1.detune); this.detune.fan(this.voice0.detune, this.voice1.detune); this.voice0.connect(this.output); this.voice1.connect(this.output); readOnly(this, ["voice0", "voice1", "frequency", "vibratoAmount", "vibratoRate"]); } getLevelAtTime(time) { time = this.toSeconds(time); return this.voice0.envelope.getValueAtTime(time) + this.voice1.envelope.getValueAtTime(time); } static getDefaults() { return deepMerge(Monophonic.getDefaults(), { vibratoAmount: 0.5, vibratoRate: 5, harmonicity: 1.5, voice0: deepMerge(omitFromObject(MonoSynth.getDefaults(), Object.keys(Monophonic.getDefaults())), { filterEnvelope: { attack: 0.01, decay: 0.0, sustain: 1, release: 0.5 }, envelope: { attack: 0.01, decay: 0.0, sustain: 1, release: 0.5 } }), voice1: deepMerge(omitFromObject(MonoSynth.getDefaults(), Object.keys(Monophonic.getDefaults())), { filterEnvelope: { attack: 0.01, decay: 0.0, sustain: 1, release: 0.5 }, envelope: { attack: 0.01, decay: 0.0, sustain: 1, release: 0.5 } }), }); } /** * Trigger the attack portion of the note */ _triggerEnvelopeAttack(time, velocity) { // @ts-ignore this.voice0._triggerEnvelopeAttack(time, velocity); // @ts-ignore this.voice1._triggerEnvelopeAttack(time, velocity); } /** * Trigger the release portion of the note */ _triggerEnvelopeRelease(time) { // @ts-ignore this.voice0._triggerEnvelopeRelease(time); // @ts-ignore this.voice1._triggerEnvelopeRelease(time); return this; } dispose() { super.dispose(); this.voice0.dispose(); this.voice1.dispose(); this.frequency.dispose(); this.detune.dispose(); this._vibrato.dispose(); this.vibratoRate.dispose(); this._vibratoGain.dispose(); this.harmonicity.dispose(); return this; } } //# sourceMappingURL=DuoSynth.js.map