pitchy
Version:
A simple pitch detection library.
222 lines (221 loc) • 8.98 kB
TypeScript
/**
* @typedef {Float32Array | Float64Array | number[]} Buffer One of the supported
* buffer types. Other numeric array types may not work correctly.
*/
/**
* A class that can perform autocorrelation on input arrays of a given size.
*
* The class holds internal buffers so that no additional allocations are
* necessary while performing the operation.
*
* @template {Buffer} T the buffer type to use. While inputs to the
* autocorrelation process can be any array-like type, the output buffer
* (whether provided explicitly or using a fresh buffer) is always of this type.
*/
export class Autocorrelator<T extends Buffer> {
/**
* A helper method to create an {@link Autocorrelator} using
* {@link Float32Array} buffers.
*
* @param inputLength {number} the input array length to support
* @returns {Autocorrelator<Float32Array>}
*/
static forFloat32Array(inputLength: number): Autocorrelator<Float32Array>;
/**
* A helper method to create an {@link Autocorrelator} using
* {@link Float64Array} buffers.
*
* @param inputLength {number} the input array length to support
* @returns {Autocorrelator<Float64Array>}
*/
static forFloat64Array(inputLength: number): Autocorrelator<Float64Array>;
/**
* A helper method to create an {@link Autocorrelator} using `number[]`
* buffers.
*
* @param inputLength {number} the input array length to support
* @returns {Autocorrelator<number[]>}
*/
static forNumberArray(inputLength: number): Autocorrelator<number[]>;
/**
* Constructs a new {@link Autocorrelator} able to handle input arrays of the
* given length.
*
* @param inputLength {number} the input array length to support. This
* `Autocorrelator` will only support operation on arrays of this length.
* @param bufferSupplier {(length: number) => T} the function to use for
* creating buffers, accepting the length of the buffer to create and
* returning a new buffer of that length. The values of the returned buffer
* need not be initialized in any particular way.
*/
constructor(inputLength: number, bufferSupplier: (length: number) => T);
/** @private @readonly @type {number} */
private readonly _inputLength;
/** @private @type {FFT} */
private _fft;
/** @private @type {(size: number) => T} */
private _bufferSupplier;
/** @private @type {T} */
private _paddedInputBuffer;
/** @private @type {T} */
private _transformBuffer;
/** @private @type {T} */
private _inverseBuffer;
/**
* Returns the supported input length.
*
* @returns {number} the supported input length
*/
get inputLength(): number;
/**
* Autocorrelates the given input data.
*
* @param input {ArrayLike<number>} the input data to autocorrelate
* @param output {T} the output buffer into which to write the autocorrelated
* data. If not provided, a new buffer will be created.
* @returns {T} `output`
*/
autocorrelate(input: ArrayLike<number>, output?: T): T;
}
/**
* A class that can detect the pitch of a note from a time-domain input array.
*
* This class uses the McLeod pitch method (MPM) to detect pitches. MPM is
* described in the paper 'A Smarter Way to Find Pitch' by Philip McLeod and
* Geoff Wyvill
* (http://miracle.otago.ac.nz/tartini/papers/A_Smarter_Way_to_Find_Pitch.pdf).
*
* The class holds internal buffers so that a minimal number of additional
* allocations are necessary while performing the operation.
*
* @template {Buffer} T the buffer type to use internally. Inputs to the
* pitch-detection process can be any numeric array type.
*/
export class PitchDetector<T extends Buffer> {
/**
* A helper method to create an {@link PitchDetector} using {@link Float32Array} buffers.
*
* @param inputLength {number} the input array length to support
* @returns {PitchDetector<Float32Array>}
*/
static forFloat32Array(inputLength: number): PitchDetector<Float32Array>;
/**
* A helper method to create an {@link PitchDetector} using {@link Float64Array} buffers.
*
* @param inputLength {number} the input array length to support
* @returns {PitchDetector<Float64Array>}
*/
static forFloat64Array(inputLength: number): PitchDetector<Float64Array>;
/**
* A helper method to create an {@link PitchDetector} using `number[]` buffers.
*
* @param inputLength {number} the input array length to support
* @returns {PitchDetector<number[]>}
*/
static forNumberArray(inputLength: number): PitchDetector<number[]>;
/**
* Constructs a new {@link PitchDetector} able to handle input arrays of the
* given length.
*
* @param inputLength {number} the input array length to support. This
* `PitchDetector` will only support operation on arrays of this length.
* @param bufferSupplier {(inputLength: number) => T} the function to use for
* creating buffers, accepting the length of the buffer to create and
* returning a new buffer of that length. The values of the returned buffer
* need not be initialized in any particular way.
*/
constructor(inputLength: number, bufferSupplier: (inputLength: number) => T);
/** @private @type {Autocorrelator<T>} */
private _autocorrelator;
/** @private @type {T} */
private _nsdfBuffer;
/** @private @type {number} */
private _clarityThreshold;
/** @private @type {number} */
private _minVolumeAbsolute;
/** @private @type {number} */
private _maxInputAmplitude;
/**
* Returns the supported input length.
*
* @returns {number} the supported input length
*/
get inputLength(): number;
/**
* Sets the clarity threshold used when identifying the correct pitch (the constant
* `k` from the MPM paper). The value must be between 0 (exclusive) and 1
* (inclusive), with the most suitable range being between 0.8 and 1.
*
* @param threshold {number} the clarity threshold
*/
set clarityThreshold(threshold: number);
/**
* Sets the minimum detectable volume, as an absolute number between 0 and
* `maxInputAmplitude`, inclusive, to consider in a sample when detecting the
* pitch. If a sample fails to meet this minimum volume, `findPitch` will
* return a clarity of 0.
*
* Volume is calculated as the RMS (root mean square) of the input samples.
*
* @param volume {number} the minimum volume as an absolute amplitude value
*/
set minVolumeAbsolute(volume: number);
/**
* Sets the minimum volume using a decibel measurement. Must be less than or
* equal to 0: 0 indicates the loudest possible sound (see
* `maxInputAmplitude`), -10 is a sound with a tenth of the volume of the
* loudest possible sound, etc.
*
* Volume is calculated as the RMS (root mean square) of the input samples.
*
* @param db {number} the minimum volume in decibels, with 0 being the loudest
* sound
*/
set minVolumeDecibels(db: number);
/**
* Sets the maximum amplitude of an input reading. Must be greater than 0.
*
* @param amplitude {number} the maximum amplitude (absolute value) of an input reading
*/
set maxInputAmplitude(amplitude: number);
/**
* Returns the pitch detected using McLeod Pitch Method (MPM) along with a
* measure of its clarity.
*
* The clarity is a value between 0 and 1 (potentially inclusive) that
* represents how "clear" the pitch was. A clarity value of 1 indicates that
* the pitch was very distinct, while lower clarity values indicate less
* definite pitches.
*
* @param input {ArrayLike<number>} the time-domain input data
* @param sampleRate {number} the sample rate at which the input data was
* collected
* @returns {[number, number]} the detected pitch, in Hz, followed by the
* clarity. If a pitch cannot be determined from the input, such as if the
* volume is too low (see `minVolumeAbsolute` and `minVolumeDecibels`), this
* will be `[0, 0]`.
*/
findPitch(input: ArrayLike<number>, sampleRate: number): [number, number];
/**
* Returns whether the input audio data is below the minimum volume allowed by
* the pitch detector.
*
* @private
* @param input {ArrayLike<number>}
* @returns {boolean}
*/
private _belowMinimumVolume;
/**
* Computes the NSDF of the input and stores it in the internal buffer. This
* is equation (9) in the McLeod pitch method paper.
*
* @private
* @param input {ArrayLike<number>}
*/
private _nsdf;
}
/**
* One of the supported
* buffer types. Other numeric array types may not work correctly.
*/
export type Buffer = Float32Array | Float64Array | number[];