Tone.js/Tone/component/dynamics/Compressor.ts

165 lines
4.4 KiB
TypeScript
Raw Normal View History

2019-08-15 23:18:09 +00:00
import { Param } from "../../core/context/Param";
import { ToneAudioNode, ToneAudioNodeOptions } from "../../core/context/ToneAudioNode";
import { Decibels, Positive, Time } from "../../core/type/Units";
import { optionsFromArguments } from "../../core/util/Defaults";
import { readOnly } from "../../core/util/Interface";
2019-11-14 17:12:52 +00:00
export interface CompressorOptions extends ToneAudioNodeOptions {
2019-08-15 23:18:09 +00:00
attack: Time;
knee: Decibels;
ratio: Positive;
release: Time;
threshold: Decibels;
}
/**
* Compressor is a thin wrapper around the Web Audio
* [DynamicsCompressorNode](http://webaudio.github.io/web-audio-api/#the-dynamicscompressornode-interface).
* Compression reduces the volume of loud sounds or amplifies quiet sounds
* by narrowing or "compressing" an audio signal's dynamic range.
* Read more on [Wikipedia](https://en.wikipedia.org/wiki/Dynamic_range_compression).
* @example
2019-10-23 20:30:07 +00:00
* import { Compressor } from "tone";
* const comp = new Compressor(-30, 3);
2019-09-16 14:15:23 +00:00
* @category Component
2019-08-15 23:18:09 +00:00
*/
export class Compressor extends ToneAudioNode<CompressorOptions> {
2019-09-04 23:18:44 +00:00
readonly name: string = "Compressor";
2019-08-15 23:18:09 +00:00
/**
2019-09-14 20:39:18 +00:00
* the compressor node
2019-08-15 23:18:09 +00:00
*/
private _compressor: DynamicsCompressorNode = this.context.createDynamicsCompressor();
2019-09-11 02:42:04 +00:00
readonly input = this._compressor;
readonly output = this._compressor;
2019-08-15 23:18:09 +00:00
/**
2019-09-14 20:39:18 +00:00
* The decibel value above which the compression will start taking effect.
2019-10-11 22:58:56 +00:00
* @min -100
* @max 0
2019-08-15 23:18:09 +00:00
*/
readonly threshold: Param<"decibels">;
2019-08-15 23:18:09 +00:00
/**
2019-09-14 20:39:18 +00:00
* The amount of time (in seconds) to reduce the gain by 10dB.
* @min 0
* @max 1
2019-08-15 23:18:09 +00:00
*/
readonly attack: Param<"time">;
2019-08-15 23:18:09 +00:00
/**
* The amount of time (in seconds) to increase the gain by 10dB.
* @min 0
* @max 1
2019-08-15 23:18:09 +00:00
*/
readonly release: Param<"time">;
2019-08-15 23:18:09 +00:00
/**
* A decibel value representing the range above the threshold where the
* curve smoothly transitions to the "ratio" portion.
* @min 0
* @max 40
2019-08-15 23:18:09 +00:00
*/
readonly knee: Param<"decibels">;
2019-08-15 23:18:09 +00:00
/**
* The amount of dB change in input for a 1 dB change in output.
* @min 1
* @max 20
2019-08-15 23:18:09 +00:00
*/
readonly ratio: Param<"positive">;
2019-08-15 23:18:09 +00:00
2019-08-27 17:02:31 +00:00
/**
* @param threshold The value above which the compression starts to be applied.
* @param ratio The gain reduction ratio.
*/
2019-08-15 23:18:09 +00:00
constructor(threshold?: Decibels, ratio?: Positive);
constructor(options?: Partial<CompressorOptions>);
constructor() {
2019-09-11 02:42:04 +00:00
super(optionsFromArguments(Compressor.getDefaults(), arguments, ["threshold", "ratio"]));
const options = optionsFromArguments(Compressor.getDefaults(), arguments, ["threshold", "ratio"]);
2019-08-15 23:18:09 +00:00
this.threshold = new Param({
minValue: this._compressor.threshold.minValue,
maxValue: this._compressor.threshold.maxValue,
2019-08-15 23:18:09 +00:00
context: this.context,
2019-09-16 03:32:40 +00:00
convert: false,
param: this._compressor.threshold,
units: "decibels",
2019-08-15 23:18:09 +00:00
value: options.threshold,
});
2019-08-15 23:18:09 +00:00
this.attack = new Param({
minValue: this._compressor.attack.minValue,
maxValue: this._compressor.attack.maxValue,
2019-08-15 23:18:09 +00:00
context: this.context,
param: this._compressor.attack,
units: "time",
value: options.attack,
});
2019-08-15 23:18:09 +00:00
this.release = new Param({
minValue: this._compressor.release.minValue,
maxValue: this._compressor.release.maxValue,
2019-08-15 23:18:09 +00:00
context: this.context,
param: this._compressor.release,
units: "time",
value: options.release,
});
2019-08-15 23:18:09 +00:00
this.knee = new Param({
minValue: this._compressor.knee.minValue,
maxValue: this._compressor.knee.maxValue,
2019-08-15 23:18:09 +00:00
context: this.context,
2019-09-16 03:32:40 +00:00
convert: false,
param: this._compressor.knee,
units: "decibels",
2019-08-15 23:18:09 +00:00
value: options.knee,
});
2019-08-15 23:18:09 +00:00
this.ratio = new Param({
minValue: this._compressor.ratio.minValue,
maxValue: this._compressor.ratio.maxValue,
2019-08-15 23:18:09 +00:00
context: this.context,
2019-09-16 03:32:40 +00:00
convert: false,
param: this._compressor.ratio,
units: "positive",
2019-08-15 23:18:09 +00:00
value: options.ratio,
});
// set the defaults
readOnly(this, ["knee", "release", "attack", "ratio", "threshold"]);
}
static getDefaults(): CompressorOptions {
return Object.assign(ToneAudioNode.getDefaults(), {
2019-09-16 03:32:40 +00:00
attack: 0.003,
knee: 30,
ratio: 12,
release: 0.25,
threshold: -24,
2019-08-15 23:18:09 +00:00
});
}
/**
* A read-only decibel value for metering purposes, representing the current amount of gain
* reduction that the compressor is applying to the signal. If fed no signal the value will be 0 (no gain reduction).
*/
2019-11-14 16:23:07 +00:00
get reduction(): Decibels {
2019-08-15 23:18:09 +00:00
return this._compressor.reduction;
}
dispose(): this {
super.dispose();
this._compressor.disconnect();
this.attack.dispose();
this.release.dispose();
this.threshold.dispose();
this.ratio.dispose();
this.knee.dispose();
return this;
}
}