UNPKG

meyda

Version:

Real-time feature extraction for the web audio api

114 lines (97 loc) 3.98 kB
'use strict'; function extractPowerSpectrum (_a) { var ampSpectrum = _a.ampSpectrum; if (typeof ampSpectrum !== "object") { throw new TypeError(); } var powerSpectrum = new Float32Array(ampSpectrum.length); for (var i = 0; i < powerSpectrum.length; i++) { powerSpectrum[i] = Math.pow(ampSpectrum[i], 2); } return powerSpectrum; } function extractMelBands (_a) { var ampSpectrum = _a.ampSpectrum, melFilterBank = _a.melFilterBank, bufferSize = _a.bufferSize; if (typeof ampSpectrum !== "object") { throw new TypeError("Valid ampSpectrum is required to generate melBands"); } if (typeof melFilterBank !== "object") { throw new TypeError("Valid melFilterBank is required to generate melBands"); } var powSpec = extractPowerSpectrum({ ampSpectrum: ampSpectrum }); var numFilters = melFilterBank.length; var filtered = Array(numFilters); var loggedMelBands = new Float32Array(numFilters); for (var i = 0; i < loggedMelBands.length; i++) { filtered[i] = new Float32Array(bufferSize / 2); loggedMelBands[i] = 0; for (var j = 0; j < bufferSize / 2; j++) { //point-wise multiplication between power spectrum and filterbanks. filtered[i][j] = melFilterBank[i][j] * powSpec[j]; //summing up all of the coefficients into one array loggedMelBands[i] += filtered[i][j]; } //log each coefficient. loggedMelBands[i] = Math.log(loggedMelBands[i] + 1); } return Array.prototype.slice.call(loggedMelBands); } function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } /*===========================================================================*\ * Discrete Cosine Transform * * (c) Vail Systems. Joshua Jung and Ben Bryan. 2015 * * This code is not designed to be highly optimized but as an educational * tool to understand the Mel-scale and its related coefficients used in * human speech analysis. \*===========================================================================*/ var cosMap = null; // Builds a cosine map for the given input size. This allows multiple input sizes to be memoized automagically // if you want to run the DCT over and over. var memoizeCosines = function(N) { cosMap = cosMap || {}; cosMap[N] = new Array(N*N); var PI_N = Math.PI / N; for (var k = 0; k < N; k++) { for (var n = 0; n < N; n++) { cosMap[N][n + (k * N)] = Math.cos(PI_N * (n + 0.5) * k); } } }; function dct$2(signal, scale) { var L = signal.length; scale = scale || 2; if (!cosMap || !cosMap[L]) memoizeCosines(L); var coefficients = signal.map(function () {return 0;}); return coefficients.map(function (__, ix) { return scale * signal.reduce(function (prev, cur, ix_, arr) { return prev + (cur * cosMap[L][ix_ + (ix * L)]); }, 0); }); } var dct_1 = dct$2; var dct = dct_1; var dct$1 = /*@__PURE__*/getDefaultExportFromCjs(dct); function mfcc (_a) { // Tutorial from: // http://practicalcryptography.com/miscellaneous/machine-learning // /guide-mel-frequency-cepstral-coefficients-mfccs/ // @ts-ignore var ampSpectrum = _a.ampSpectrum, melFilterBank = _a.melFilterBank, numberOfMFCCCoefficients = _a.numberOfMFCCCoefficients, bufferSize = _a.bufferSize; var _numberOfMFCCCoefficients = Math.min(40, Math.max(1, numberOfMFCCCoefficients || 13)); var numFilters = melFilterBank.length; if (numFilters < _numberOfMFCCCoefficients) { throw new Error("Insufficient filter bank for requested number of coefficients"); } var loggedMelBandsArray = extractMelBands({ ampSpectrum: ampSpectrum, melFilterBank: melFilterBank, bufferSize: bufferSize, }); var mfccs = dct$1(loggedMelBandsArray).slice(0, _numberOfMFCCCoefficients); return mfccs; } module.exports = mfcc;