Browse Source

tweak

master
rdrew 3 weeks ago
parent
commit
1833f24f03
  1. 134
      robs_metronome.html

134
robs_metronome.html

@ -263,6 +263,55 @@
margin-top: 10px;
min-height: 1em;
}
.tuner-grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 8px;
}
.string-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
background: var(--panel);
border: 1px solid var(--rule);
border-radius: 6px;
padding: 12px 4px;
cursor: pointer;
font-family: "Work Sans";
color: var(--ink);
transition:
background 0.12s ease,
border-color 0.12s ease;
}
.string-btn .note {
font-family: "Fraunces", serif;
font-size: 1.3rem;
font-weight: 600;
color: var(--walnut);
}
.string-btn .hz {
font-size: 0.68rem;
color: var(--ink-soft);
font-variant-numeric: tabular-nums;
}
.string-btn:hover {
border-color: var(--brass);
}
.string-btn.active {
background: var(--brass-light);
border-color: var(--brass);
}
.string-btn.active .note {
color: var(--walnut);
}
.tuner-hint {
text-align: center;
font-size: 0.8rem;
color: var(--ink-soft);
margin-top: 12px;
}
</style>
</head>
<body>
@ -304,6 +353,14 @@
<hr class="divider" />
<h2>Tuner</h2>
<div class="tuner-grid" id="tunerGrid"></div>
<p class="tuner-hint">
Tap a string to play its tone. Tap again to stop.
</p>
<hr class="divider" />
<h2>Your tunes</h2>
<div class="tune-list" id="tuneList">
<div class="empty" id="emptyMsg">Loading…</div>
@ -330,10 +387,8 @@
accept="application/json"
style="display: none"
/>
<a href="https://tuner-online.com/#sounds" target="_blank">
<button>Guitar Tuner</button>
</a>
</div>
<div class="status" id="statusMsg"></div>
</div>
@ -455,6 +510,79 @@
flashPad(false);
});
// ---------- Guitar tuner ----------
const GUITAR_STRINGS = [
{ note: "E", octave: 2, freq: 82.41 },
{ note: "A", octave: 2, freq: 110.0 },
{ note: "D", octave: 3, freq: 146.83 },
{ note: "G", octave: 3, freq: 196.0 },
{ note: "B", octave: 3, freq: 246.94 },
{ note: "E", octave: 4, freq: 329.63 },
];
const tunerGrid = document.getElementById("tunerGrid");
let tuneOsc = null;
let tuneGain = null;
let activeStringBtn = null;
function stopTunerTone() {
if (tuneOsc) {
const g = tuneGain;
const now = audioCtx.currentTime;
g.gain.cancelScheduledValues(now);
g.gain.setValueAtTime(g.gain.value, now);
g.gain.exponentialRampToValueAtTime(0.0001, now + 0.06);
tuneOsc.stop(now + 0.08);
}
if (activeStringBtn) activeStringBtn.classList.remove("active");
tuneOsc = null;
tuneGain = null;
activeStringBtn = null;
}
function playTunerTone(freq, btn) {
ensureAudio();
if (audioCtx.state === "suspended") audioCtx.resume();
// Toggle off if this string is already sounding
if (activeStringBtn === btn) {
stopTunerTone();
return;
}
stopTunerTone();
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = "sine";
osc.frequency.value = freq;
const now = audioCtx.currentTime;
gain.gain.setValueAtTime(0.0001, now);
gain.gain.exponentialRampToValueAtTime(0.28, now + 0.03);
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start();
tuneOsc = osc;
tuneGain = gain;
activeStringBtn = btn;
btn.classList.add("active");
}
GUITAR_STRINGS.forEach((s) => {
const btn = document.createElement("button");
btn.className = "string-btn";
btn.innerHTML =
'<span class="note">' +
s.note +
s.octave +
'</span><span class="hz">' +
s.freq.toFixed(2) +
" Hz</span>";
btn.addEventListener("click", () => playTunerTone(s.freq, btn));
tunerGrid.appendChild(btn);
});
// ---------- Tune storage (browser-local cache + JSON export/import) ----------
const tuneList = document.getElementById("tuneList");
const emptyMsg = document.getElementById("emptyMsg");

Loading…
Cancel
Save