Godstrument/README.md
monsterrobotparty 60173d44cb Add socio-economic data, performance mode, spells (full-state templates)
- world_bank.py: poverty, food security, fertility, life expectancy (World Bank)
  folded into the "shadow" / "bright" concept groups
- spells: save/load now captures the full live mix (gains/mutes/freezes), not
  just the wiring; TEMPLATES panel renamed SPELLS
- performance mode (press P): clean projection view + rotating "dispatches from
  the world" text readout for live shows

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 02:37:03 +10:00

258 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🌍 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
```bash
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`:
```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:
```json
"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:
```bash
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.