node-pitchfinder
Version:
A pitch-detection library for node (using C++ Addon)
86 lines (73 loc) • 2.56 kB
JavaScript
;
var DEFAULT_MIN_FREQUENCY = 82;
var DEFAULT_MAX_FREQUENCY = 1000;
var DEFAULT_RATIO = 5;
var DEFAULT_SENSITIVITY = 0.1;
var DEFAULT_SAMPLE_RATE = 44100;
module.exports = function () {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var sampleRate = config.sampleRate || DEFAULT_SAMPLE_RATE;
var minFrequency = config.minFrequency || DEFAULT_MIN_FREQUENCY;
var maxFrequency = config.maxFrequency || DEFAULT_MAX_FREQUENCY;
var sensitivity = config.sensitivity || DEFAULT_SENSITIVITY;
var ratio = config.ratio || DEFAULT_RATIO;
var amd = [];
var maxPeriod = Math.round(sampleRate / minFrequency + 0.5);
var minPeriod = Math.round(sampleRate / maxFrequency + 0.5);
return function AMDFDetector(float32AudioBuffer) {
'use strict';
var maxShift = float32AudioBuffer.length;
var t = 0;
var minval = Infinity;
var maxval = -Infinity;
var frames1 = void 0,
frames2 = void 0,
calcSub = void 0,
i = void 0,
j = void 0,
u = void 0,
aux1 = void 0,
aux2 = void 0;
// Find the average magnitude difference for each possible period offset.
for (i = 0; i < maxShift; i++) {
if (minPeriod <= i && i <= maxPeriod) {
for (aux1 = 0, aux2 = i, t = 0, frames1 = [], frames2 = []; aux1 < maxShift - i; t++, aux2++, aux1++) {
frames1[t] = float32AudioBuffer[aux1];
frames2[t] = float32AudioBuffer[aux2];
}
// Take the difference between these frames.
var frameLength = frames1.length;
calcSub = [];
for (u = 0; u < frameLength; u++) {
calcSub[u] = frames1[u] - frames2[u];
}
// Sum the differences.
var summation = 0;
for (u = 0; u < frameLength; u++) {
summation += Math.abs(calcSub[u]);
}
amd[i] = summation;
}
}
for (j = minPeriod; j < maxPeriod; j++) {
if (amd[j] < minval) minval = amd[j];
if (amd[j] > maxval) maxval = amd[j];
}
var cutoff = Math.round(sensitivity * (maxval - minval) + minval);
for (j = minPeriod; j <= maxPeriod && amd[j] > cutoff; j++) {}
var searchLength = minPeriod / 2;
minval = amd[j];
var minpos = j;
for (i = j - 1; i < j + searchLength && i <= maxPeriod; i++) {
if (amd[i] < minval) {
minval = amd[i];
minpos = i;
}
}
if (Math.round(amd[minpos] * ratio) < maxval) {
return sampleRate / minpos;
} else {
return null;
}
};
};