Skip to content
The Fenophone

Developer docs

Adaptive runtime reference

The engine that powers the instrument is, structurally, game-audio middleware: a deterministic, seedable, tempo-syncable music core behind a framework-free C interface, proven from plain C in continuous integration on every push.

Why this engine, for a game

Getting the SDK. The runtime and its engine bindings ship privately today — join the waitlist for access (commercial titles and free game-jam builds both start there). These pages are the integration reference for what you get.

The mapping (game state → controls)

Game signalEngine controlBehavior
Danger / combat heatIntensitylive, no re-anchor
World scale / opennessSpreadlive
Pacing / player input rateChange Ratelive — the web demo drives this from applied turns per second, so the player's hands audibly play the dial
Scene detailLayers, Flowlive
Scripted build / stingerpin a slow layer (tri-state)held at the next tick
Mix levelLevellive, smoothed
The game clockhost tempobars phase-lock to your grid
Scene / moodpack switchthe musical transition (below)
Leitmotif / diegetic melodyheld notes + Followthe score riffs around the held harmony (≈ a beat of latency)

And the reverse flow — the game reading the score: each event's harmonic-tension lane is the tension trajectory, and a field-poll call streams the cascade's structure for visualization.

The musical clock. A frames-to-next-bar call is the beat-sync primitive: the number of your own output frames until the next downbeat reaches the listener — schedule a stinger on it, beat-match a gameplay event, or pre-warm the reveal a queued bar-quantized switch will land on (zero exactly on a boundary). A position call reads the output's zero-based musical position in the current take. Both are computed at the current effective tempo and self-correct after a tempo change, exactly like the switch boundary itself.

Musical transitions (the part middleware usually makes you build)

The bar-quantized pack switch is the built-in horizontal re-sequencing primitive: the current pack finishes its bar, the new pack's first tick lands exactly on the next downbeat, and the sample timeline never breaks. Dials, pins, Level, Tempo and Key carry over. It is replay-stable: the same request at the same musical position produces the same audio.

Inference-driven direction (the listener pattern). You do not have to wire a "combat started" event to get the mood move: the Unity director sample ships a regime listener — a small Hamilton filter over the same Markov-switching multifractal family the engine generates from — that infers the regime from one raw gameplay scalar's churn (danger, threat, arousal) and drives the bar-quantized switch through a debounced gate, so the score hears combat rather than being told. See it running in the browser at the live demo with the listener meter on; a calibration tool in the SDK fits the listener to a recorded playtest trace by maximum likelihood.

Audio integration

Determinism & save games

The humanized feel is deterministic too: the microtiming is a bounded, integer-exact function of the seed (a per-voice timing sub-cascade, not a per-playback jitter), so the exact groove survives a replay, a rollback resim, or a loaded save — where a non-deterministic humanizer cannot. Save the seed with the game save for a fresh-but-identical score, or the state chunk to resume the exact take, pins and all. Pin the engine version if your replays must survive engine updates — the event stream is bit-exact per version; rendered audio is tolerance-equal.

The scaffold registry

The registry calls enumerate the embedded packs — the launch packs (beat-driven, warm ambient, cinematic) and the rest of the shipped corpus, every pack held to the same ten quality invariants as the web product, including the spectral-structure gate (the 1/f onset-stream floor) — so a mood switch can never land on a pack that lost its multi-scale character. Artist adaptive-soundtrack packs ride the same registry.

Engine bindings

Thin, idiomatic bindings for the common engines ship with the SDK — a header-only C++ wrapper (the substrate for the others), a Unity package (P/Invoke + an AudioSource component), a Godot 4 GDExtension node, and an Unreal component. Each is a 1:1 wrapper over this interface, pinned to the C header symbol-for-symbol in CI. Start from the game developer start-up guide, or see the bindings overview.

What this is not (yet)

Engine-side state morphs (continuous interpolation between packs) are not built — use the two-instance crossfade. The bindings are reference-grade wrappers, not yet published SDK packages on each engine's store; that productization (and the counsel-reviewed runtime license going live) is gated on real demand — the waitlist is where that signal comes from.

Where to go next