From 35ebfac6c860cc7de7db447b57158a7a3a27daaa Mon Sep 17 00:00:00 2001 From: skal Date: Wed, 18 Feb 2026 05:11:12 +0100 Subject: fix(mq_editor): Catmull-Rom bezier fit, NaN guard, synth FFT toggle - evalBezier: guard dt<=0 to avoid NaN on degenerate curves - fitBezier: replace nearest-neighbor control points with Catmull-Rom tangents (Hermite->Bezier), curve now passes through endpoints - key 'a': toggle mini-spectrum between original and synth FFT handoff(Claude): bezier fix + synth FFT comparison Co-Authored-By: Claude Sonnet 4.6 --- tools/mq_editor/viewer.js | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'tools/mq_editor/viewer.js') diff --git a/tools/mq_editor/viewer.js b/tools/mq_editor/viewer.js index e8780e7..21c0a0c 100644 --- a/tools/mq_editor/viewer.js +++ b/tools/mq_editor/viewer.js @@ -40,6 +40,8 @@ class SpectrogramViewer { this.spectrumCanvas = document.getElementById('spectrumCanvas'); this.spectrumCtx = this.spectrumCanvas ? this.spectrumCanvas.getContext('2d') : null; this.spectrumTime = 0; // Time to display spectrum for + this.showSynthFFT = false; // Toggle: false=original, true=synth + this.synthStftCache = null; // Setup event handlers this.setupMouseHandlers(); @@ -467,9 +469,16 @@ class SpectrogramViewer { return this.stftCache.getMagnitudeDB(time, freq); } + setSynthStftCache(cache) { + this.synthStftCache = cache; + } + renderSpectrum() { if (!this.spectrumCtx || !this.stftCache) return; + const useSynth = this.showSynthFFT && this.synthStftCache; + const cache = useSynth ? this.synthStftCache : this.stftCache; + const canvas = this.spectrumCanvas; const ctx = this.spectrumCtx; const width = canvas.width; @@ -479,10 +488,10 @@ class SpectrogramViewer { ctx.fillStyle = '#1e1e1e'; ctx.fillRect(0, 0, width, height); - const spectrum = this.stftCache.getFFT(this.spectrumTime); + const spectrum = cache.getFFT(this.spectrumTime); if (!spectrum) return; - const fftSize = this.stftCache.fftSize; + const fftSize = cache.fftSize; // Draw bars const numBars = 100; @@ -503,14 +512,24 @@ class SpectrogramViewer { const barHeight = intensity * height; const x = i * barWidth; - // Gradient from bottom (cyan) to top (yellow) + // Color: cyan/yellow for original, green/lime for synth const gradient = ctx.createLinearGradient(0, height - barHeight, 0, height); - gradient.addColorStop(0, '#4af'); - gradient.addColorStop(1, '#fa4'); + if (useSynth) { + gradient.addColorStop(0, '#4f8'); + gradient.addColorStop(1, '#af4'); + } else { + gradient.addColorStop(0, '#4af'); + gradient.addColorStop(1, '#fa4'); + } ctx.fillStyle = gradient; ctx.fillRect(x, height - barHeight, barWidth - 1, barHeight); } + + // Label + ctx.fillStyle = useSynth ? '#4f8' : '#4af'; + ctx.font = '9px monospace'; + ctx.fillText(useSynth ? 'SYNTH [a]' : 'ORIG [a]', 4, 10); } // Utilities -- cgit v1.2.3