Rename spectrogram references to waveform throughout codebase

This commit is contained in:
5shekel
2026-01-18 17:37:03 +02:00
parent ef4a303b6d
commit 2144e3dd6b
3 changed files with 50 additions and 66 deletions

94
app.js
View File

@@ -5,8 +5,8 @@ const durationEl = document.getElementById("duration");
const activeSpeakerEl = document.getElementById("activeSpeaker");
const speakerListEl = document.getElementById("speakerList");
const spaceCanvas = document.getElementById("spaceCanvas");
const spectrogramCanvas = document.getElementById("spectrogramCanvas");
const spectrogramOverlay = document.getElementById("spectrogramOverlay");
const waveformCanvas = document.getElementById("waveformCanvas");
const waveformOverlay = document.getElementById("waveformOverlay");
const transcriptPanel = document.getElementById("transcriptPanel");
const configToggle = document.getElementById("configToggle");
const configPanel = document.getElementById("configPanel");
@@ -18,14 +18,14 @@ const sizeSelect = document.getElementById("sizeSelect");
const waveformEmbeddedCheckbox = document.getElementById("waveformEmbedded");
const stageEl = document.querySelector(".stage");
const appEl = document.querySelector(".app");
const spectrogramWrap = document.querySelector(".spectrogram-wrap");
const waveformWrap = document.querySelector(".waveform-wrap");
const embeddedWaveform = document.getElementById("embeddedWaveform");
const embeddedWaveformCanvas = document.getElementById("embeddedWaveformCanvas");
const embeddedWaveformOverlay = document.getElementById("embeddedWaveformOverlay");
const spaceCtx = spaceCanvas.getContext("2d");
const spectrogramCtx = spectrogramCanvas.getContext("2d");
const spectrogramOverlayCtx = spectrogramOverlay.getContext("2d");
const waveformCtx = waveformCanvas.getContext("2d");
const waveformOverlayCtx = waveformOverlay.getContext("2d");
const embeddedWaveformCtx = embeddedWaveformCanvas ? embeddedWaveformCanvas.getContext("2d") : null;
const embeddedWaveformOverlayCtx = embeddedWaveformOverlay ? embeddedWaveformOverlay.getContext("2d") : null;
@@ -75,7 +75,6 @@ const state = {
waveformReady: false,
waveformLoading: false,
waveformEmbedded: false,
stars: [],
spaceSize: { width: 0, height: 0 },
waveformSize: { width: 0, height: 0 },
transcriptRows: CONFIG.transcript.rows,
@@ -398,8 +397,8 @@ function resizeCanvas(canvas, ctx) {
function resizeAll() {
resizeCanvas(spaceCanvas, spaceCtx);
resizeCanvas(spectrogramCanvas, spectrogramCtx);
resizeCanvas(spectrogramOverlay, spectrogramOverlayCtx);
resizeCanvas(waveformCanvas, waveformCtx);
resizeCanvas(waveformOverlay, waveformOverlayCtx);
if (embeddedWaveformCanvas && embeddedWaveformCtx) {
resizeCanvas(embeddedWaveformCanvas, embeddedWaveformCtx);
}
@@ -409,13 +408,12 @@ function resizeAll() {
const { width, height } = spaceCanvas.getBoundingClientRect();
if (width > 0 && height > 0 && (width !== state.spaceSize.width || height !== state.spaceSize.height)) {
state.spaceSize = { width, height };
state.stars = seedStars(width, height);
layoutSpeakers();
}
const specRect = spectrogramCanvas.getBoundingClientRect();
if (specRect.width > 0 && specRect.height > 0) {
if (specRect.width !== state.waveformSize.width || specRect.height !== state.waveformSize.height) {
state.waveformSize = { width: specRect.width, height: specRect.height };
const waveformRect = waveformCanvas.getBoundingClientRect();
if (waveformRect.width > 0 && waveformRect.height > 0) {
if (waveformRect.width !== state.waveformSize.width || waveformRect.height !== state.waveformSize.height) {
state.waveformSize = { width: waveformRect.width, height: waveformRect.height };
}
}
if (state.waveformReady && state.waveformData) {
@@ -423,20 +421,6 @@ function resizeAll() {
}
}
function seedStars(width, height) {
const stars = [];
const count = Math.floor((width * height) / 5500);
for (let i = 0; i < count; i += 1) {
stars.push({
x: Math.random() * width,
y: Math.random() * height,
radius: Math.random() * 1.8 + 0.2,
alpha: Math.random() * 0.7 + 0.2,
});
}
return stars;
}
function renderSpace(timeMs) {
const { width, height } = spaceCanvas.getBoundingClientRect();
spaceCtx.clearRect(0, 0, width, height);
@@ -484,8 +468,8 @@ function renderSpace(timeMs) {
}
function updatePlayhead() {
const { width, height } = spectrogramOverlay.getBoundingClientRect();
spectrogramOverlayCtx.clearRect(0, 0, width, height);
const { width, height } = waveformOverlay.getBoundingClientRect();
waveformOverlayCtx.clearRect(0, 0, width, height);
// Also update embedded waveform overlay
if (embeddedWaveformOverlay && embeddedWaveformOverlayCtx) {
@@ -496,12 +480,12 @@ function updatePlayhead() {
if (!Number.isFinite(audio.duration) || audio.duration <= 0) return;
const progress = audio.currentTime / audio.duration;
const x = progress * width;
spectrogramOverlayCtx.strokeStyle = "#f4d35e";
spectrogramOverlayCtx.lineWidth = 2;
spectrogramOverlayCtx.beginPath();
spectrogramOverlayCtx.moveTo(x, 0);
spectrogramOverlayCtx.lineTo(x, height);
spectrogramOverlayCtx.stroke();
waveformOverlayCtx.strokeStyle = "#f4d35e";
waveformOverlayCtx.lineWidth = 2;
waveformOverlayCtx.beginPath();
waveformOverlayCtx.moveTo(x, 0);
waveformOverlayCtx.lineTo(x, height);
waveformOverlayCtx.stroke();
// Draw playhead on embedded waveform overlay
if (embeddedWaveformOverlay && embeddedWaveformOverlayCtx) {
@@ -586,9 +570,9 @@ function drawWaveformOnCanvas(ctx, peaks, width, height, duration, intervals, sp
}
function drawWaveform(peaks) {
const { width, height } = spectrogramCanvas.getBoundingClientRect();
const { width, height } = waveformCanvas.getBoundingClientRect();
const duration = Number.isFinite(audio.duration) ? audio.duration : 0;
drawWaveformOnCanvas(spectrogramCtx, peaks, width, height, duration, state.intervals, state.speakerMap);
drawWaveformOnCanvas(waveformCtx, peaks, width, height, duration, state.intervals, state.speakerMap);
// Also draw on embedded waveform canvas
if (embeddedWaveformCanvas && embeddedWaveformCtx) {
@@ -601,8 +585,8 @@ async function loadWaveformData() {
if (state.waveformLoading || state.waveformReady) return;
state.waveformLoading = true;
if (spectrogramWrap) {
spectrogramWrap.classList.add("loading");
if (waveformWrap) {
waveformWrap.classList.add("loading");
}
try {
@@ -618,21 +602,21 @@ async function loadWaveformData() {
console.info("Generate waveform data using: node scripts/generate-waveform.js <audio-file>");
} finally {
state.waveformLoading = false;
if (spectrogramWrap) {
spectrogramWrap.classList.remove("loading");
if (waveformWrap) {
waveformWrap.classList.remove("loading");
}
}
}
function attachScrubHandlers() {
if (!spectrogramWrap) return;
if (!waveformWrap) return;
let wasPlaying = false;
const onDown = (event) => {
state.playheadDragging = true;
wasPlaying = !audio.paused;
if (event.pointerId != null) {
spectrogramWrap.setPointerCapture(event.pointerId);
waveformWrap.setPointerCapture(event.pointerId);
}
scrubToEvent(event);
};
@@ -646,7 +630,7 @@ function attachScrubHandlers() {
const wasDragging = state.playheadDragging;
state.playheadDragging = false;
if (event.pointerId != null) {
spectrogramWrap.releasePointerCapture(event.pointerId);
waveformWrap.releasePointerCapture(event.pointerId);
}
// Start playback on any timeline click/scrub
if (wasDragging) {
@@ -654,10 +638,10 @@ function attachScrubHandlers() {
}
};
spectrogramWrap.addEventListener("pointerdown", onDown);
spectrogramWrap.addEventListener("pointermove", onMove);
spectrogramWrap.addEventListener("pointerup", onUp);
spectrogramWrap.addEventListener("pointerleave", () => {
waveformWrap.addEventListener("pointerdown", onDown);
waveformWrap.addEventListener("pointermove", onMove);
waveformWrap.addEventListener("pointerup", onUp);
waveformWrap.addEventListener("pointerleave", () => {
const wasDragging = state.playheadDragging;
state.playheadDragging = false;
if (wasDragging && wasPlaying) {
@@ -665,19 +649,19 @@ function attachScrubHandlers() {
}
});
spectrogramWrap.addEventListener("mousedown", onDown);
waveformWrap.addEventListener("mousedown", onDown);
window.addEventListener("mousemove", onMove);
window.addEventListener("mouseup", onUp);
spectrogramWrap.addEventListener("touchstart", (event) => {
waveformWrap.addEventListener("touchstart", (event) => {
event.preventDefault();
onDown(event.touches[0]);
}, { passive: false });
spectrogramWrap.addEventListener("touchmove", (event) => {
waveformWrap.addEventListener("touchmove", (event) => {
event.preventDefault();
onMove(event.touches[0]);
}, { passive: false });
spectrogramWrap.addEventListener("touchend", (event) => {
waveformWrap.addEventListener("touchend", (event) => {
event.preventDefault();
onUp(event.changedTouches[0] || event.touches[0]);
}, { passive: false });
@@ -685,8 +669,8 @@ function attachScrubHandlers() {
function scrubToEvent(event) {
if (!Number.isFinite(audio.duration)) return;
if (!spectrogramWrap) return;
const rect = spectrogramWrap.getBoundingClientRect();
if (!waveformWrap) return;
const rect = waveformWrap.getBoundingClientRect();
const percent = Math.min(1, Math.max(0, (event.clientX - rect.left) / rect.width));
audio.currentTime = percent * audio.duration;
}
@@ -805,7 +789,7 @@ async function init() {
window.addEventListener("load", () => requestAnimationFrame(resizeAll));
const resizeObserver = new ResizeObserver(() => resizeAll());
if (stageEl) resizeObserver.observe(stageEl);
if (spectrogramWrap) resizeObserver.observe(spectrogramWrap);
if (waveformWrap) resizeObserver.observe(waveformWrap);
if (embeddedWaveform) resizeObserver.observe(embeddedWaveform);
attachScrubHandlers();
attachEmbeddedScrubHandlers();

View File

@@ -60,8 +60,8 @@
<div class="speaker-list" id="speakerList"></div>
</div>
<div class="embedded-waveform" id="embeddedWaveform">
<canvas id="embeddedWaveformCanvas" class="spectrogram"></canvas>
<canvas id="embeddedWaveformOverlay" class="spectrogram overlay"></canvas>
<canvas id="embeddedWaveformCanvas" class="waveform"></canvas>
<canvas id="embeddedWaveformOverlay" class="waveform overlay"></canvas>
</div>
</section>
@@ -74,9 +74,9 @@
<span class="time-divider">/</span>
<span id="duration">0:00</span>
</div>
<div class="spectrogram-wrap">
<canvas id="spectrogramCanvas" class="spectrogram"></canvas>
<canvas id="spectrogramOverlay" class="spectrogram overlay"></canvas>
<div class="waveform-wrap">
<canvas id="waveformCanvas" class="waveform"></canvas>
<canvas id="waveformOverlay" class="waveform overlay"></canvas>
</div>
<div class="scrub-hint">Drag anywhere on the waveform to scrub.</div>
</section>

View File

@@ -185,7 +185,7 @@ body {
background: rgba(5, 7, 11, 0.8);
}
.spectrogram-wrap {
.waveform-wrap {
position: relative;
height: 50px;
border-radius: 0;
@@ -197,14 +197,14 @@ body {
touch-action: none;
}
.spectrogram {
.waveform {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.spectrogram.overlay {
.waveform.overlay {
pointer-events: none;
}
@@ -325,7 +325,7 @@ body {
bottom: calc(25% + 28px);
}
.app.waveform-embedded .transport .spectrogram-wrap {
.app.waveform-embedded .transport .waveform-wrap {
display: none;
}
@@ -333,7 +333,7 @@ body {
display: none;
}
.spectrogram-wrap.loading::before {
.waveform-wrap.loading::before {
content: "";
position: absolute;
inset: 0;
@@ -347,7 +347,7 @@ body {
z-index: 1;
}
.spectrogram-wrap.loading::after {
.waveform-wrap.loading::after {
content: "Loading waveform...";
position: absolute;
inset: 0;