/ simulated_instruments / cymbal2
Sign in
simulated_instruments / cymbal2
cymbal2 / webapp / src / components / plots / WaveformPlot.tsx
66 lines · 2.0 KBCodeBlameHistory
1793cecTime-domain nonlinear shell cymbal after Samejima (2021)Jeremy Magland 1import { useCanvas, drawFrame, PLOT_COLORS } from './canvasUtils';
3interface Props {
4 y: Float32Array;
5 sampleRate: number;
6}
8export default function WaveformPlot({ y, sampleRate }: Props) {
9 const ref = useCanvas(
10 (ctx, w, h) => {
11 drawFrame(ctx, w, h);
12 const padL = 34;
13 const padB = 16;
14 const pw = w - padL - 6;
15 const ph = h - padB - 6;
16 const midY = 6 + ph / 2;
18 ctx.strokeStyle = PLOT_COLORS.grid;
19 ctx.beginPath();
20 ctx.moveTo(padL, midY);
21 ctx.lineTo(padL + pw, midY);
22 ctx.stroke();
24 // time gridlines, step chosen so about ten fit
25 const durS = y.length / sampleRate;
26 const steps = [0.05, 0.1, 0.2, 0.5, 1, 2];
27 const tStep = steps.find((s) => durS / s <= 12) ?? 5;
28 ctx.fillStyle = PLOT_COLORS.axis;
29 ctx.font = '10px system-ui';
30 ctx.textAlign = 'center';
31 for (let t = 0; t <= durS + 1e-9; t += tStep) {
32 const x = padL + (t / durS) * pw;
33 ctx.strokeStyle = PLOT_COLORS.grid;
34 ctx.beginPath();
35 ctx.moveTo(x, 6);
36 ctx.lineTo(x, 6 + ph);
37 ctx.stroke();
38 ctx.fillText(`${t.toFixed(1)}s`, x, h - 4);
39 }
40 ctx.textAlign = 'right';
41 ctx.fillText('+1', padL - 4, 12);
42 ctx.fillText('-1', padL - 4, 6 + ph);
44 // min/max envelope per pixel column
45 ctx.strokeStyle = PLOT_COLORS.trace;
46 ctx.beginPath();
47 const perPx = y.length / pw;
48 for (let px = 0; px < pw; px++) {
49 const i0 = Math.floor(px * perPx);
50 const i1 = Math.min(y.length, Math.max(i0 + 1, Math.floor((px + 1) * perPx)));
51 let mn = Infinity, mx = -Infinity;
52 for (let i = i0; i < i1; i++) {
53 if (y[i] < mn) mn = y[i];
54 if (y[i] > mx) mx = y[i];
55 }
56 if (!Number.isFinite(mn)) continue;
57 ctx.moveTo(padL + px + 0.5, midY - mx * (ph / 2));
58 ctx.lineTo(padL + px + 0.5, midY - mn * (ph / 2) + 0.5);
59 }
60 ctx.stroke();
61 },
62 [y, sampleRate],
63 170,
64 );
65 return <canvas ref={ref} />;
↑↓ move↵openescclose