UNPKG

octave-bands

Version:

Frequency limits for fractional Octave Bands

99 lines (98 loc) 3.59 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.equalizer = exports.bandwidth = exports.octaves = void 0; const DEFAULT_OPTIONS = { spectrum: [15, 21000], center: 1000 }; /** * Calculates and returns the frequency limits for octave bands. * @param fraction (default `1`) octave bands fraction * @param options (optional) bands limit options * @returns an array of bands, where each band is a tuple of `[lower, center, higher]` frequencies */ const octaves = (fraction = 1, options) => { validateFraction(fraction); const { spectrum: [min, max], center, } = Object.assign(Object.assign({}, DEFAULT_OPTIONS), options); validateSpectrum([min, max]); validateCenter(center, [min, max]); const factor = Math.pow(2, fraction); const factor2 = Math.pow(Math.SQRT2, fraction); const bands = []; for (let c = center; c >= min; c /= factor) { bands.unshift([c / factor2, c, c * factor2]); } for (let c = center * factor; c <= max; c *= factor) { bands.push([c / factor2, c, c * factor2]); } return bands; }; exports.octaves = octaves; /** * Calculates the fractional bandwidth per given octave band: * `BW = (f_high - f_low) / f_center` * @param fraction (default `1`) octave band fraction */ const bandwidth = (fraction = 1) => { validateFraction(fraction); return (Math.pow(2, fraction) - 1) / Math.pow(2, fraction / 2); }; exports.bandwidth = bandwidth; /** * Calculates the frequency bounds for a given spectrum and number of bands * @param bands number of bands * @param spectrum the audio spectrum for bands' center frequencies (default `[15, 21000]`) * @returns an array of bands, where each band is a tuple of `[lower, center, higher]` frequencies */ const equalizer = (bands, options) => { validateBands(bands); const { spectrum } = Object.assign(Object.assign({}, DEFAULT_OPTIONS), options); validateSpectrum(spectrum); const fraction = Math.log2(spectrum[1] / spectrum[0]) / (bands - 1); const factor = Math.pow(2, fraction); const factor2 = Math.sqrt(factor); const result = [ [spectrum[0] / factor2, spectrum[0], spectrum[0] * factor2], ]; while (result[result.length - 1][2] < spectrum[1]) { const center = result[result.length - 1][1] * factor; result.push([center / factor2, center, center * factor2]); } return result; }; exports.equalizer = equalizer; const validateFraction = (fraction) => { if (typeof fraction !== 'number') { throw new Error('fraction not a number'); } if (fraction <= 0) { throw new Error('fraction should be positive'); } }; const validateBands = (bands) => { if (bands <= 0) { throw new Error('bands should be positive'); } if (Math.floor(bands) !== bands) { throw new Error('bands should be integer'); } }; const validateSpectrum = (spectrum) => { if (typeof spectrum[0] !== 'number') { throw new Error('spectrum min not a number'); } if (typeof spectrum[1] !== 'number') { throw new Error('spectrum max not a number'); } if (spectrum[0] <= 0) { throw new Error('spectrum min should be positive'); } if (spectrum[0] >= spectrum[1]) { throw new Error('spectrum range invalid'); } }; const validateCenter = (value, spectrum) => { if (typeof value !== 'number') { throw new Error('center not a number'); } if (value < spectrum[0] || value > spectrum[1]) { throw new Error('center out of spectrum range'); } };