I'm trying to calculate the Fast Fourier transform of a wav file in Typescript.
I was thinking about using a dedicated npm package for this, like fft.js, but then I noticed that the standard AnalyzerNode has a built-in FFT feature. However, I've only seen AnalyzerNode used to process real-time audio streams.
How would you send it data loaded from a generic wav file, either loaded from the filesystem or from any other source (e.g. wav-decoder), and not the microphone?
First, note that AnalyserNode
only gives you the magnitude of the FFT; the phase part is not included. However, if that works for you, then you can use an OfflineAudioContext
and suspend(time)
to get the FFT (magnitude). Something like:
// Let f be the file that has the wav file.
// c is used only so we can run decodeAudioData. There are other ways to
// do this.
let c = new AudioContext();
let b = await fetch(f)
.then(response => response.arrayBuffer())
.then(buffer => c.decodeAudioData(buffer));
let oac = new OfflineAudioContext({
numberOfChannels: b.numberOfChannels,
length: b.length,
sampleRate: b.sampleRate});
let a = new AnalyserNode(oac, {fftSize: 1024});
// Suspend the context every fftSize frames so we can get the FFT of
// the previous fftSize frames.
for (let k = a.fftSize; k < b.length; k += a.fftSize) {
oac.suspend(k / b.sampleRate)
.then(() => {
a.getFloatFrequencyData(fftData);
// Copy fftData out or do something with it
});
.then(() => oac.resume());
}
// We can ignore the buffer that startRendering would return from the
// resolved promise.
await oac.startRendering();