Go to file
monsterrobotparty 28be1de3b8 🥁 godrum: five synthesized drum voices in the Synth engine
Kick / snare / clap / closed-hat / open-hat as one-shot node graphs
summed onto a drumBus → preSat, so drums ride the world's saturation →
crush → chorus/reverb/echo like every other voice. Each voice keeps a
persistent level→pan chain; hits connect into it. TR-style choke: a
closed hat OR a new open hat cuts the ringing open hat.

Frozen API (§0.6): drum(name,vel), drumParam get/set, drumParamList,
drumKit / drumKitLoad. All params normalized 0..1 at the boundary and
mapped to real units inside each voice; non-finite inputs rejected.
Entirely inside the Synth IIFE — no other territory touched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 21:34:19 +10:00
.claude 🧭 fix deploy target in CLAUDE.md + track dev launch configs 2026-07-09 18:23:58 +10:00
strudel Add dark/yang data, concept groups, named templates, editing console, Strudel kit 2026-07-05 02:25:19 +10:00
viz 🥁 godrum: five synthesized drum voices in the Synth engine 2026-07-12 21:34:19 +10:00
workers 🏟 tune the stadium roster — seven sports round the clock 2026-07-07 22:49:03 +10:00
.gitignore 🎚 the Groove — swing, humanize, per-step velocity & chance 2026-07-09 17:17:46 +10:00
auth.py 🔒 session-token credential binding + admin-guard/CSRF hardening (adversarial review) 2026-07-11 09:51:10 +10:00
build_manual.py 📖 add a polished standalone user manual (viz/manual.html) + generator 2026-07-11 06:49:25 +10:00
cities.json Godstrument: a multi-modal sensor-fusion instrument 2026-07-05 02:13:05 +10:00
CLAUDE.md 🌱 LIFESTRUMENT_BRIEF.md — build brief for the fun one 2026-07-12 12:42:36 +10:00
config.json 🏟 the stadium — the world at play (opt-in) 2026-07-07 20:43:50 +10:00
GODSTRUMENT_MANUAL_SOURCE.md 📖 Z6 — grimoire + manual: zero-build, OMNI panel, dimensions & vibes 2026-07-11 00:37:09 +10:00
godstrument.txt Godstrument: a multi-modal sensor-fusion instrument 2026-07-05 02:13:05 +10:00
hub.py 🧹 health-sweep tidy-up: 5 low-severity loose ends (0 broken found) 2026-07-11 10:21:03 +10:00
LIFESTRUMENT_BRIEF.md 🌱 lifestrument v1.0.1 — post-ship review fixes (fable) 2026-07-12 14:52:04 +10:00
local_source.py local_source.py — device firmware for the "local source" sensor rig 2026-07-06 15:51:42 +10:00
matrix.py Godstrument: a multi-modal sensor-fusion instrument 2026-07-05 02:13:05 +10:00
normalize.py Accounts, socio-economic feeds, and hub fixes (track deployed work) 2026-07-05 16:18:35 +10:00
README.md Add socio-economic data, performance mode, spells (full-state templates) 2026-07-05 02:37:03 +10:00
recorder.py Godstrument: a multi-modal sensor-fusion instrument 2026-07-05 02:13:05 +10:00
requirements.txt Godstrument: a multi-modal sensor-fusion instrument 2026-07-05 02:13:05 +10:00
run.py 🏟 the stadium — the world at play (opt-in) 2026-07-07 20:43:50 +10:00
test_fixes.py Accounts, socio-economic feeds, and hub fixes (track deployed work) 2026-07-05 16:18:35 +10:00
test_lifestrument.py 🌱 LIFESTRUMENT — the gentle client (viz/life.html) 2026-07-12 13:43:48 +10:00
timewarp.py Godstrument: a multi-modal sensor-fusion instrument 2026-07-05 02:13:05 +10:00
transform.py 🧹 health-sweep tidy-up: 5 low-severity loose ends (0 broken found) 2026-07-11 10:21:03 +10:00
ZERO_OMNI_BRIEF.md 📖 brief: STATUS + CONTINUATION — Z0-Z2 approved, C1-C4 instructions (Fable review) 2026-07-10 23:42:05 +10:00

