UNPKG

@sebastbake/music-tempo

Version:

Finding out tempo of the music

79 lines (76 loc) 2.21 kB
/** * Get Hamming window * @param {Number} bufferSize - windows size * @return {Array} wnd - Hamming window */ export function getHammingWindow(bufferSize: number) { const a = 25 / 46; const b = 21 / 46; const scale = 1 / bufferSize / 0.54; const sqrtBufferSize = Math.sqrt(bufferSize); const factor = (Math.PI * 2) / bufferSize; let wnd: number[] = []; for (let i = 0; i < bufferSize; i++) { wnd[i] = sqrtBufferSize * (scale * (a - b * Math.cos(factor * i))); } return wnd; } /** * Computes FFT and converts the results to magnitude representation * @param {Array} re - the real part of the input data and the magnitude of the output data * @param {Array} im - the imaginary part of the input data */ export function getSpectrum(re: number[], im: number[]) { const direction = -1; const n = re.length; const bits = Math.round(Math.log(n) / Math.log(2)); const twoPI = Math.PI * 2; if (n != 1 << bits) throw new Error("FFT data must be power of 2"); let localN; let j = 0; for (let i = 0; i < n - 1; i++) { if (i < j) { let temp = re[j]; re[j] = re[i]; re[i] = temp; temp = im[j]; im[j] = im[i]; im[i] = temp; } let k = n / 2; while (k >= 1 && k - 1 < j) { j = j - k; k = k / 2; } j = j + k; } for (let m = 1; m <= bits; m++) { localN = 1 << m; let Wjk_r = 1; let Wjk_i = 0; let theta = twoPI / localN; let Wj_r = Math.cos(theta); let Wj_i = direction * Math.sin(theta); let nby2 = localN / 2; for (j = 0; j < nby2; j++) { for (let k = j; k < n; k += localN) { let id = k + nby2; let tempr = Wjk_r * re[id] - Wjk_i * im[id]; let tempi = Wjk_r * im[id] + Wjk_i * re[id]; re[id] = re[k] - tempr; im[id] = im[k] - tempi; re[k] += tempr; im[k] += tempi; } let wtemp = Wjk_r; Wjk_r = Wj_r * Wjk_r - Wj_i * Wjk_i; Wjk_i = Wj_r * Wjk_i + Wj_i * wtemp; } } for (let i = 0; i < re.length; i++) { let pow = re[i] * re[i] + im[i] * im[i]; //im[i] = Math.atan2(im[i], re[i]); re[i] = pow; } for (let i = 0; i < re.length; i++) re[i] = Math.sqrt(re[i]); }