Tone.js/Tone/component/analysis/FFT.ts

93 lines
2.8 KiB
TypeScript
Raw Normal View History

2019-10-31 19:43:16 +00:00
import { ToneAudioNode } from "../../core/context/ToneAudioNode";
import { dbToGain } from "../../core/type/Conversions";
import { Hertz, NormalRange, PowerOfTwo } from "../../core/type/Units";
2019-09-09 22:24:07 +00:00
import { optionsFromArguments } from "../../core/util/Defaults";
import { MeterBase, MeterBaseOptions } from "./MeterBase";
import { assert } from "../../core/util/Debug";
2019-09-09 22:24:07 +00:00
export interface FFTOptions extends MeterBaseOptions {
2019-09-09 22:24:07 +00:00
size: PowerOfTwo;
smoothing: NormalRange;
normalRange: boolean;
2019-09-09 22:24:07 +00:00
}
/**
* Get the current frequency data of the connected audio source using a fast Fourier transform.
2019-09-16 14:15:23 +00:00
* @category Component
2019-09-09 22:24:07 +00:00
*/
export class FFT extends MeterBase<FFTOptions> {
2019-09-09 22:24:07 +00:00
readonly name: string = "FFT";
/**
* If the output should be in decibels or normal range between 0-1. If `normalRange` is false,
* the output range will be the measured decibel value, otherwise the decibel value will be converted to
* the range of 0-1
*/
normalRange: boolean;
2019-09-09 22:24:07 +00:00
/**
* @param size The size of the FFT. Value must be a power of two in the range 16 to 16384.
2019-09-09 22:24:07 +00:00
*/
constructor(size?: PowerOfTwo);
constructor(options?: Partial<FFTOptions>);
constructor() {
super(optionsFromArguments(FFT.getDefaults(), arguments, ["size"]));
const options = optionsFromArguments(FFT.getDefaults(), arguments, ["size"]);
this.normalRange = options.normalRange;
this._analyser.type = "fft";
this.size = options.size;
2019-09-09 22:24:07 +00:00
}
static getDefaults(): FFTOptions {
return Object.assign(ToneAudioNode.getDefaults(), {
normalRange: false,
2019-09-09 22:24:07 +00:00
size: 1024,
smoothing: 0.8,
});
}
/**
2019-09-14 20:39:18 +00:00
* Gets the current frequency data from the connected audio source.
* Returns the frequency data of length [[size]] as a Float32Array of decibel values.
2019-09-09 22:24:07 +00:00
*/
getValue(): Float32Array {
const values = this._analyser.getValue() as Float32Array;
return values.map(v => this.normalRange ? dbToGain(v) : v);
2019-09-09 22:24:07 +00:00
}
/**
2019-09-14 20:39:18 +00:00
* The size of analysis. This must be a power of two in the range 16 to 16384.
* Determines the size of the array returned by [[getValue]] (i.e. the number of
* frequency bins). Large FFT sizes may be costly to compute.
2019-09-09 22:24:07 +00:00
*/
get size(): PowerOfTwo {
return this._analyser.size;
}
set size(size) {
this._analyser.size = size;
}
/**
2019-09-14 20:39:18 +00:00
* 0 represents no time averaging with the last analysis frame.
2019-09-09 22:24:07 +00:00
*/
get smoothing(): NormalRange {
return this._analyser.smoothing;
}
set smoothing(val) {
this._analyser.smoothing = val;
}
/**
* Returns the frequency value in hertz of each of the indices of the FFT's [[getValue]] response.
* @example
* const fft = new Tone.FFT(32);
2020-07-19 00:21:24 +00:00
* console.log([0, 1, 2, 3, 4].map(index => fft.getFrequencyOfIndex(index)));
*/
getFrequencyOfIndex(index: number): Hertz {
assert(0 <= index && index < this.size, `index must be greater than or equal to 0 and less than ${this.size}`);
return index * this.context.sampleRate / (this.size * 2);
}
2019-09-09 22:24:07 +00:00
}