Original hard A4
Eight sine generators. Each has its own 9-byte native envelope. Fixed output gains and pan. No hammer noise, no reverb, no amplitude streaming.
Run the original programFANCO / SIREN / a visual teardown
What the current approximation really does, where its 31 kB went, and which parts could become a tiny instrument description instead.
Hard A4 · ~441 HzQuarter-width · reduced 440 Hz openingSnapshot · October 22, 2026
Yes, the first hard-note program was only 307 bytes. The present one is 31,146 bytes — not because it contains a recording or a second synthesizer, but because it spells out eight amplitude controls 1,920 times.
Next design: sparse updates, smooth chip-side motion — interactive reactivity lab →
Loading the audited program data…
01 / Storage is not complexity
Original hard A4
Eight sine generators. Each has its own 9-byte native envelope. Fixed output gains and pan. No hammer noise, no reverb, no amplitude streaming.
Run the original programCurrent listening candidate
The same eight-partial idea, but measured amplitude motion, one noise modulator, stereo reverb, narrower output, and the recent opening adjustment.
Run this exact candidateThese are existing previews, not an envelope-only A/B: pan, hammer and reverb also differ. Similar perceived piano character does not mean the programs produce identical waveforms.
| Component | Original | Current |
|---|---|---|
| Total | 307 B | 31,146 B |
File size is not the whole machine's memory use. SIREN already has internal delay buffers (a 16 MiB shared pool in this prototype), oscillator/envelope state, and a host renderer. These are not embedded in the note's program. A compact patch would still use the chip.
02 / No hidden FM piano
Generators 0–7 produce sine waves at slightly inharmonic frequencies. Their pitches do not wiggle in this candidate. The large table changes their output gains. Generator 8 is a short noise source that amplitude-modulates only generator 0.
Eᵢ is the chip's own envelope. Here the eight carriers have a short 2 ms compact-ADSR attack and then hold at full sustain; the time-table gains provide the audible decay. Initial phase is restarted on trigger. The first sine also has the AM factor described below.
240 Hz: CPU reads the next row.
600 Hz: SIREN
latches parameter changes.
48,000 Hz: oscillators, envelopes and
delay processing generate samples.
The 240 Hz stream is not a 240 Hz recording. Table values are held, not smoothly interpolated by the player; the chip latch adds timing quantization.
Musical pitch registers use 256 steps per semitone. Frequencies below are decoded from the actual program, not copied from the original measurement estimates.
| Partial | Hz | vs i × f₁ | Signed pan | Send / 255 | Peak gain / 4095 |
|---|
03 / What the extra data buys
Solid curves come from the actual current table. Dashed curves are the original 307-byte program's native envelopes, evaluated using SIREN's segment equations. Both are normalized to their own peak so we can compare shape, not absolute mix level.
Vertical axis: amplitude dB relative to each curve's peak, clipped at −60 dB. The current plots show gain words, not the oscillator waveform or reverb output. Times are nominal table times; actual writes/latches add small delays. Original envelopes use ideal segment math with sample-rounded durations.
Each record contains four pairs (target, time) plus a flags byte. In the
original held note, the first three stages are an attack and two decays; stage four is
the release path if gate-off occurs. The original test program does not issue gate-off.
| Partial | Attack target/time | Decay 1 target/time | Decay 2 target/time | Release target/time | Flags |
|---|
Two smooth decays can describe much of a piano note in very little data. They cannot reproduce arbitrary beating-like rises and dips. That is why we temporarily replaced the compact envelopes with measured controls: to learn which motion is audible before designing a smaller model.
Offline analysis isolates each measured partial using complex demodulation and a 30 Hz low-pass filter. It estimates stereo RMS amplitude, subtracts a pre-onset noise-power estimate, compensates pan, and samples the result at 240 Hz. It does not preserve the recording's stereo phase trajectories.
Then come an 8 ms start ramp, an 8-second cutoff with a short fade, gain quantization, and the later listening tweaks. Current quarter-width uses compensated gains/pans/sends. The favorite reduces the first partial by 3 dB through 200 ms, fading that reduction to zero by 500 ms. The actual resulting words are in the inspector below.
Measurements supply the starting curve; listening chooses the useful details. The current favorite includes changes selected by ear, including its narrower stereo image and gentler 440 Hz opening.
04 / The only generator-to-generator modulation
Generator 8 makes colored xorshift noise. Its envelope rises to full level in 2 ms, then decays exponentially toward zero for about 30.65 ms. It has no output slot: it modulates the first sine instead.
AM depth is 32, not full ring modulation. When the noise ends, the carrier remains at 223/255 of its unmodulated value; the fitted table compensates for this. Reducing the first partial also reduces the hammer component carried by it.
255,17, 0,80, 0,0, 0,0, 2
Two active segments, then zero. Flags = 2 makes segment two exponential. No extra sampled hammer recording.
The underlying pseudorandom value is updated on the noise generator's oscillator wrap. Its pitch register is 44000 in musical format; the internal increment is capped at half the sample rate. This shapes a short transient, not a physical hammer simulation.
05 / The space around the note
Each output slot pans one partial directly to left and right, and also sends an unpanned amount into a mono delay bus. Four delay lines feed one another. Their two taps return signed amounts to left and right.
Implemented approximately using existing pan/gain/send values and delay tap levels — not a separate stereo processor. Register rounding makes it slightly approximate. This does not recreate the real recording's evolving stereo phases.
Each main tap contributes ±32/128 to each destination line. In matrix form: F = 0.25 H. H has norm 2, so this feedback mixing has gain 0.5 before damping. Feedback reaches destinations one audio sample later.
| Line / tap | Position code | Samples | Milliseconds | L | R | Feedback |
|---|
Tap positions use the implementation's 16-bit minifloat decoder and fractional-sample interpolation. The current SOUND.txt calls them Q4; that wording is stale. This walkthrough follows the actual kernel. No allpass mode or delay modulation is enabled in this candidate. The standard mixer scaling and master are shown above; the listening WAV additionally uses one fixed offline playback gain.
06 / Open the supposedly mysterious 32 kB
Every row contains eight little-endian 16-bit words, one per output slot. The upper twelve bits are a gain from 0 to 4095. The lower four bits repeat the source generator number, 0–7.
Those repeated source nibbles alone consume 7,680 bytes. They save the player from repacking a word at each update. They are not musical information.
| Row | Nominal time | G0 | G1 | G2 | G3 | G4 | G5 | G6 | G7 |
|---|
Download every word + all patch settings as JSON — an inspectable export, not the binary size of the program.
irq:
cmp r,0
bz done
mov a,[p++]
mov.w [0x200],a ; gain/source for partial 1
mov a,[p++]
mov.w [0x205],a ; partial 2
mov a,[p++]
mov.w [0x20a],a ; partial 3
mov a,[p++]
mov.w [0x20f],a ; partial 4
mov a,[p++]
mov.w [0x214],a ; partial 5
mov a,[p++]
mov.w [0x219],a ; partial 6
mov a,[p++]
mov.w [0x21e],a ; partial 7
mov a,[p++]
mov.w [0x223],a ; partial 8
dec r
done:
reti
The start code sets p to the table and r to 1,920. After eight seconds the zero-gain final row remains active. The IRQ still runs but no longer advances the table. The measured 51,849 guest instructions cover a 16-second render, including this idle tail; that number is not the host renderer's CPU cost.
07 / A model instead of a transcript
The broad dips and recoveries make these envelopes interesting. Rather than store every update, describe a few landmarks and let the chip move between them. The compact original already carries the basic piano character; now we want a small description that also keeps the curves' personality.
23,040 B: pack only the twelve gain bits.
15,360 B:
one quantized byte per gain, still at 240 Hz.
Much less: sparse
breakpoints or fitted native envelopes.
First option removes redundant bits exactly; the byte gains and reduced curves introduce approximation. A decoder has code/state/CPU costs that must be counted.
8 partials × 4 bytes = 32 bytes per anchor. One possible four-parameter starting model is initial level, fast decay time, slow decay time, and slow-tail mixture.
Two decays capture the broad falling shape. To keep the dips and recoveries too, use compact time/level landmarks or a shared shape vocabulary. The vocabulary has its own storage cost.
The 32 bytes would be the varying harmonic-envelope payload, not an entire instrument. Pitch ratios/inharmonicity, shared attack/release behavior, hammer, pan, reverb, decoding code, and per-voice state still need explicit homes. One byte per partial can index a shared vocabulary, but it cannot encode arbitrary independent histories for free.
We have A3, A4 and A5 references — nominally 220, 440 and 880 Hz — at three dynamics. At 32 bytes each, those nine anchors would occupy 288 bytes, plus the shared description and player. None of that compact interpolation is implemented yet.
Interpolation between measured anchors is different from extrapolating outside them. Extrapolation needs bounded rules and listening checks. A single smooth decay model will not represent every instrument, arbitrary nonharmonic spectrum, or articulation. We should fit the current favorite first, then choose the smallest model that keeps what matters to your ears.