From 6ed5952afe5c7a03f82ea02d261c3be2d56bd6a1 Mon Sep 17 00:00:00 2001 From: skal Date: Fri, 6 Feb 2026 16:44:18 +0100 Subject: fix(editor): Apply window to spectrum before IDCT, not after Fixed comb-like pattern in web editor playback by matching the C++ synth windowing strategy. Root Cause: - C++ synth (synth.cc): Applies window to SPECTRUM before IDCT - JavaScript editors: Applied window to TIME DOMAIN after IDCT - This mismatch caused phase/amplitude distortion (comb pattern) Solution: - Updated spectral_editor/script.js: Window spectrum before IDCT - Updated editor/script.js: Window spectrum before IDCT - Removed redundant time-domain windowing after IDCT - JavaScript now matches C++ approach exactly Result: - Clean frequency spectrum (no comb pattern) - Correct audio playback matching C++ synth output - Generated Gaussian curves sound proper Co-Authored-By: Claude Sonnet 4.5 --- tools/editor/script.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'tools/editor') diff --git a/tools/editor/script.js b/tools/editor/script.js index abfd4f4..ebc543a 100644 --- a/tools/editor/script.js +++ b/tools/editor/script.js @@ -631,11 +631,18 @@ async function playSpectrogramData(specData) { // Convert spectrogram frames (frequency domain) to audio samples (time domain) for (let frameIndex = 0; frameIndex < numFrames; frameIndex++) { const spectralFrame = specData.data.slice(frameIndex * dctSize, (frameIndex + 1) * dctSize); - const timeDomainFrame = javascript_idct_512(spectralFrame); - // Apply Hanning window for smooth transitions + // Apply window to spectrum before IDCT (matches C++ synth.cc) + const windowedSpectral = new Float32Array(dctSize); for (let i = 0; i < dctSize; i++) { - audioData[frameIndex * dctSize + i] = timeDomainFrame[i] * hanningWindowArray[i]; + windowedSpectral[i] = spectralFrame[i] * hanningWindowArray[i]; + } + + const timeDomainFrame = javascript_idct_512(windowedSpectral); + + // Direct output (no additional windowing) + for (let i = 0; i < dctSize; i++) { + audioData[frameIndex * dctSize + i] = timeDomainFrame[i]; } } -- cgit v1.2.3