🌍 GODSTRUMENT

An instrument where your hand, the room, and the planet are the same kind of thing.

Godstrument is a multi-modal sensor-fusion instrument. Every input — a hand sensor, the room's microphone, a satellite, the price of bitcoin, an earthquake on the other side of the Earth — is turned into a clean control signal and fired at a central hub. The hub normalizes and smooths everything, runs it through a modulation matrix, and pours the result out as MIDI/OSC for Ableton or TouchDesigner, plus a live web visualizer so you can watch the planet play.

Nothing here needs the physical sensors to run. The world-data feeds and a sensor simulator give you a fully playable instrument today; the ESP32 + ToF + light hardware slot into the exact same OSC contract when they arrive.


The architecture (everything is an OSC source)

  hand / room / sky / markets / humanity                      outputs
  ─────────────────────────────────────                    ───────────
  sim_esp32 ─┐                                          ┌─► OSC /out/*  → Ableton / TouchDesigner
  world_*   ─┤                                          │
  audio     ─┼─►  OSC 9000  ─►  HUB  ─► mod-matrix ─────┼─► MIDI CC / notes (optional, via IAC)
  vision    ─┤              normalize + One-Euro        │
  midi      ─┘              + impulse envelopes         └─► WebSocket 8765 → 🖥  visualizer (http 8088)
  • normalize.py — One Euro filter (jitter-free, low-lag), adaptive normalization (auto-scales unknown/drifting ranges to 0..1), impulse envelopes (events → decaying signals), slew.
  • matrix.py — the patchbay: N sources × M destinations, each cable with an amount, response curve, polarity, optional threshold gate and quantize-to-scale (so a data stream picks notes in a key instead of wobbling formlessly).
  • hub.py — receives all OSC, runs the control-rate clock, evaluates the matrix, drives the outputs + websocket.
  • config.json — the current patch: which source routes to which destination. This is where you compose.
  • workers/ — one process per source, each just emits OSC.
  • viz/index.html — the live console.

The starter patch

The sun opens the master filter · bitcoin volatility drives the hats and plays the lead melody in a minor pentatonic · Delhi's air becomes distortion grit · every Wikipedia edit on Earth is a glitch burst · earthquakes open the reverb void and choose the bass note · Tokyo's weather brightens the pads · aircraft aloft thicken the drone · your (simulated) hand morphs the wavetable and feeds the delay. Edit config.json to rewire any of it.

Run it

python3 -m venv .venv
./.venv/bin/pip install python-osc websockets
./.venv/bin/python run.py

Then open http://localhost:8088. That's it — real planetary data starts flowing in seconds.

Profiles: --profile core (default: simulator + all world feeds), --profile world (data only), --profile all (adds mic/webcam/MIDI workers if their optional libs are installed), --profile minimal (just the simulator).

Live data sources (all free, all keyless)

Source Feed Character
Earthquakes USGS all-hour GeoJSON event triggers
Weather Open-Meteo slow / mood
Air quality Open-Meteo air-quality slow / grit
Solar wind NOAA SWPC slow LFO
ISS position open-notify drift
Crypto ticks Binance websocket sub-second chaos / rhythm
Aircraft OpenSky swarm / drone
Wikipedia edits Wikimedia SSE stream human pulse / glitch
Local sky computed (NOAA solar position) day/night LFO, per-venue
Humanity modelled vital rates births/deaths/growth velocity
Ephemeris / almanac computed (Swiss Ephemeris) planets, moon, planting calendar
National debt US Treasury (no key) slow dark ballast + daily churn
Inflation US BLS CPI (no key) grinding pressure
Human condition World Bank (no key) poverty, hunger, fertility, life expectancy

The dark half (debt, inflation, pollution, quakes, the death rate) balances the bright (births, moon, harmony, fertility, daylight) — group your sources by feeling, not category: a "shadow" group, a "sad" group, whatever you blend. Congress-trade and conflict feeds are possible too but need keyed/curated sources.

Spells

Save a whole configuration — routes, groups, orbits, and the live mix (gains, mutes, freezes) — as a named spell from the ⚙ panel's SPELLS section (save, then load from the dropdown). Casting a saved spell restores the exact state. They live in patches/*.json.

Performance mode

Press P for a clean projection view: the editing chrome vanishes, the source readouts declutter, and a rotating line of "dispatches from the world" (bitcoin at $62,902 · the moon is 81% lit · mercury is retrograde · M4.2 earthquake) appears for the audience. Open the console on a second monitor / projector and hit P. (Curated selections + MIDI-mappable display controls are the next layer.)

Strudel & MIDI voices

The ⚙ Web MIDI out already turns every destination into CC/notes, so any synth becomes an output that "receives sources." strudel/godstrument.md is a starter kit that drives a live Strudel track (free/open, no Ableton) from the hub's CC map — plus a no-MIDI websocket path for a custom web-audio synth.

Playing it live — the performance layer

Raw data is honest but mechanical. The tweak layer (transform.py) lets you play it: gain, offset (bend/lean), invert, freeze (a CDJ-style hold — "stop the planet here"), and smooth (make a signal liquid or snap it tight).

Groups let one control lean on many sources at once. The starter patch defines three — planet (local world), cosmos (shared sky), human — and binds live controls to them in config.json:

"controls": [
  {"src": "hand.open", "target": "@planet", "param": "gain",   "min": 0.2, "max": 1.4},
  {"src": "midi.cc.1", "target": "@cosmos", "param": "offset", "min": -0.3, "max": 0.3},
  {"src": "midi.cc.20","target": "@planet", "param": "freeze", "min": 0.0, "max": 1.0}
]

src is any signal — a hardware knob (midi.cc.1, via the MIDI worker), a hand sensor (hand.open, tof.near), or another data stream. So a physical knob, or your open palm, becomes a macro over four data sources at once.

Time-warp — scratch a month of the planet

run.py --profile warp swaps the live quake + weather feeds for replay workers (timewarp.py): they fetch history and play it back compressed on a loop — 26 days of global earthquakes into 5 minutes, a week of weather into 4 — so glacial data finally has agency in a track.

Because a replay has a playhead, you can scrub it. The warp section in config.json binds a control to each loop's jog:

"warp": {
  "quakes": {"port": 9101, "rate_src": "tof.cx", "nudge_src": "tof.near"}
}

So your hand (or a knob) sets the warp speed and shoves the playhead forward/back like a CDJ platter. A month of the Earth's seismicity becomes a loopable, scratchable rhythm.

Memory — record everything, replay anything

run.py --record runs recorder.py alongside the live rig, taps the hub, and writes every signal + event to godstrument.db (SQLite — live and historical in one file). Then replay_db.py can time-warp any recorded signal — not just feeds with a public history API, but your own hand, the room mic, the ToF sensor:

python workers/replay_db.py --signals tof.cx,tof.cy,audio.rms --window last:3d --into 240

Footprint is small (change-based logging + a decimation cap). Measured: ~68 bytes/sample, so world data ≈ 80 MB/day (most of it the Wikipedia firehose — throttle it and it's ~15 MB/day); fast local sensors at 20 Hz are the main cost. A 35 day rolling buffer is a few hundred MB — trivial, fine on a Pi's SD card. Prune with DELETE FROM samples WHERE t < <cutoff> + VACUUM. recorder.py --stats prints size / signals / span.

Your own market — the dealgod feed

run.py --dealgod runs workers/world_dealgod.py, which reads price history from the basegod warehouse (dealgod.price_events, ~4M rows) over the tailnet — read-only, a single server-side aggregate query, no writes — bins it into an activity curve and an average-price curve, and replays them compressed + jog-scrubbable. Your deal-flow becomes a control source: market activity drives the hats and nudges tempo; average price adds grit and plays the lead melody (G dorian). Flags: --ssh, --days, --into. Point --ssh at a dashboard_ro host for strict least-privilege networked access.

The heavens — real ephemeris, no downloads

world_ephemeris.py computes actual planetary positions with the Swiss Ephemeris (Moshier mode — no data files, 3000 BC3000 AD). Nothing is stored or fetched; the sky is generated on demand, like the sun worker. It emits moon phase, zodiac longitudes (natural LFOs from monthly to Saturn's 29-year wheel), aspect tension/harmony, and retrograde flags. In the starter patch the moon sets the master space, Mercury retrograde smears the delay, hard aspects add grit, Saturn weights the drone. Ephemeris is computed, not ingested — the opposite of big data (pip install pyswisseph, zero downloads).

The console is playable

The visualizer isn't just a display — it's a control surface. Click any source sphere to mute / unmute it (it gets a red slash). The ⚙ button, top-right, opens a panel with per-group mute / freeze / gain macros (planet, cosmos, humanity, market, sky). Commands travel back to the hub over the same websocket, so it stays in sync. Deep patch editing — routes, curves, ranges — still lives in config.json.

Web MIDI (Chrome/Edge): the ⚙ panel has a WEB MIDI section — enable MIDI, pick an out port and the destinations stream as CC/notes straight to your DAW (no Python/IAC needed), pick an in port and hit MIDI learn to bind a knob to any control (click a slider / mute / sphere, then move the knob; saved to localStorage). Web MIDI needs a secure context: localhost works as-is; a VPS-hosted console needs HTTPS (e.g. tailscale serve). The browser runs the MIDI, so a remote-hosted page still drives the MIDI on your laptop.

The planting almanac

world_almanac.py computes the old sow-by-the-moon calendar from the same sky — no data, no downloads. The zodiac's four elements cycle fire→earth→air→water, and biodynamic tradition maps them to crop types, so the Moon walks a slow four-step sequencer (changing every ~2.25 days): earth=root, water=leaf, air=flower, fire=fruit/seed. It also emits waxing/waning (sow above vs below ground), the Moon's ascending/descending declination cycle (~27.3d), and a fertility score. The instrument's character can follow the moon through the garden.

Planetary orbits

Any group can be assigned a planet ("orbit": "neptune" in config.json); its whole contribution then waxes and wanes at that planet's real relative orbital rate. With orbit_base_seconds mapping one Earth year, Mercury (your market) pulses every ~14s, Mars (humanity) every ~113s, Saturn (cosmos) every ~29min, Neptune (the sky) every ~2.7h. Group your sources by planet and the solar system becomes a bank of LFOs spanning seconds to a lifetime.

Wiring it on stage — the editing console

The console is fully live-editable, no config file needed:

  • Drag a source sphere onto a destination to patch a new cable.
  • Shift-click any node for its inspector — what it is, every cable in/out, an amount slider and an unpatch × per connection.
  • ⌘/Ctrl-click spheres to multi-select, then group them into a new macro.
  • Mutes, group macros, and Web MIDI live in the ⚙ panel.

It all travels to the hub over the websocket (add_route / remove_route / set_route / make_group), which rewires the modulation matrix in real time.

Sending it to Ableton / TouchDesigner

  • OSC: the hub streams /out/<destination> floats to 127.0.0.1:9001. Point TouchDesigner's OSC In, or a Max-for-Live OSC device, at that port.
  • MIDI: set "midi": {"enabled": true} in config.json, create an IAC bus in Audio MIDI Setup → MIDI Studio, pip install python-rtmidi, and the hub sends CC + notes to it. Map the CCs in Ableton with MIDI-learn.

Adding real hardware later

The ESP32 firmware just has to send the same OSC addresses the simulator does (/gs/tof/cx, /gs/tof/cy, /gs/tof/near, /gs/light/lux, /gs/light/flash/event) to your Mac's IP on port 9000. Kill sim_esp32.py, power on the board, nothing else changes.