UNPKG

node-pitchfinder

Version:
86 lines (73 loc) 2.56 kB
'use strict'; 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; } }; };