---
title: "Signal · generative art"
description: "A picture as a screen receives it, one scanline at a time. Generative art plate #44 by Theodore Vorillas, drawn live in your browser from its code."
url: "https://vorillaz.com/lab/signal"
---

![](https://vorillaz.com/_astro/signal.Wer_f7m0_2iU4Fc.webp)

fig. #44 · rendered live in your browser from the code below

# #44 signal

A picture as a screen receives it, one scanline at a time.

- date

  2026.10.13

- tags

  generative-art · javascript

A picture as a screen receives it. A frame in a black surround is ruled into rows and columns and cut into blocks, and each block carries one kind of signal: barcode bars, dark on black or light on black, a grey carrier, dashes of data, a stripe, a checker. None of it is drawn as a shape. It is laid down one scanline at a time, the way a raster draws a picture, so every bar is a stack of short segments, each a hair off the one above, and a sync burst is a few columns of bright dashes.

There are three channels. The first cuts the frame into small blocks and lets a slow field decide where the bars run light. The second cuts it into large ones: stripes over a ground of data, checkers, and grey fields cut by black bands that step across from row to row. The third is a timing chart. Its rows come in threes, and in each group the bars start a little earlier or stop a little sooner on every repeat, so the frame fills with ladders.

Play it and a beam runs down the frame, redrawing it a scanline at a time. Data changes on every pass. Every so often a block changes, arrives in signal for one pass, and then shows as itself. Now and then the horizontal hold slips, and a band of lines tears sideways, wraps around, and settles back.

## The blocks

```javascript title="signal.js"
// cut at grid lines, mostly across the longer side, until each piece is about `area` cells
const split = (x0, x1, y0, y1) => {
  const W = x1 - x0, H = y1 - y0;
  if (W * H < area * (0.5 + random() * 1.5)) return blocks.push({ x0, x1, y0, y1 });
  if (random() < W ** 2 / (W ** 2 + H ** 2)) {
    const c = x0 + minC + floor(random() * (W - minC * 2 + 1));
    split(x0, c, y0, y1); split(c, x1, y0, y1);
  } else {
    const r = y0 + minR + floor(random() * (H - minR * 2 + 1));
    split(x0, x1, y0, r); split(x0, x1, r, y1);
  }
};
```

## The scanline

```javascript title="signal.js"
// every block is drawn one scanline at a time; a bar is its segments, stacked
for (const [x, w, level] of bars) {
  const n = hash(seed, s, i);
  if (n < 0.008) continue;                     // a segment the signal dropped
  fill(level + (n - 0.5) * 0.03, x + (hash(s, i, seed) - 0.5) * unit * 0.2, y, w, h);
}
```

## The beam

```javascript title="signal.js"
// a few scanlines a frame; a block that changes arrives in signal for one pass
for (let i = 0; i < perFrame; i++) {
  line(beam);
  if (++beam === scanlines) { beam = 0; pass++; }
}
// the hold slips: a band of lines shears sideways and wraps round, then settles
dx = amp * sin(PI * sqrt(e)) * (1 - e * 0.4) * (0.35 + 0.65 * along);
```

## References

- [Raster scan](https://en.wikipedia.org/wiki/Raster_scan)
- [Barcode](https://en.wikipedia.org/wiki/Barcode)
- [Test card](https://en.wikipedia.org/wiki/Test_card)
