pnpm dlx shadcn@latest add @audio-ui/use-gl-lane
import { sameSamples, visibleClips, OVERSCAN, groundOf, hasWebGL2, /* … */ } from "@/hooks/use-gl-lane";| Files | hooks/use-gl-lane.ts |
|---|---|
| Depends on | arrangement |
| npm | Nothing |
| Used by | block-audio-editor, clip-spectrogram, waveform-lane |
| Export | Kind | What it is |
|---|---|---|
LaneSamples | interface | A recording's samples, mixed to one: how many frames it holds, and a reader of the frames from from to to. |
LaneClip | interface | A clip of a lane to draw: where it starts, what it reads and at what level. |
sameSamples | function | Whether two readings are the same samples: a reader may hand out a new view of the same memory each time, which is not new data to upload. |
VisibleClip | interface | A clip the view shows: its part of the canvas in CSS px from the canvas' left, the frames of its recording it reads there, and its samples. |
visibleClips | function | The clips of a lane the view shows, each with its part of the canvas and the frames it reads there, and their samples read together. |
OVERSCAN | const | The pixels drawn past each edge of the view, so a scroll shows them at once. |
groundOf | function | The nearest background that is not transparent, from element up: what a picture's silence lies over. |
hasWebGL2 | function | Whether this browser can draw with WebGL 2: the lanes that need it say no, and the page draws them another way. |
placeLane | function | Sizes the canvas to the stretch of its lane the view shows, and gives that stretch in CSS px from the lane's left with the device pixel ratio, or hides the canvas when none shows. |
GlLaneContext | interface | What a lane hands its painter and its listeners. |
useGlLane | function | What a lane drawn by WebGL on one canvas needs: the canvas placed on the stretch of the lane the view shows, drawn again when its inputs change, the lane resizes, the view scrolls a good way or the theme changes, and let go of when it leaves. |
Usage
A lane of clips drawn on the GPU is one canvas in the lane's box, sized to the stretch the view shows, with every clip in its own viewport of one WebGL context: a browser keeps some sixteen contexts and drops the oldest past that, so a canvas a clip would lose its picture once a sound is cut into enough pieces. useGlLane is what the two such lanes of the registry share, WaveformLane and SpectrogramLane, and what a lane of your own over another renderer would use.
import { useGlLane, placeLane, visibleClips } from "@/hooks/use-gl-lane";
const ref = useGlLane({
create: () => ({ gone: false, renderers: new Map() }), // what the lane keeps between paints
destroy: (held) => { /* let go of what create made */ },
inputs, // memoized: a new value draws again
paint: async ({ body, canvas, held, inputs, view }) => {
const { clips, zoom } = inputs();
const placed = placeLane(canvas, body, view); // null when no part of the lane shows
if (!placed) return false;
const visible = await visibleClips(clips, placed, zoom); // each with its x, width and frames
// draw each into its viewport; return true while some of it is not yet whole
return false;
},
});
<canvas className="absolute inset-y-0" ref={ref} />;placeLane sizes the canvas to what the view shows and gives where it starts, and visibleClips the clips of the lane the view shows with the frames each reads there and their samples. sameSamples tells whether a reader handed out the same memory again, so it is not uploaded twice, and hasWebGL2 whether this browser can draw this way at all: a page draws the lane another way when it cannot.