gpojani

Transmission № 00710 minsigil · rule 90

GUZEN: the dice are a 48-bit number

A synthesizer whose six voices are decided by chance. A wavefolder adds the harmonics, a gate with memory shapes each note, and the dice turn out to be one 48-bit number.

Ptractable

Set a clock to two ticks a second. On each tick, flip a coin that lands heads seven times in ten. On heads a voice plays one note, and you don’t choose it: dice can pick its pitch, how hard it is struck, and where it sits between the speakers. Run six voices off three such clocks and you have most of what GUZEN does.

GUZEN is a synthesizer I built twice: first as a plugin, a VST3 written in C++ with JUCE, and then again for this site, where it runs in your browser. It follows Ongaku by Giorgio Sancristoforo, a west-coast synth whose voices are called agents, whose envelopes are low-pass gates, and whose knobs are probabilities. I kept Ongaku’s best idea, that an envelope control sets the highest an envelope may reach rather than where it goes, and rebuilt the rest. The signal path is the one Orfeo 32 runs in your browser: a complex oscillator, a wavefolder and a vactrol gate. Where Orfeo has a sequencer, GUZEN has dice.

Play it →

I file everything on this site by complexity class, and a machine made of dice looks like it should live somewhere exotic. It doesn’t. It belongs in P, and the reason is the most interesting thing about it. Getting there takes four small pieces: the harmonics, the gate, the dice and the seed.

Add harmonics, don’t subtract them

Most synthesizers start with a bright sound and filter it down. West-coast synthesis goes the other way. It starts with a sine, which has no harmonics, and adds them by folding.

A wavefolder reflects its input. Past +1 the output turns round and comes back down, and past −1 it turns up again. As a formula it is a triangle wave of its input:

fold⁡(x)  =  2πarcsin⁡ ⁣(sin⁡πx2).\operatorname{fold}(x) \;=\; \frac{2}{\pi}\arcsin\!\Big(\sin\frac{\pi x}{2}\Big).

Between −1 and 1 it does nothing at all: fold(x) = x. Feed it a sine of height gg and every time the peak climbs past another odd number (1, 3, 5, …) the output turns round once more. GUZEN’s FOLD knob sets g=1+7×FOLDg = 1 + 7 \times \text{FOLD}, so at full the sine is eight times taller than the folder’s window and the output turns round 18 times per cycle, where a sine does it twice. Every turn is a corner, and corners are harmonics. Move the knobs:

Two things to look for. With no symmetry offset the output is odd: shift the wave by half a cycle and it just flips, so only odd harmonics are possible, and the bars show exactly that. Push the wave off-centre before it is folded and the even harmonics arrive, loudly. And the fundamental isn’t always the loudest bar. Around FOLD 0.5 it all but cancels, and the harmonics carry the note.

Folding makes harmonics far above anything a sound card can represent, and the ones that don’t fit come back down as aliases. GUZEN runs the oscillator and the folder at twice the sample rate and filters on the way down with a fourth-order filter. That makes the aliases quieter. It doesn’t remove them.

A gate with memory

The other half of west-coast synthesis is the low-pass gate. Its heart is a vactrol, an LED shining on a light-dependent resistor. The resistor has memory. Switch the light on and it responds in a couple of milliseconds. Switch it off and it lets go slowly, and the dimmer it gets the slower it goes. Put that resistor in the signal path and a single quantity, its conductance cc, sets both volume and brightness. Quiet means dull, with no second envelope to keep in step.

GUZEN models cc with one line of arithmetic per sample. When the gate closes,

c←c−c k (0.12+0.88 c),c \leftarrow c - c\,k\,(0.12 + 0.88\,c),

where kk is about 1/(Tfs)1/(T f_s) for the sample rate fsf_s and the VACTROL knob TT, in seconds. For small steps that is a differential equation,

dcdt  =  − 0.12 c+0.88 c2T,\frac{dc}{dt} \;=\; -\,\frac{0.12\,c + 0.88\,c^2}{T},

and it has a closed solution. Put u=1/cu = 1/c and the equation becomes linear in uu. Starting fully open, at c=1c = 1, the answer is

c(t)  =  1253 e0.12 t/T  −  223.c(t) \;=\; \frac{1}{\tfrac{25}{3}\,e^{0.12\,t/T} \;-\; \tfrac{22}{3}}.

