mirror of
https://github.com/Tonejs/Tone.js
synced 2024-12-27 12:03:12 +00:00
parent
0399687863
commit
364040cefe
1 changed files with 48 additions and 21 deletions
|
@ -1,9 +1,22 @@
|
||||||
import { Envelope, EnvelopeOptions } from "../component/envelope/Envelope";
|
import { Envelope, EnvelopeOptions } from "../component/envelope/Envelope";
|
||||||
import { Filter } from "../component/filter/Filter";
|
import { Filter } from "../component/filter/Filter";
|
||||||
import { Gain } from "../core/context/Gain";
|
import { Gain } from "../core/context/Gain";
|
||||||
import { ToneAudioNode, ToneAudioNodeOptions } from "../core/context/ToneAudioNode";
|
import {
|
||||||
import { Frequency, NormalRange, Positive, Seconds, Time } from "../core/type/Units";
|
ToneAudioNode,
|
||||||
import { deepMerge, omitFromObject, optionsFromArguments } from "../core/util/Defaults";
|
ToneAudioNodeOptions,
|
||||||
|
} from "../core/context/ToneAudioNode";
|
||||||
|
import {
|
||||||
|
Frequency,
|
||||||
|
NormalRange,
|
||||||
|
Positive,
|
||||||
|
Seconds,
|
||||||
|
Time,
|
||||||
|
} from "../core/type/Units";
|
||||||
|
import {
|
||||||
|
deepMerge,
|
||||||
|
omitFromObject,
|
||||||
|
optionsFromArguments,
|
||||||
|
} from "../core/util/Defaults";
|
||||||
import { noOp, RecursivePartial } from "../core/util/Interface";
|
import { noOp, RecursivePartial } from "../core/util/Interface";
|
||||||
import { Multiply } from "../signal/Multiply";
|
import { Multiply } from "../signal/Multiply";
|
||||||
import { Scale } from "../signal/Scale";
|
import { Scale } from "../signal/Scale";
|
||||||
|
@ -23,17 +36,15 @@ export interface MetalSynthOptions extends MonophonicOptions {
|
||||||
* Inharmonic ratio of frequencies based on the Roland TR-808
|
* Inharmonic ratio of frequencies based on the Roland TR-808
|
||||||
* Taken from https://ccrma.stanford.edu/papers/tr-808-cymbal-physically-informed-circuit-bendable-digital-model
|
* Taken from https://ccrma.stanford.edu/papers/tr-808-cymbal-physically-informed-circuit-bendable-digital-model
|
||||||
*/
|
*/
|
||||||
const inharmRatios: number[] = [1.0, 1.483, 1.932, 2.546, 2.630, 3.897];
|
const inharmRatios: number[] = [1.0, 1.483, 1.932, 2.546, 2.63, 3.897];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A highly inharmonic and spectrally complex source with a highpass filter
|
* A highly inharmonic and spectrally complex source with a highpass filter
|
||||||
* and amplitude envelope which is good for making metallophone sounds.
|
* and amplitude envelope which is good for making metallophone sounds.
|
||||||
* Based on CymbalSynth by [@polyrhythmatic](https://github.com/polyrhythmatic).
|
* Based on CymbalSynth by [@polyrhythmatic](https://github.com/polyrhythmatic).
|
||||||
* Inspiration from [Sound on Sound](https://shorturl.at/rSZ12).
|
|
||||||
* @category Instrument
|
* @category Instrument
|
||||||
*/
|
*/
|
||||||
export class MetalSynth extends Monophonic<MetalSynthOptions> {
|
export class MetalSynth extends Monophonic<MetalSynthOptions> {
|
||||||
|
|
||||||
readonly name: string = "MetalSynth";
|
readonly name: string = "MetalSynth";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,10 +95,13 @@ export class MetalSynth extends Monophonic<MetalSynthOptions> {
|
||||||
*/
|
*/
|
||||||
readonly envelope: Envelope;
|
readonly envelope: Envelope;
|
||||||
|
|
||||||
constructor(options?: RecursivePartial<MetalSynthOptions>)
|
constructor(options?: RecursivePartial<MetalSynthOptions>);
|
||||||
constructor() {
|
constructor() {
|
||||||
super(optionsFromArguments(MetalSynth.getDefaults(), arguments));
|
super(optionsFromArguments(MetalSynth.getDefaults(), arguments));
|
||||||
const options = optionsFromArguments(MetalSynth.getDefaults(), arguments);
|
const options = optionsFromArguments(
|
||||||
|
MetalSynth.getDefaults(),
|
||||||
|
arguments
|
||||||
|
);
|
||||||
|
|
||||||
this.detune = new Signal({
|
this.detune = new Signal({
|
||||||
context: this.context,
|
context: this.context,
|
||||||
|
@ -158,12 +172,15 @@ export class MetalSynth extends Monophonic<MetalSynthOptions> {
|
||||||
static getDefaults(): MetalSynthOptions {
|
static getDefaults(): MetalSynthOptions {
|
||||||
return deepMerge(Monophonic.getDefaults(), {
|
return deepMerge(Monophonic.getDefaults(), {
|
||||||
envelope: Object.assign(
|
envelope: Object.assign(
|
||||||
omitFromObject(Envelope.getDefaults(), Object.keys(ToneAudioNode.getDefaults())),
|
omitFromObject(
|
||||||
|
Envelope.getDefaults(),
|
||||||
|
Object.keys(ToneAudioNode.getDefaults())
|
||||||
|
),
|
||||||
{
|
{
|
||||||
attack: 0.001,
|
attack: 0.001,
|
||||||
decay: 1.4,
|
decay: 1.4,
|
||||||
release: 0.2,
|
release: 0.2,
|
||||||
},
|
}
|
||||||
),
|
),
|
||||||
harmonicity: 5.1,
|
harmonicity: 5.1,
|
||||||
modulationIndex: 32,
|
modulationIndex: 32,
|
||||||
|
@ -177,12 +194,19 @@ export class MetalSynth extends Monophonic<MetalSynthOptions> {
|
||||||
* @param time When the attack should be triggered.
|
* @param time When the attack should be triggered.
|
||||||
* @param velocity The velocity that the envelope should be triggered at.
|
* @param velocity The velocity that the envelope should be triggered at.
|
||||||
*/
|
*/
|
||||||
protected _triggerEnvelopeAttack(time: Seconds, velocity: NormalRange = 1): this {
|
protected _triggerEnvelopeAttack(
|
||||||
|
time: Seconds,
|
||||||
|
velocity: NormalRange = 1
|
||||||
|
): this {
|
||||||
this.envelope.triggerAttack(time, velocity);
|
this.envelope.triggerAttack(time, velocity);
|
||||||
this._oscillators.forEach(osc => osc.start(time));
|
this._oscillators.forEach((osc) => osc.start(time));
|
||||||
if (this.envelope.sustain === 0) {
|
if (this.envelope.sustain === 0) {
|
||||||
this._oscillators.forEach(osc => {
|
this._oscillators.forEach((osc) => {
|
||||||
osc.stop(time + this.toSeconds(this.envelope.attack) + this.toSeconds(this.envelope.decay));
|
osc.stop(
|
||||||
|
time +
|
||||||
|
this.toSeconds(this.envelope.attack) +
|
||||||
|
this.toSeconds(this.envelope.decay)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
@ -194,7 +218,9 @@ export class MetalSynth extends Monophonic<MetalSynthOptions> {
|
||||||
*/
|
*/
|
||||||
protected _triggerEnvelopeRelease(time: Seconds): this {
|
protected _triggerEnvelopeRelease(time: Seconds): this {
|
||||||
this.envelope.triggerRelease(time);
|
this.envelope.triggerRelease(time);
|
||||||
this._oscillators.forEach(osc => osc.stop(time + this.toSeconds(this.envelope.release)));
|
this._oscillators.forEach((osc) =>
|
||||||
|
osc.stop(time + this.toSeconds(this.envelope.release))
|
||||||
|
);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +239,7 @@ export class MetalSynth extends Monophonic<MetalSynthOptions> {
|
||||||
return this._oscillators[0].modulationIndex.value;
|
return this._oscillators[0].modulationIndex.value;
|
||||||
}
|
}
|
||||||
set modulationIndex(val) {
|
set modulationIndex(val) {
|
||||||
this._oscillators.forEach(osc => (osc.modulationIndex.value = val));
|
this._oscillators.forEach((osc) => (osc.modulationIndex.value = val));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -226,7 +252,7 @@ export class MetalSynth extends Monophonic<MetalSynthOptions> {
|
||||||
return this._oscillators[0].harmonicity.value;
|
return this._oscillators[0].harmonicity.value;
|
||||||
}
|
}
|
||||||
set harmonicity(val) {
|
set harmonicity(val) {
|
||||||
this._oscillators.forEach(osc => (osc.harmonicity.value = val));
|
this._oscillators.forEach((osc) => (osc.harmonicity.value = val));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,13 +280,14 @@ export class MetalSynth extends Monophonic<MetalSynthOptions> {
|
||||||
}
|
}
|
||||||
set octaves(val) {
|
set octaves(val) {
|
||||||
this._octaves = val;
|
this._octaves = val;
|
||||||
this._filterFreqScaler.max = this._filterFreqScaler.min * Math.pow(2, val);
|
this._filterFreqScaler.max =
|
||||||
|
this._filterFreqScaler.min * Math.pow(2, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): this {
|
dispose(): this {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
this._oscillators.forEach(osc => osc.dispose());
|
this._oscillators.forEach((osc) => osc.dispose());
|
||||||
this._freqMultipliers.forEach(freqMult => freqMult.dispose());
|
this._freqMultipliers.forEach((freqMult) => freqMult.dispose());
|
||||||
this.frequency.dispose();
|
this.frequency.dispose();
|
||||||
this.detune.dispose();
|
this.detune.dispose();
|
||||||
this._filterFreqScaler.dispose();
|
this._filterFreqScaler.dispose();
|
||||||
|
|
Loading…
Reference in a new issue