feedBack/plugins/tuner/visualization/default.js
2026-06-16 18:47:13 +02:00

82 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Default (gauge) tuner visualization for the Slopsmith tuner plugin.
*
* Contract: window._tunerViz_default(container) → { update(note, cents, freq), destroy() }
* - note: string | null (null = no signal)
* - cents: number (deviation from target, 50…+50)
* - freq: number (detected frequency in Hz)
*/
window._tunerViz_default = function (container) {
'use strict';
// ── DOM ───────────────────────────────────────────────────────────
const noteDisplay = document.createElement('div');
noteDisplay.className = 'my-2 h-16 flex items-center justify-center';
const noteText = document.createElement('div');
noteText.className = 'text-5xl font-black text-white';
noteText.textContent = '--';
noteDisplay.appendChild(noteText);
container.appendChild(noteDisplay);
const freqDisplay = document.createElement('div');
freqDisplay.className = 'text-xs text-gray-500 mb-3 font-mono text-center w-full';
freqDisplay.textContent = '0.0 Hz';
container.appendChild(freqDisplay);
const gaugeEl = document.createElement('div');
gaugeEl.className = 'w-full h-2.5 bg-dark-900 border border-gray-800 rounded-full relative overflow-hidden mb-1.5';
const centerMarker = document.createElement('div');
centerMarker.className = 'absolute left-1/2 top-0 bottom-0 w-0.5 bg-accent z-10';
gaugeEl.appendChild(centerMarker);
const gaugeNeedle = document.createElement('div');
gaugeNeedle.className = 'absolute left-1/2 top-0 bottom-0 w-1 bg-white transition-all duration-100 ease-out -translate-x-1/2 z-20 shadow-[0_0_8px_rgba(255,255,255,0.5)]';
gaugeEl.appendChild(gaugeNeedle);
container.appendChild(gaugeEl);
const centsDisplay = document.createElement('div');
centsDisplay.className = 'text-sm font-bold tracking-tight text-center w-full';
centsDisplay.textContent = '0 cents';
container.appendChild(centsDisplay);
// ── Public API ────────────────────────────────────────────────────
function update(note, cents, freq) {
if (note === null) {
noteText.textContent = '--';
noteText.className = 'text-5xl font-black text-white';
freqDisplay.textContent = '0.0 Hz';
centsDisplay.textContent = '0 cents';
gaugeNeedle.style.left = '50%';
gaugeNeedle.className = 'absolute left-1/2 top-0 bottom-0 w-1 bg-white transition-all duration-100 ease-out -translate-x-1/2 z-20 shadow-[0_0_8px_rgba(255,255,255,0.5)]';
return;
}
noteText.textContent = note;
noteText.className = 'text-5xl font-black ' + (Math.abs(cents) < 5 ? 'text-green-400' : 'text-white');
freqDisplay.textContent = freq.toFixed(1) + ' Hz';
centsDisplay.textContent = (cents > 0 ? '+' : '') + cents.toFixed(0) + ' cents';
const gaugeRange = 50;
const percent = Math.max(0, Math.min(100, 50 + (cents / gaugeRange) * 50));
gaugeNeedle.style.left = percent + '%';
if (Math.abs(cents) < 5) {
gaugeNeedle.className = 'absolute top-0 bottom-0 w-1 bg-green-400 transition-all duration-100 ease-out -translate-x-1/2 z-20 shadow-[0_0_8px_rgba(74,222,128,0.5)]';
} else {
gaugeNeedle.className = 'absolute top-0 bottom-0 w-1 bg-white transition-all duration-100 ease-out -translate-x-1/2 z-20 shadow-[0_0_8px_rgba(255,255,255,0.5)]';
}
}
function destroy() {
noteDisplay.remove();
freqDisplay.remove();
gaugeEl.remove();
centsDisplay.remove();
}
return { update, destroy };
};