K

Data buckets

Stream realtime DSP data to the GPU as textures, rings, and arrays.

A bucket is a block of realtime data your DSP writes and a GPU shader reads as a texture: a spectrogram history, a waveform, an arbitrary field. Declare it in describe, fill it in process, sample it by name in the shader.

Buckets are only serialized while the canvas is on-screen and only when the data changed, so an idle visual costs nothing.

Declare

MethodShapeRead in shader as
m.array(name, len, format?)1D, 1 x lenimage("name", uv)
m.texture(name, w, h, format?)2D imageimage("name", uv)
m.ring(name, w, frames, format?)Scrolling history, w x framesimage("name", uv)

A ring is the one for spectrograms and waterfalls: write the newest column each block and the host scrolls it for you, with a stable time axis and no full re-upload.

Formats

Pick the smallest format that holds your data. It sizes the buffer, the bytes shipped to the UI, and the GPU upload all proportionally.

FormatBytes/texelUse
FMT_R81Scalar byte.
FMT_R16F2Scalar half-float (great for a spectrogram).
FMT_RG16F4Two half-floats.
FMT_RGBA8 / FMT_R32F4Color bytes / scalar float.
FMT_RGBA16F / FMT_RG32F8
FMT_RGBA32F16Full-precision RGBA (default).

Transport

The 6th arg to a bucket controls when it's sent:

  • XPORT_WATCHED (default): sent once per block, only while the canvas is visible.
  • XPORT_HOT ("hot_frame"): always sent. For tiny, always-on data.

Write

CallFor
ctx.writeBucket(idx, float32Array)The FMT_*32F formats.
ctx.writeBucketBytes(idx, uint8Array)Packed formats. Pack half-floats yourself with f32ToF16(value).

idx is the bucket's declaration order.

Limits

Max 1024 per side, and 1 MiB per bucket.

Example

// describe: a scrolling spectrogram, half-float scalar
m.ring("spectro", 512, 256, FMT_R16F);

// processSpectrum: pack one column of dB magnitudes as f16 and write it
ctx.writeBucketBytes(0, packedColumn);

The shader reads it with image("spectro", uv).x. See Stream data to a visual and the spectrogram example.