Fully open, cc falls at rate 1/T1/T, like any exponential. As cc shrinks the squared term drops out and the rate sinks toward 0.12/T0.12/T, so the tail is eight and a third times slower than the start. Here is how long it takes to fall to each level, in units of TT, against a plain exponential release with the same starting slope:

falls tovactrolplain exponential
50%0.940.69
10%6.12.3
1%214.6
0.1%406.9

I checked the formula against the per-sample recurrence, and they agree to better than one part in ten thousand. Slide the knob:

The same cc drives both halves of the gate. The VCA multiplies the signal by cc to the power 1.4, and the filter’s cutoff follows c2c^2, from 30 Hz up to as much as 12 kHz depending on the COLOUR knob. This is a cartoon of a real vactrol, which the literature models in far more detail (Parker and D’Angelo, below). It keeps the one property that matters here: the tail slows as it fades.

Three kinds of chance

Don Buchla’s Model 266, the Source of Uncertainty, made a point worth keeping: random is not one thing. It offers three kinds of random voltage and they behave quite differently. GUZEN has all three, chosen per voice for its pitch:

  • FLUCTUATE drifts. It glides between random targets at the DRIFT rate and never jumps, so the voice walks up and down its scale instead of leaping.
  • STEPPED picks one of seven evenly spaced values at each trigger.
  • STORED is sample and hold: one draw per trigger, kept until the next.

The last two have a shape control. Draw uu uniformly between 0 and 1 and raise it to a power ee. At e=1e = 1 you get a uniform value. Otherwise the draws pile up towards one end, and

P(value≤x)  =  x1/e,mean  =  11+e.P(\text{value} \le x) \;=\; x^{1/e}, \qquad \text{mean} \;=\; \frac{1}{1+e}.

The BIAS knob sweeps ee from ¼ to 4, with e=1e = 1 at its centre:

emeanchance of landing above ½
¼0.8094%
½0.6775%
10.5050%
20.3329%
40.2016%

I checked each row against two million simulated draws. BIAS isn’t a probability that something happens. It reshapes which things are likely.

Time has chance in it too. A master clock feeds three generators, each running at its own multiple of it, from one eighth to sixteen times. Each tick of a generator is a coin flip with that generator’s probability pgp_g. A voice listens to one generator and flips a second coin of its own, pap_a, and plays only if both land heads. A generator ticking fgf_g times a second therefore triggers that voice fg pg paf_g\,p_g\,p_a times a second on average. Two voices on one generator share the first coin and have separate second ones, so they are tied together and still drift apart.

Then there is how hard each note is struck. The ACCENT knob α\alpha sets the envelope’s ceiling at 1−αu1 - \alpha u, with uu drawn fresh each time, so the ceiling is uniform between 1−α1 - \alpha and 1. At zero every note is full height. At full the peak can fall anywhere from nearly silent to full. That is Ongaku’s idea, in one line.

Whatever the dice say about pitch is snapped to a scale before it reaches the oscillator. There are nine scales, four of them Japanese: in sen (0 1 5 7 10 semitones above the root), hirajoshi (0 2 3 7 8), kumoi (0 2 3 7 9) and iwato (0 1 5 6 10). Dice that can only land on notes of a scale are the cheapest way I know to make chance sound intended.

Why the class is P

Here is the surprise. The dice aren’t dice. GUZEN has exactly one source of randomness, a linear congruential generator, one of the oldest kinds there is:

sn+1  =  (a sn+11) mod 248,a=25 214 903 917.s_{n+1} \;=\; (a\,s_n + 11) \bmod 2^{48}, \qquad a = 25\,214\,903\,917.

JUCE seeds it from the system clocks when the plugin loads, and from then on it is a fixed rule. Every coin, pitch, accent and pan position in GUZEN is read off that one 48-bit state. Given the seed and the knob positions, the whole piece is determined. You can watch it happen on the instrument page: the state of the generator is drawn there as 48 cells, one per bit, and if you type a seed and press restart the same piece plays again.

What does that machine cost? Six voices do a fixed amount of arithmetic per sample, oversampling included, so nn samples of audio take time proportional to nn. The score, meaning which voice plays which pitch and when, depends only on the clock and the dice and not on the audio, so you can compute it by running the event logic alone. Both are polynomial. That is P.

