"use strict";
/**
* @license
* Copyright (C) 2006-2020 Music Technology Group - Universitat Pompeu Fabra
*
* This file is part of Essentia
*
* Essentia is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation (FSF), either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the Affero GNU General Public License
* version 3 along with this program. If not, see http://www.gnu.org/licenses/
*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
exports.__esModule = true;
var core_api_1 = require("../core_api");
/**
* EssentiaExtractor
* This class provides one-liner methods which implements the whole chain of algorithms
* required for computing features such as log-scaled mel spectrogram, HPCP chroma features etc.
* This can be extended according to your needs.
* @class
* @extends {Essentia}
*/
var EssentiaExtractor = /** @class */ (function (_super) {
__extends(EssentiaExtractor, _super);
/**
*Creates an instance of EssentiaExtractor.
* @param {*} EssentiaWASM
* @param {boolean} [isDebug=false]
* @constructs
*/
function EssentiaExtractor(EssentiaWASM, isDebug) {
if (isDebug === void 0) { isDebug = false; }
var _this = _super.call(this, EssentiaWASM, isDebug) || this;
_this.EssentiaWASM = EssentiaWASM;
_this.isDebug = isDebug;
_this.sampleRate = 44100;
_this.frameSize = 2048;
_this.profile = {
Windowing: {
normalized: false,
size: 1024,
type: "hann",
zeroPadding: 0,
zeroPhase: true
},
Spectrum: {
size: _this.frameSize
},
MelBands: {
highFrequencyBound: Math.floor(_this.sampleRate / 2),
inputSize: Math.floor(_this.frameSize / (2 + 1)),
log: false,
lowFrequencyBound: 0,
normalize: 'unit_tri',
numberBands: 96,
sampleRate: _this.sampleRate,
type: 'power',
warpingFormula: 'slaneyMel',
weighting: 'linear'
},
SpectralPeaks: {
magnitudeThreshold: 0,
maxFrequency: 4500,
maxPeaks: 100,
minFrequency: 80,
orderBy: 'frequency',
sampleRate: _this.sampleRate
},
SpectralWhitening: {
maxFrequency: 4500,
sampleRate: _this.sampleRate
},
HPCP: {
bandPreset: true,
bandSplitFrequency: 500,
harmonics: 0,
maxFrequency: 4500,
maxShifted: false,
minFrequency: 80,
nonLinear: false,
normalized: 'unitMax',
referenceFrequency: 440,
sampleRate: _this.sampleRate,
size: 12,
weightType: 'squaredCosine',
windowSize: 1
}
};
return _this;
}
/**
* Compute log-scaled mel spectrogram for a given audio signal frame along with an optional extractor profile configuration
* @method
* @param {Float32Array} audioFrame a frame of decoded audio signal as Float32 typed array.
* @param {number} sampleRate Sample rate of the input audio signal.
* @param {boolean} [asVector=false] whether to output the spectrogram as a vector float type for chaining with other essentia algorithms.
* @param {*} [config=this.profile]
* @returns {Array} Log-scaled Mel Spectrum
* @memberof EssentiaExtractor
*/
EssentiaExtractor.prototype.melSpectrumExtractor = function (audioFrame, sampleRate, asVector, config) {
if (sampleRate === void 0) { sampleRate = this.sampleRate; }
if (asVector === void 0) { asVector = false; }
if (config === void 0) { config = this.profile; }
var signalFrame = this.arrayToVector(audioFrame);
var _frameSize = audioFrame.length;
// we need to compute the following signal process chain
// audio frame => windowing => spectrum => mel bands => log scale
var windowOut = this.Windowing(signalFrame, config.Windowing.normalized, config.Windowing.size, config.Windowing.type, config.Windowing.zeroPadding, config.Windowing.zeroPhase);
var spectrumOut = this.Spectrum(windowOut.frame, _frameSize);
var melOut = this.MelBands(spectrumOut.spectrum, config.MelBands.highFrequencyBound, Math.floor(_frameSize / (2 + 1)), config.MelBands.log, config.MelBands.lowFrequencyBound, config.MelBands.normalize, config.MelBands.numberBands, sampleRate, config.MelBands.type, config.MelBands.warpingFormula, config.MelBands.weighting);
// shift operation of mel-spectrograms
var shift = this.UnaryOperator(melOut.bands, 10000, 1);
// logarithmic compression of mel-spectrograms
var logComp = this.UnaryOperator(shift.array, 1, 0, "log10");
// return the output of the feature extractor either as VectorFloat type or as JavaScript Float32 typed array
if (asVector) {
// fallback to free the std vectors
//delete windowOut.frame;
delete spectrumOut.spectrum;
delete melOut.bands;
delete shift.array;
return logComp.array;
}
else {
// convert type to JS array
var logMelBands = this.vectorToArray(logComp.array);
// fallback to free the std vectors
//delete windowOut.frame;
delete spectrumOut.spectrum;
delete melOut.bands;
delete shift.array;
delete logComp.array;
return logMelBands;
}
};
/**
* Compute HPCP chroma feature for a given audio signal frame along with an optional extractor profile configuration
* @method
* @param {Float32Array} audioFrame a decoded audio signal frame as Float32 typed array.
* @param {number} sampleRate Sample rate of the input audio signal.
* @param {boolean} [asVector=false] whether to output the hpcpgram as a vector float type for chaining with other essentia algorithms.
* @param {*} [config=this.profile]
* @returns {Array} Frame-wise HPCP
* @memberof EssentiaExtractor
*/
EssentiaExtractor.prototype.hpcpExtractor = function (audioFrame, sampleRate, asVector, config) {
if (sampleRate === void 0) { sampleRate = this.sampleRate; }
if (asVector === void 0) { asVector = false; }
if (config === void 0) { config = this.profile; }
var signalFrame = this.arrayToVector(audioFrame);
var _frameSize = audioFrame.length;
// we need to compute the following signal process chain
// audio frame => windowing => spectrum => spectral peak => spectral whitening => HPCP
var windowOut = this.Windowing(signalFrame, config.Windowing.normalized, config.Windowing.size, config.Windowing.type, config.Windowing.zeroPadding, config.Windowing.zeroPhase);
var spectrumOut = this.Spectrum(windowOut.frame, _frameSize);
var peaksOut = this.SpectralPeaks(spectrumOut.spectrum, config.SpectralPeaks.magnitudeThreshold, config.SpectralPeaks.maxFrequency, config.SpectralPeaks.maxPeaks, config.SpectralPeaks.minFrequency, config.SpectralPeaks.orderBy, sampleRate);
var whiteningOut = this.SpectralWhitening(spectrumOut.spectrum, peaksOut.frequencies, peaksOut.magnitudes, config.SpectralWhitening.maxFrequency, sampleRate);
var hpcpOut = this.HPCP(peaksOut.frequencies, whiteningOut.magnitudes, config.HPCP.bandPreset, config.HPCP.bandSplitFrequency, config.HPCP.harmonics, config.HPCP.maxFrequency, config.HPCP.maxShifted, config.HPCP.minFrequency, config.HPCP.nonLinear, config.HPCP.normalized, config.HPCP.referenceFrequency, sampleRate, config.HPCP.size, config.HPCP.weightType, config.HPCP.windowSize);
// return the output of the feature extractor either as VectorFloat type or as JavaScript Float32 typed array
if (asVector) {
// fallback to free the std vectors
delete windowOut.frame;
delete spectrumOut.spectrum;
delete peaksOut.frequencies;
delete peaksOut.magnitudes;
delete whiteningOut.magnitudes;
return hpcpOut.hpcp;
}
else {
// convert type to JS array
var hpcpFrame = this.vectorToArray(hpcpOut.hpcp);
delete windowOut.frame;
delete spectrumOut.spectrum;
delete peaksOut.frequencies;
delete peaksOut.magnitudes;
delete whiteningOut.magnitudes;
delete hpcpOut.hpcp;
return hpcpFrame;
}
};
return EssentiaExtractor;
}(core_api_1["default"]));
exports["default"] = EssentiaExtractor;