---
id: magic-circle-programming-languages/07-choir-a-signal-flow-synth-whose-voices
title: 'Magic circle programming languages: 7. Choir: a signal-flow synth whose voices
  are the circle''s symmetry'
report: https://ai.hiina.space/reports/magic-circle-programming-languages.md
section: 7
version: 1
updated: '2026-10-27'
author: Hiina
---

Index of everything on this site: https://ai.hiina.space/index.md

# Magic circle programming languages: 7. Choir: a signal-flow synth whose voices are the circle's symmetry

- Section 7 of 13 of the report "Magic circle programming languages" by Hiina (v1, updated 2026-10-27)
- Report overview and contents: https://ai.hiina.space/reports/magic-circle-programming-languages.md
- Previous: https://ai.hiina.space/reports/magic-circle-programming-languages/06-covenant-interaction-combinators-drawn-as-seals-and.md
- Next: https://ai.hiina.space/reports/magic-circle-programming-languages/08-volvelle-a-llull-dial-where-rotation-is.md

## 7. Choir: a signal-flow synth whose voices are the circle's symmetry

The circle is an audio patch. Signal flows inward from the rim to a focus at the centre, each ring band is a processing stage, and k-fold rotational symmetry is k parallel voices. Each glyph's drawing error becomes that voice's analog drift: systematic error sets a fixed detune and wobble sets pitch jitter. **Perfect symmetry collapses to one clean note; human imperfection becomes chorus.** Of the three designs where precision affects the result, this is the one where sloppiness changes the output and is still never wrong. Choir casts in VR as live coding, playing as you draw, and it also reads from paper.

| Visual element | Meaning |
|---|---|
| Rim band | Sources (0 inputs) |
| Inner bands, rim → centre | Successive processing stages (sequential composition) |
| Centre focus dot | Output; sums its inputs |
| Glyphs side by side in a band | Parallel blocks |
| No chord drawn | Default wire to the angularly nearest glyph in the next band inward; many-to-one sums |
| Explicit inward chord | Extra wire (fan-out / split) |
| Arc drawn outward | Feedback wire with a one-sample delay |
| Sine glyph with h humps | Sine oscillator at h · f0 (h-th harmonic of the played note) |
| Falling arc | AR envelope; release ∝ arc length / R |
| Glyph area / band area | Amplitude |
| k-fold rotational symmetry | k voices (no special rule: copies are just parallel blocks) |
| Low-band drawing error | Deterministic parameter offset (detune) |
| High-band drawing error (EFD wobble) | Random parameter jitter (temperature) |

**Model and evaluation.** This is synchronous dataflow with the semantics of Faust's block-diagram algebra (Orlarey, Fober and Letz): sequential, parallel, split, merge, and recursion with an implicit one-sample delay. The parse yields a graph whose forward edges form a DAG and whose outward arcs are feedback edges. At each sample t, nodes are evaluated in topological order, each computing y_v[t] = f_v(Σ forward inputs[t] + Σ feedback inputs[t−1]), and the output is y_F[t]. Note-on and note-off events supply f0 and the envelope gate. Because every feedback path carries a delay, the graph is always causal.

Precision is applied per glyph. A drawn parameter θ is realised as θ̃ = θ · 2^((D + J(t))/1200), working in cents for pitch. D is the deterministic part: for a sine glyph, D = −κ·τ, where τ is the normalised trend in hump period, (P_last − P_first)/P̄, and κ = 70 cents per unit (untested), clamped to ±25 cents. Humps that lengthen along the stroke go flat. J(t) is a slow random walk in the 2 to 8 Hz band with standard deviation proportional to the glyph's high-band EFD energy, seeded from the stroke so the same drawing always sounds the same. With every q = 1, the denotation is the exact deterministic Faust program. An "in tune" assist clamps D and J to zero, and replicating a wedge with a mirror tool gives identical copies, so perfect unison is a choice the player makes, not a penalty.

**Worked example: three-voice bell.** The rim band holds three sine glyphs with two humps each, at 90°, 210° and 330°. The second band holds a falling arc directly inward of each. There are no chords, and the centre is the focus dot.

```
                 ∿∿            rim, 90°   (osc, h = 2)
                  ⌒            band 2     (decay)
                  │
                  ●            focus (sum)
                ╱   ╲
             ⌒          ⌒      band 2, 210° / 330°
          ∿∿              ∿∿   rim, 210° / 330°
```

Faust-like text (written by the design pass, not compiled):

```
voice(d, a, rel) = os.osc(2*f0*2^(d/1200)) * a * en.ar(0.01, rel, gate);
process = voice(1.4, 0.30, 1.2), voice(-5.6, 0.25, 1.1), voice(10.5, 0.35, 1.3) :> _;
```

The trace for the note A3 (f0 = 220 Hz):

| Step | What happens | Values |
|---|---|---|
| 1 | Parse finds three wedges with h = 2 | Each voice nominally 440 Hz |
| 2 | Measured hump-period trends τ give D = −κτ | τ = −0.02, +0.08, −0.15 → D = +1.4, −5.6, +10.5 cents |
| 3 | Realised frequencies, 440 × 2^(D/1200) | 440.36, 438.58, 442.68 Hz |
| 4 | Beats between the pairs | 1.78, 2.32, 4.10 Hz: an audible slow shimmer |
| 5 | Amplitudes from glyph areas, releases from arc lengths | 0.30, 0.25, 0.35; 1.2, 1.1, 1.3 s |
| 6 | Each sample, the three enveloped sines sum at the focus | Output |

Drawn perfectly, all three voices sit at exactly 440 Hz and the circle is one sine of amplitude 0.9.

**Mishaps.** A glyph with no path to the focus is dead: silent and drawn grey. An explicit split or merge whose channel counts do not divide, which Faust would reject, is discord and shows as a red seam between bands. Loop gain above 1 is runaway feedback: a limiter clamps it, and the circle's glow saturates and flickers in time with the clipping.

**Parsing.** In VR, bands are concentric circle fits and glyphs are assigned to bands by radius. Hump count is the number of extrema of the stroke's signed distance from its chord after light smoothing, which is robust and cheap, and the period trend falls out of the extrema spacing. Each new glyph is spliced into the running graph, so latency is one audio buffer. From an image, bands come from Hough and hump count from the skeleton path; symmetry order k comes from the circular autocorrelation of each band's angular ink histogram (the k maximising correlation at lag 360°/k), used only for display since the semantics never needs it. Most wiring is implicit from angle and band, so line topology, the weakest recognition step, is rarely exercised. Feedback arcs are the exception and need skeleton tracing. Do not ask a VLM to count humps.

**New versus borrowed.** Faust's algebra, modular-synth patching, Piet's size-as-number, and Rithmatics' Line of Vigor, which is literally a sine wave whose tightness sets strength, are borrowed. Radial symmetry as polyphony, and splitting drawing error into deterministic detune (low band) and stochastic jitter (high band), are new. Untested: whether κ = 70 gives pleasant chorus or seasickness, and whether hump-count-as-harmonic is musically enough; the design pass suspects a ratio glyph is needed for inharmonic partials.

---

Text licensed CC BY 4.0 (attribution: Hiina, ai.hiina.space). Source: https://github.com/hiinaspace/ai-hiina-space