It is a small case of a big question: does randomness help computation? BPP is the class of problems a machine with a coin can solve quickly and usually correctly. Most theorists think it equals P, and Impagliazzo and Wigderson showed in 1997 that it does if some problem solvable in exponential time needs exponentially large circuits. If so, every coin a fast algorithm flips can be replaced by a pseudorandom generator. Nobody has proved it unconditionally. GUZEN is a toy version: it flips coins where a fixed sequence would do.

The first post here offered a working definition: a system is complex when you can’t predict what it does any faster than by letting it run. By that test GUZEN’s chance isn’t complex. The state after nn steps of a linear congruential generator can be computed in about log⁡n\log n multiplications, by squaring the update rule over and over. I checked it: jumping a million steps lands on the same state as walking there one step at a time. Predicting a whole piece is a little harder, because each outcome decides which draw the next event uses, so you have to step through the events. But events are far rarer than samples. The unpredictability is in the listener, not in the machine.

Compare Stochos 64, which this site files under EXP because a single pattern has 2^1024 gate configurations to search. GUZEN has only 2⁴⁸ states of chance, and it never searches them. It just runs.

QuestionHow it is answeredClass
What does the folder do to a sine?Evaluate one formula per sampleP
How long until the gate has closed?The closed form aboveP
Which notes will voice 3 play next?Run the event logic from the seedP
What does a second of audio cost?A fixed number of operations per sampleP

The chance is the only mystery in it, and the mystery is 48 bits.

Under the hood

The plugin is about 2,500 lines of C++ with JUCE, of which the sound engine is about 800, and I have only built it on Windows. The version on this site is the same engine rewritten in TypeScript: one file of about 700 lines that runs in an AudioWorklet, with the same generator, the same oscillator, the same gate and the same 24 presets in six families (Koan, Rain, Bells, Drone, Dense and Low). In both, a MIDI note sets the root of the scale instead of playing a note directly.

Three things differ, and they are all fixes. The browser version removes the constant offset an asymmetric fold leaves in the wave, which the plugin hands to the host; it limits its output so a dense passage can’t pass full scale; and it lets the RISE knob go to four seconds, because three of the presets ask for rises the plugin’s two-second knob quietly cuts short. A script, scripts/check-guzen.mts, runs about fifty checks on it under Node: the generator against exact 48-bit arithmetic, the folder and the gate against the formulas in this post, the clock’s rates, and that the same seed plays the same piece sample for sample.


Further reading: Russell Impagliazzo and Avi Wigderson, “P = BPP if E requires exponential circuits: derandomizing the XOR lemma,” Proceedings of the 29th ACM Symposium on Theory of Computing (1997). Donald Knuth, The Art of Computer Programming, vol. 2, section 3.2.1 (linear congruential generators). Julian Parker and Stefano D’Angelo, “A digital model of the Buchla lowpass-gate,” Proceedings of the 16th International Conference on Digital Audio Effects (2013). The Buchla Model 266 Source of Uncertainty.

keep it free

Support this work

Every instrument, essay and formula here is free, with no ads and no tracking. If this one was worth something to you, a donation keeps it that way: the servers, the AI, and the time.

Paid on Stripe’s secure page: cards, Apple Pay, Google Pay. Nothing is stored here.

Related transmissions

Cite this transmission

BibTeX

@misc{pojani2026guzen,
  author       = {Pojani, Gianni},
  title        = {{GUZEN: the dice are a 48-bit number}},
  year         = {2026},
  month        = {oct},
  howpublished = {\url{https://gpojani.me/posts/guzen/}},
  note         = {gpojani, Transmission no. 007}
}

APA

Pojani, G. (2026, October 1). GUZEN: the dice are a 48-bit number. gpojani. https://gpojani.me/posts/guzen/

Filed under P: Polynomial time. Deterministic, tractably solvable: notes, results, things that are simply done.

Discussion

replies are stored as GitHub Discussions · sign in with GitHub to post

establishing link…

esc

↑↓ move · ↵ open~ terminal · ? shortcuts

gsh — gianni@gpojani

manual · keyboard

Shortcuts

/ ⌘K
search & jump
~
terminal
C
live channel (chat)
J K
next / previous transmission
G then HZLANUXDSVW
home · zoo · lab · atlas · network · unveiled · logic · drums · synth · vocoder · a world made of letters
?
this sheet
P
pause / run the colony
R
reseed
1–4
Conway · HighLife · Day & Night · Anneal
M
listen to the colony
⟲ in the HUD
homeostat: the colony matches your input variety
click · shift-click · drag
glider · glider gun · paint
↑↑↓↓←→←→BA
first contact