/** * Calculate FFT - Based on https://github.com/corbanbrook/dsp.js */ /* eslint-disable complexity, no-redeclare, no-var, one-var */ const FFT = function(bufferSize, sampleRate, windowFunc, alpha) { this.bufferSize = bufferSize; this.sampleRate = sampleRate; this.bandwidth = 2 / bufferSize * sampleRate / 2; this.sinTable = new Float32Array(bufferSize); this.cosTable = new Float32Array(bufferSize); this.windowValues = new Float32Array(bufferSize); this.reverseTable = new Uint32Array(bufferSize); this.peakBand = 0; this.peak = 0; switch (windowFunc) { case 'bartlett' : for (var i = 0; i> 1; var i; while (limit < bufferSize) { for (i = 0; i < limit; i++) { this.reverseTable[i + limit] = this.reverseTable[i] + bit; } limit = limit << 1; bit = bit >> 1; } for (i = 0; i < bufferSize; i++) { this.sinTable[i] = Math.sin(-Math.PI/i); this.cosTable[i] = Math.cos(-Math.PI/i); } this.calculateSpectrum = function(buffer) { // Locally scope variables for speed up var bufferSize = this.bufferSize, cosTable = this.cosTable, sinTable = this.sinTable, reverseTable = this.reverseTable, real = new Float32Array(bufferSize), imag = new Float32Array(bufferSize), bSi = 2 / this.bufferSize, sqrt = Math.sqrt, rval, ival, mag, spectrum = new Float32Array(bufferSize / 2); var k = Math.floor(Math.log(bufferSize) / Math.LN2); if (Math.pow(2, k) !== bufferSize) { throw 'Invalid buffer size, must be a power of 2.'; } if (bufferSize !== buffer.length) { throw 'Supplied buffer is not the same size as defined FFT. FFT Size: ' + bufferSize + ' Buffer Size: ' + buffer.length; } var halfSize = 1, phaseShiftStepReal, phaseShiftStepImag, currentPhaseShiftReal, currentPhaseShiftImag, off, tr, ti, tmpReal; for (var i = 0; i < bufferSize; i++) { real[i] = buffer[reverseTable[i]] * this.windowValues[reverseTable[i]]; imag[i] = 0; } while (halfSize < bufferSize) { phaseShiftStepReal = cosTable[halfSize]; phaseShiftStepImag = sinTable[halfSize]; currentPhaseShiftReal = 1; currentPhaseShiftImag = 0; for (var fftStep = 0; fftStep < halfSize; fftStep++) { var i = fftStep; while (i < bufferSize) { off = i + halfSize; tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]); ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]); real[off] = real[i] - tr; imag[off] = imag[i] - ti; real[i] += tr; imag[i] += ti; i += halfSize << 1; } tmpReal = currentPhaseShiftReal; currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag); currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal); } halfSize = halfSize << 1; } for (var i = 0, N = bufferSize / 2; i < N; i++) { rval = real[i]; ival = imag[i]; mag = bSi * sqrt(rval * rval + ival * ival); if (mag > this.peak) { this.peakBand = i; this.peak = mag; } spectrum[i] = mag; } return spectrum; }; }; /* eslint-enable complexity, no-redeclare, no-var, one-var */ /** * @typedef {Object} SpectrogramPluginParams * @property {string|HTMLElement} container Selector of element or element in * which to render * @property {number} fftSamples=512 number of samples to fetch to FFT. Must be * a pwer of 2. * @property {number} noverlap Size of the overlapping window. Must be < * fftSamples. Auto deduced from canvas size by default. * @property {string} windowFunc='hann' The window function to be used. One of * these: `'bartlett'`, `'bartlettHann'`, `'blackman'`, `'cosine'`, `'gauss'`, * `'hamming'`, `'hann'`, `'lanczoz'`, `'rectangular'`, `'triangular'` * @property {?number} alpha Some window functions have this extra value. * (Between 0 and 1) * @property {number} pixelRatio=wavesurfer.params.pixelRatio to control the * size of the spectrogram in relation with its canvas. 1 = Draw on the whole * canvas. 2 = Draw on a quarter (1/2 the length and 1/2 the width) * @property {?boolean} deferInit Set to true to manually call * `initPlugin('spectrogram')` */ /** * Render a spectrogram visualisation of the audio. * * @implements {PluginClass} * @extends {Observer} * @example * // es6 * import SpectrogramPlugin from 'wavesurfer.spectrogram.js'; * * // commonjs * var SpectrogramPlugin = require('wavesurfer.spectrogram.js'); * * // if you are using