···11-/*
22- * - **Ghost-loop prevention** via a `stopped` flag — if the cleanup function
33- * is called mid-draw, the loop won't re-schedule itself via the rAF at the
44- * end of the tick (which would otherwise keep the old loop running forever
55- * and fighting any new preview for the canvas).
66- *
77- * Returns a cleanup function — call it once to stop the loop and cancel the
88- * pending animation frame.
99- */
1010-111// double buffered anim loop: draws offscreen then gets placed to
122// visible canvas in one op
133export function createPreviewLoop(
···2414 const displayCtx = canvas.getContext("2d")!;
25152616 let raf: number;
1717+1818+ // using this prevents ghost-loops; if cleanup is called mid-draw,
1919+ // loop won't re-schedule via rAF at end of tick and prevents
2020+ // old loop running forever and fighting new preview for canvas
2721 let stopped = false;
28222923 function loop(now: number) {
3024 if (stopped) return;
3125 if (now >= nextFrame) {
3226 // fps limiting: skips rAF callbacks until the next frame deadline
3333- // then catches up if the callback was delayed (no spiral).
2727+ // then catches up if the callback was delayed
3428 nextFrame += fixedDt * 1000;
3529 if (nextFrame < now) nextFrame = now + fixedDt * 1000;
3630 render(offscreen, fixedDt);
···4034 }
41354236 raf = requestAnimationFrame(loop);
3737+3838+ // cleanup function: called once to stop loop and cancel pending animation
4339 return () => {
4440 stopped = true;
4541 cancelAnimationFrame(raf);
4642 };
4743}
48444949-/**
5050- * Fills a Uint8Array with synthetic frequency data (animated sine wave).
5151- * Used by previews that don't have real audio data.
5252- */
4545+// generates Uint8Array with an animated sine wave
4646+// useful for previews that need real audio data placeholder
5347export function generateSyntheticFreq(
5448 freq: Uint8Array,
5549 phase: number,