From 1d3039f3e2e9269e69364a9b6da90fd28b36c18f Mon Sep 17 00:00:00 2001 From: skal Date: Wed, 18 Feb 2026 05:20:39 +0100 Subject: refactor(mq_editor): store only squared amplitude after FFT, drop re/im handoff(Claude): removed full spectrum storage from STFTCache frames; getFFT() deleted; viewers use squaredAmplitude + 10*log10 directly. Co-Authored-By: Claude Sonnet 4.6 --- tools/mq_editor/fft.js | 19 ++++++------------- tools/mq_editor/viewer.js | 16 +++++----------- 2 files changed, 11 insertions(+), 24 deletions(-) (limited to 'tools/mq_editor') diff --git a/tools/mq_editor/fft.js b/tools/mq_editor/fft.js index 36b9936..9b9bc94 100644 --- a/tools/mq_editor/fft.js +++ b/tools/mq_editor/fft.js @@ -109,7 +109,7 @@ class STFTCache { this.sampleRate = sampleRate; this.fftSize = fftSize; this.hopSize = hopSize; - this.frames = []; // Array of {time, offset, spectrum} + this.frames = []; // Array of {time, offset, squaredAmplitude} this.compute(); } @@ -131,18 +131,16 @@ class STFTCache { windowed[i] = frame[i] * w; } - // Compute FFT - const spectrum = realFFT(windowed); - - // Cache squared amplitudes (re*re + im*im, no sqrt) + // Compute FFT, store only squared amplitudes (re*re + im*im, no sqrt) + const fftOut = realFFT(windowed); const squaredAmplitude = new Float32Array(this.fftSize / 2); for (let i = 0; i < this.fftSize / 2; ++i) { - const re = spectrum[i * 2]; - const im = spectrum[i * 2 + 1]; + const re = fftOut[i * 2]; + const im = fftOut[i * 2 + 1]; squaredAmplitude[i] = re * re + im * im; } - this.frames.push({time, offset, spectrum, squaredAmplitude}); + this.frames.push({time, offset, squaredAmplitude}); } } @@ -175,11 +173,6 @@ class STFTCache { return this.getFrameAtIndex(frameIdx); } - getFFT(t) { - const frame = this.getFrameAtTime(t); - return frame ? frame.spectrum : null; - } - getSquaredAmplitude(t) { const frame = this.getFrameAtTime(t); return frame ? frame.squaredAmplitude : null; diff --git a/tools/mq_editor/viewer.js b/tools/mq_editor/viewer.js index 21c0a0c..3ca2f87 100644 --- a/tools/mq_editor/viewer.js +++ b/tools/mq_editor/viewer.js @@ -166,7 +166,7 @@ class SpectrogramViewer { const frame = stftCache.getFrameAtIndex(frameIdx); if (!frame) continue; - const spectrum = frame.spectrum; + const squaredAmp = frame.squaredAmplitude; // Compute frame time range const frameTime = frame.time; @@ -186,10 +186,7 @@ class SpectrogramViewer { const freqNext = (bin + 1) * binFreqWidth; if (freqNext < this.freqStart || freq > this.freqEnd) continue; - const re = spectrum[bin * 2]; - const im = spectrum[bin * 2 + 1]; - const mag = Math.sqrt(re * re + im * im); - const magDB = 20 * Math.log10(Math.max(mag, 1e-10)); + const magDB = 10 * Math.log10(Math.max(squaredAmp[bin], 1e-20)); const normalized = (magDB + 80) / 80; const clamped = Math.max(0, Math.min(1, normalized)); @@ -488,8 +485,8 @@ class SpectrogramViewer { ctx.fillStyle = '#1e1e1e'; ctx.fillRect(0, 0, width, height); - const spectrum = cache.getFFT(this.spectrumTime); - if (!spectrum) return; + const squaredAmp = cache.getSquaredAmplitude(this.spectrumTime); + if (!squaredAmp) return; const fftSize = cache.fftSize; @@ -500,10 +497,7 @@ class SpectrogramViewer { for (let i = 0; i < numBars; ++i) { const binIdx = Math.floor(i * numBins / numBars); - const re = spectrum[binIdx * 2]; - const im = spectrum[binIdx * 2 + 1]; - const mag = Math.sqrt(re * re + im * im); - const magDB = 20 * Math.log10(Math.max(mag, 1e-10)); + const magDB = 10 * Math.log10(Math.max(squaredAmp[binIdx], 1e-20)); // Normalize to [0, 1] const normalized = (magDB + 80) / 80; -- cgit v1.2.3