[screen] round 5 notes: both organs, and what I could not verify
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
fd2aee6c50
commit
70130c9e71
@ -410,3 +410,131 @@ NEXT (not self-assigning): the era→standard table means THE SCREEN now knows a
|
||||
strata skins (sepia Reel, phosphor Broadcast, rainbow-on-black Disc) could drive the *base feed's*
|
||||
palette per the player's current era, so the clean programming itself ages as they tech up. That
|
||||
plus the mask template would give era-flavoured biomes on the sky.
|
||||
|
||||
### Round 5 (MEGA) — 2026-07-18 — Opus 4.8
|
||||
|
||||
SHIPPED: all 8 orders, both organs. THE SPEAKER exists.
|
||||
- PART A: `eras.ts` + `eras.test.ts` (new), `baseTexture.ts` (era substrate + general chyron),
|
||||
`glitchStack.ts` (wildlife pass, title composite), `boredom.ts` (jammed-rot), `index.ts`.
|
||||
- PART B: `graph.ts`, `sfx.ts`, `stations.ts`, `radio.ts`, `ambience.ts`, `subtitleBus.ts`,
|
||||
`band.test.ts` (all new), and `index.ts` replacing the stub.
|
||||
- 78 tests in my two lanes, all green. Repo-wide 443/443, tsc clean.
|
||||
|
||||
**A NOTE ON "VERIFICATION INCLUDES LISTENING": I cannot hear.** I have no ears, and I won't
|
||||
pretend a waveform is a listening session. What I did instead is render every sound through an
|
||||
`OfflineAudioContext` and measure it — spectra, peak/RMS, attack times, onset rates — and the
|
||||
description below is derived from those measurements plus the synthesis I wrote. It is an
|
||||
honest account of what the numbers say the speaker is doing, not of what it feels like in a
|
||||
room. **Please put headphones on and tell me what's wrong** — mix balance and "is this
|
||||
annoying after ten minutes" are exactly what measurement can't answer, and I'd rather get that
|
||||
from you than guess.
|
||||
|
||||
WHAT IT SOUNDS LIKE (measured, then described):
|
||||
- **Brownout** — the important one. A 0.29 ms attack: a genuine broadband click, not a fade.
|
||||
Then ~0.5 s of bandpassed brown crackle and a sawtooth whine sliding 420→40 Hz under a
|
||||
closing lowpass. It should read as a rack losing its rails: snap, spit, sag.
|
||||
- **Placement thunk** — 2.3 ms attack, a sine dropping 150→55 Hz (the mass) under a 1.4 kHz
|
||||
noise slap (the contact). Detuned per placement so a row of belts isn't a machine gun.
|
||||
- **Scram klaxon** — 620/440 Hz square alternating four times, lowpassed at 1.8 kHz. Peak 0.29:
|
||||
deliberately not the loudest thing, because it fires often.
|
||||
- **Ratification sting** — 85 ms attack, F–A–C sines with an octave shimmer. The *only*
|
||||
consonant, in-tune, untroubled sound in the game. Everything the player makes is filth; the
|
||||
enemy sounds lovely. That's the joke, and it's why its attack is slow when everything else
|
||||
is percussive.
|
||||
- **FKTRY FM 88.1** — 4.9 note onsets/sec against 6.13 sixteenths at 92 bpm, i.e. the ~34%
|
||||
rests are audible as space rather than a wall. Square lead over triangle bass, pentatonic
|
||||
minor, pattern mutating every 32 bars. Spectrum is bass-dominant (60 Hz: 0.49) with nothing
|
||||
above 4 kHz.
|
||||
- **THE STANDARD 640** — 2.9 syllables/sec, which is real speech cadence. Ring-modulated
|
||||
carrier through two moving formants, lowpassed at 4.5 kHz to AM bandwidth. Sits at 500 Hz
|
||||
and nowhere else. It is deliberately just short of intelligible — you can hear that it's
|
||||
speech and not what it says. **THE SCREEN tells you what it says.** That gap is the trick.
|
||||
- **NUMBERS 6955** — 4.0 digits/sec, a formant voice with a per-digit vowel shape so numerals
|
||||
are learnable by ear, through a narrow SW bandpass (sharp 2 kHz peak, 0.50). No affect, no
|
||||
melody, no acknowledgement.
|
||||
- **DEAD AIR 108.0** — lowpassed brown room tone breathing at 0.21 Hz (projector pace), plus
|
||||
one reversed chime — swelling up out of nothing then cut dead — every ten minutes, seeded.
|
||||
|
||||
DECISIONS:
|
||||
- **Everything takes `(ctx, dest, t0)` and nothing assumes a live context.** That one choice is
|
||||
why the whole speaker can be rendered in an `OfflineAudioContext` and measured deterministically
|
||||
— same code the player hears, no test-only path. Noise buffers use a seeded PRNG for the same
|
||||
reason: identical spectra every run.
|
||||
- **The limiter is a `tanh` WaveShaper, not a DynamicsCompressor.** A compressor's makeup gain
|
||||
would pump the entire mix every time the klaxon fires. tanh just refuses to exceed 1, which is
|
||||
what "don't clip" actually means, and it adds the saturation a blown factory PA should have.
|
||||
- **Pre-discovery silence is structural, not a volume setting.** The radio's master gain is 0
|
||||
and ambience is never started until `relicFound`. Layer 1 is all one-shots, so a quiet factory
|
||||
is *actually* quiet between events rather than humming under a noise floor.
|
||||
- **Inter-station noise is band-specific** because that's what makes a band feel like a place:
|
||||
AM brown crackle, FM white hiss, SW a wandering bandpass plus a heterodyne whistle whose pitch
|
||||
is the beat frequency — so it swoops *down to nothing* as you zero in. Hunting is the mechanic.
|
||||
- **The era ages the substrate, never the corruption.** Same shader, same params; only what
|
||||
they're painted onto changes. The contact sheet shows identical melt drips across all five eras.
|
||||
- **Boot era is `reel`.** With nothing ratified the world starts in the deepest stratum and
|
||||
climbs to the surface (stream) and beyond (fortress). The old SMPTE look is now mid-game.
|
||||
- Title timed in seconds (1.53 s hold, gone by 2.07 s), awakening 0.47 s. Both are *moments*;
|
||||
the scram wipe stays frame-counted because it's a tape artifact. Three clocks, three fictions.
|
||||
|
||||
VERIFIED (offline render + pixel reads + contact sheets):
|
||||
- **Pre-discovery silence: peak 0.0 and RMS 0.0, exactly zero**, with the dial swept across all
|
||||
three bands and ambience asked for max load+fever. Same graph post-discovery: peak 0.285.
|
||||
- **Station lock vs static are distinct spectra, and correctly so per band.** AM static has
|
||||
**70× the 60 Hz energy of AM locked** (1.40 vs 0.02 — the brown crackle). FM *inverts*: locked
|
||||
is bass-dominant (0.49 @60 Hz, nothing @14 k), static is treble-only hiss (0.10 @14 k, nothing
|
||||
@60 Hz). SW locked shows a 2 kHz formant peak (0.50) that static (0.09) lacks.
|
||||
- **Subtitles end-to-end**: tuned AM → The Correction's line on the chyron; off by 4 kHz (lock
|
||||
0.906) → still captioned; off station → caption clears; SW → `5 3 0 7 9` on the sky, which is
|
||||
the real coordinate for the nitrate vein. FM and DEAD AIR caption nothing (no words). Screenshot
|
||||
in the sheet.
|
||||
- **Era contact sheet**: reel (sepia + sprocket holes), broadcast (phosphor + interlace), disc
|
||||
(rainbow-on-black gloss), stream (classic SMPTE), fortress (blinding white) — all under the
|
||||
same 20× melt.
|
||||
- **Budget: SCREEN 0.040 ms/frame** (GPU sync, 2000 entities, every artifact + wildlife + strain
|
||||
+ brownout). **SPEAKER 0.0063 ms/frame** on the worst case (SW numbers + heterodyne + ambience)
|
||||
— the per-frame path only writes AudioParams; Web Audio does synthesis on its own thread.
|
||||
|
||||
BLOCKED/BROKEN: nothing blocking.
|
||||
- **I caught a balance bug by measuring rather than hearing**: DEAD AIR rendered at RMS 0.072,
|
||||
*louder than the music station* (0.032), which made "dead air" the loudest thing on the dial —
|
||||
exactly backwards. Dropped its tone gain 0.32→0.10 and the breath depth with it; it now sits at
|
||||
0.023, under the music. This is the clearest argument for you actually listening: I only found
|
||||
it because I happened to print RMS side by side.
|
||||
- Harness gotcha, mine not the product's: importing a module with a `?v=` cache-buster creates a
|
||||
**second module instance**, so my first subtitle test wrote to a different singleton than THE
|
||||
SCREEN reads and the chyron looked broken. Verified `busQ !== busC`. Re-ran canonically and it
|
||||
works. Same family as round 3's clock rewind: the harness lied, not the code.
|
||||
|
||||
FINDING FOR LANE-DATA (not touching their file): `stations.json`'s `_doc` says the decoys
|
||||
"decode to empty ground", but **two of them decode onto real seams** — `08127` → (-24,-20) lands
|
||||
in `reel-beds-deep`, and `27503` → (-5,18) lands in `broadcast-shelf-south`. Both are visible,
|
||||
non-hidden seams so no secret leaks and the treasure hunt is intact — it's a doc/data drift, not
|
||||
a break. I deliberately did **not** red-light my suite over another lane's content (round 4's
|
||||
lesson); my test asserts the invariant that actually matters — *no decoy ever leaks a HIDDEN
|
||||
seam* — which passes. Their three planted groups all decode exactly right, and I have a test
|
||||
pinning that against `seams.json` so the map can never drift.
|
||||
|
||||
CONTRACT REQUEST: none. v6 covered everything.
|
||||
|
||||
SANCTIONED IMPORTS (documenting as ordered): LANE-UI's tuner dock should
|
||||
`import { getRadio } from '../audio'` — a narrow surface of setBand/setFrequency/setVolume/
|
||||
setMuted/getState/subscribe/listStations, nothing else reachable. Returns `null` before the first
|
||||
user gesture builds the graph, so the dock must handle that (and should probably render disabled
|
||||
until `getState().unlocked`). Internally, `src/screen` reads `src/audio/subtitleBus` — both are my
|
||||
lane, and it's a zero-dependency module precisely so neither organ couples to the other's guts.
|
||||
|
||||
STATIONS SCHEMA: I conformed to LANE-DATA's file exactly as written rather than proposing my own
|
||||
— it's better than what I'd have specified (the `eraFlavor` table and the coordinate encoding
|
||||
especially). Nothing to agree; it's already right.
|
||||
|
||||
PROPOSAL: THE STANDARD renders at RMS 0.0037 against FKTRY FM's 0.032 — ~9× quieter. That's
|
||||
*correct* for gated speech (its peak, 0.10, matches the other stations; the gap is all the silence
|
||||
between syllables) but it may still feel too quiet in practice next to continuous music. If it
|
||||
does when you listen, the fix is a slow compressor on that station alone rather than a gain bump,
|
||||
which would just make the syllables shout. Flagging rather than pre-emptively "fixing" something
|
||||
the numbers say is fine.
|
||||
|
||||
NEXT (not self-assigning): the tuner has no UI yet — LANE-UI's dock is what makes the band
|
||||
findable at all, and until then the radio is only reachable from the console. Also `growthMask`
|
||||
now has two customers (moiré, wildlife) and is ready for a third: HF dust piles are regional in
|
||||
the codex and `dust-pile` wildlife already arrives in the same event I'm consuming.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user