diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-18 07:15:39 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-18 07:15:39 +0100 |
| commit | c37c9459c78a03e2b69b29cbeb17075a19c0418f (patch) | |
| tree | cc9a5db7cd89459927fbea94c6cefc75379bd22d /tools/mq_editor/index.html | |
| parent | 105c817021a84bfacffa1553d6bcd536808b9f23 (diff) | |
refactor(mq_editor): clean coordinate API and remove UI duplication
viewer.js:
- Add timeToX(), freqLogNorm(), normToFreq() coordinate primitives
- freqToY/canvasToFreq now delegate to freqLogNorm/normToFreq
- normalizeDB() replaces duplicated (magDB-(maxDB-80))/80 formula
- partialColor(p) replaces repeated color array
- All inline time/freq→pixel math replaced with API calls
index.html:
- getKeepCount() replaces 3 copies of the same calculation
- playAudioBuffer() replaces duplicated playback setup + RAF loop
handoff(Claude): refactor complete
Diffstat (limited to 'tools/mq_editor/index.html')
| -rw-r--r-- | tools/mq_editor/index.html | 111 |
1 files changed, 37 insertions, 74 deletions
diff --git a/tools/mq_editor/index.html b/tools/mq_editor/index.html index 345d2b9..60076b3 100644 --- a/tools/mq_editor/index.html +++ b/tools/mq_editor/index.html @@ -140,8 +140,8 @@ <canvas id="cursorCanvas" width="1400" height="600" style="position:absolute;top:0;left:0;pointer-events:none;"></canvas> <!-- Mini spectrum viewer (bottom-right overlay) --> - <div id="spectrumViewer" style="position: absolute; bottom: 10px; right: 10px; width: 200px; height: 100px; background: rgba(30, 30, 30, 0.9); border: 1px solid #555; border-radius: 3px; pointer-events: none;"> - <canvas id="spectrumCanvas" width="200" height="100"></canvas> + <div id="spectrumViewer" style="position: absolute; bottom: 10px; right: 10px; width: 400px; height: 100px; background: rgba(30, 30, 30, 0.9); border: 1px solid #555; border-radius: 3px; pointer-events: none;"> + <canvas id="spectrumCanvas" width="400" height="100"></canvas> </div> </div> @@ -184,11 +184,13 @@ const keepPctLabel = document.getElementById('keepPctLabel'); const fftSize = 1024; // Fixed + function getKeepCount() { + return Math.max(1, Math.ceil(extractedPartials.length * parseInt(keepPct.value) / 100)); + } + keepPct.addEventListener('input', () => { keepPctLabel.textContent = keepPct.value + '%'; - if (viewer && extractedPartials) { - viewer.setKeepCount(Math.max(1, Math.ceil(extractedPartials.length * parseInt(keepPct.value) / 100))); - } + if (viewer && extractedPartials) viewer.setKeepCount(getKeepCount()); }); // Initialize audio context @@ -297,7 +299,7 @@ viewer.setFrames(result.frames); setStatus(`Extracted ${result.partials.length} partials`, 'info'); viewer.setPartials(result.partials); - viewer.setKeepCount(Math.max(1, Math.ceil(result.partials.length * parseInt(keepPct.value) / 100))); + viewer.setKeepCount(getKeepCount()); } catch (err) { setStatus('Extraction error: ' + err.message, 'error'); @@ -317,18 +319,12 @@ if (stftCache) runExtraction(); }); - // Play audio - playBtn.addEventListener('click', () => { - if (!audioBuffer || !audioContext) return; - - stopAudio(); - + function playAudioBuffer(buffer, statusMsg) { const startTime = audioContext.currentTime; currentSource = audioContext.createBufferSource(); - currentSource.buffer = audioBuffer; + currentSource.buffer = buffer; currentSource.connect(audioContext.destination); currentSource.start(); - currentSource.onended = () => { currentSource = null; playBtn.disabled = false; @@ -336,43 +332,40 @@ viewer.setPlayheadTime(-1); setStatus('Stopped', 'info'); }; - playBtn.disabled = true; stopBtn.disabled = false; - setStatus('Playing...', 'info'); - - // Animate playhead - function updatePlayhead() { + setStatus(statusMsg, 'info'); + function tick() { if (!currentSource) return; - const elapsed = audioContext.currentTime - startTime; - viewer.setPlayheadTime(elapsed); - requestAnimationFrame(updatePlayhead); + viewer.setPlayheadTime(audioContext.currentTime - startTime); + requestAnimationFrame(tick); } - updatePlayhead(); - }); - - // Stop audio - stopBtn.addEventListener('click', () => { - stopAudio(); - }); + tick(); + } function stopAudio() { if (currentSource) { - try { - currentSource.stop(); - } catch (e) { - // Already stopped - } + try { currentSource.stop(); } catch (e) {} currentSource = null; } - if (viewer) { - viewer.setPlayheadTime(-1); - } + if (viewer) viewer.setPlayheadTime(-1); playBtn.disabled = false; stopBtn.disabled = true; setStatus('Stopped', 'info'); } + // Play audio + playBtn.addEventListener('click', () => { + if (!audioBuffer || !audioContext) return; + stopAudio(); + playAudioBuffer(audioBuffer, 'Playing...'); + }); + + // Stop audio + stopBtn.addEventListener('click', () => { + stopAudio(); + }); + function setStatus(msg, type = '') { status.innerHTML = msg; status.className = type; @@ -390,53 +383,23 @@ setStatus('Synthesizing...', 'info'); - // Synthesize PCM from top-N% partials by amplitude - const sampleRate = audioBuffer.sampleRate; - const duration = audioBuffer.duration; - const keepCount = Math.max(1, Math.ceil(extractedPartials.length * parseInt(keepPct.value) / 100)); + const keepCount = getKeepCount(); const partialsToUse = extractedPartials.slice(0, keepCount); setStatus(`Synthesizing ${keepCount}/${extractedPartials.length} partials (${keepPct.value}%)...`, 'info'); + const integratePhase = document.getElementById('integratePhase').checked; const disableJitter = document.getElementById('disableJitter').checked; const disableSpread = document.getElementById('disableSpread').checked; - const pcm = synthesizeMQ(partialsToUse, sampleRate, duration, integratePhase, {disableJitter, disableSpread}); + const pcm = synthesizeMQ(partialsToUse, audioBuffer.sampleRate, audioBuffer.duration, + integratePhase, {disableJitter, disableSpread}); - // Build STFT cache for synth signal (for FFT comparison via key 'a') if (viewer) { - const synthStft = new STFTCache(pcm, sampleRate, fftSize, parseInt(hopSize.value)); - viewer.setSynthStftCache(synthStft); + viewer.setSynthStftCache(new STFTCache(pcm, audioBuffer.sampleRate, fftSize, parseInt(hopSize.value))); } - // Create audio buffer - const synthBuffer = audioContext.createBuffer(1, pcm.length, sampleRate); + const synthBuffer = audioContext.createBuffer(1, pcm.length, audioBuffer.sampleRate); synthBuffer.getChannelData(0).set(pcm); - - const startTime = audioContext.currentTime; - currentSource = audioContext.createBufferSource(); - currentSource.buffer = synthBuffer; - currentSource.connect(audioContext.destination); - currentSource.start(); - - currentSource.onended = () => { - currentSource = null; - playBtn.disabled = false; - stopBtn.disabled = true; - viewer.setPlayheadTime(-1); - setStatus('Stopped', 'info'); - }; - - playBtn.disabled = true; - stopBtn.disabled = false; - setStatus(`Playing synthesized (${keepCount}/${extractedPartials.length} partials, ${keepPct.value}%)...`, 'info'); - - // Animate playhead - function updatePlayhead() { - if (!currentSource) return; - const elapsed = audioContext.currentTime - startTime; - viewer.setPlayheadTime(elapsed); - requestAnimationFrame(updatePlayhead); - } - updatePlayhead(); + playAudioBuffer(synthBuffer, `Playing synthesized (${keepCount}/${extractedPartials.length} partials, ${keepPct.value}%)...`); } // Keyboard shortcuts |
