Tone.js/Tone/instrument/MembraneSynth.ts

97 lines
2.8 KiB
TypeScript
Raw Normal View History

import { FrequencyClass } from "../core/type/Frequency";
import { Frequency, Positive, Time } from "../core/type/Units";
2019-08-16 17:57:38 +00:00
import { deepMerge, optionsFromArguments } from "../core/util/Defaults";
import { readOnly, RecursivePartial } from "../core/util/Interface";
import { Monophonic } from "./Monophonic";
2019-08-16 17:57:38 +00:00
import { Synth, SynthOptions } from "./Synth";
2019-12-30 23:49:55 +00:00
import { range, timeRange } from "../core/util/Decorator";
2019-08-16 17:57:38 +00:00
export interface MembraneSynthOptions extends SynthOptions {
2019-08-16 17:57:38 +00:00
pitchDecay: Time;
octaves: Positive;
}
/**
* MembraneSynth makes kick and tom sounds using a single oscillator
* with an amplitude envelope and frequency ramp. A Tone.OmniOscillator
* is routed through a Tone.AmplitudeEnvelope to the output. The drum
* quality of the sound comes from the frequency envelope applied
* during MembraneSynth.triggerAttack(note). The frequency envelope
* starts at <code>note * .octaves</code> and ramps to <code>note</code>
* over the duration of <code>.pitchDecay</code>.
* @example
* const synth = new Tone.MembraneSynth().toDestination();
2019-08-16 17:57:38 +00:00
* synth.triggerAttackRelease("C2", "8n");
2019-09-16 14:15:23 +00:00
* @category Instrument
2019-08-16 17:57:38 +00:00
*/
export class MembraneSynth extends Synth<MembraneSynthOptions> {
2019-08-16 17:57:38 +00:00
2019-09-04 23:18:44 +00:00
readonly name: string = "MembraneSynth";
2019-08-16 17:57:38 +00:00
/**
2019-09-14 20:39:18 +00:00
* The number of octaves the pitch envelope ramps.
2019-09-24 21:21:59 +00:00
* @min 0.5
* @max 8
2019-08-16 17:57:38 +00:00
*/
2019-12-30 23:49:55 +00:00
@range(0)
2019-08-16 17:57:38 +00:00
octaves: Positive;
/**
2019-09-14 20:39:18 +00:00
* The amount of time the frequency envelope takes.
2019-09-24 21:21:59 +00:00
* @min 0
* @max 0.5
2019-08-16 17:57:38 +00:00
*/
2019-12-30 23:49:55 +00:00
@timeRange(0)
2019-08-16 17:57:38 +00:00
pitchDecay: Time;
/**
* Portamento is ignored in this synth. use pitch decay instead.
*/
readonly portamento = 0;
2019-08-27 15:57:00 +00:00
/**
* @param options the options available for the synth see defaults
*/
2019-08-16 17:57:38 +00:00
constructor(options?: RecursivePartial<MembraneSynthOptions>)
constructor() {
super(optionsFromArguments(MembraneSynth.getDefaults(), arguments));
const options = optionsFromArguments(MembraneSynth.getDefaults(), arguments);
this.pitchDecay = options.pitchDecay;
this.octaves = options.octaves;
2019-08-16 17:57:38 +00:00
readOnly(this, ["oscillator", "envelope"]);
}
static getDefaults(): MembraneSynthOptions {
return deepMerge(Monophonic.getDefaults(), Synth.getDefaults(), {
2019-09-14 22:12:44 +00:00
envelope: {
attack: 0.001,
attackCurve: "exponential",
decay: 0.4,
release: 1.4,
sustain: 0.01,
2019-08-16 17:57:38 +00:00
},
octaves: 10,
oscillator: {
type: "sine",
},
pitchDecay: 0.05,
});
}
setNote(note: Frequency | FrequencyClass, time?: Time): this {
2019-08-16 17:57:38 +00:00
const seconds = this.toSeconds(time);
const hertz = this.toFrequency(note instanceof FrequencyClass ? note.toFrequency() : note);
2019-08-16 17:57:38 +00:00
const maxNote = hertz * this.octaves;
this.oscillator.frequency.setValueAtTime(maxNote, seconds);
this.oscillator.frequency.exponentialRampToValueAtTime(hertz, seconds + this.toSeconds(this.pitchDecay));
return this;
}
dispose(): this {
super.dispose();
return this;
}
}