Realtime spatial audio server for the akM toolchain, built with SuperCollider.
akm-server is now booted through a modular entrypoint:
bootstrap.scd(entrypoint)lib/00_config.scd(JSON loading + validation)lib/01_server_options.scd(SC server options from config)lib/02_buses.scd(all control/audio buses)lib/03_synthdefs.scd(DSP graph definitions)lib/04_groups.scd(execution order)lib/05_synths.scd(instance creation)lib/06_osc.scd(OSC API v3: setters + heartbeat + perf + meters + 20 Hz change-driven/state/*+/event/*)lib/07_util.scd(helpers)
v3 migration note — the group EQ went from 5 bands to 3 parametric peaks (no shelves; the per-role group filter handles broad shaping). Any
lowShelf/highShelfblocks inpackages/akm-config/venues/main/server.jsonare ignored on load and stripped on the next save. If you relied on shelves, fold their effect into the group filter or the peaks before upgrading. Seepackages/akm-config/docs/osc.mdfor the v3 OSC API.
The legacy monolithic script akM_spatServer.scd is kept as historical reference only.
Config is externalized in JSON and shared from packages/akm-config:
packages/akm-config/venues/main/layout.jsonpackages/akm-config/venues/main/server.json
Launch command from repository root:
sclang "akm-server/bootstrap.scd" -- "packages/akm-config/venues/main/layout.json" "packages/akm-config/venues/main/server.json"From repository root:
pnpm run test:osc-smokeWhat it checks:
- server reaches
AKM SERVER READY - ACK round-trips for core OSC endpoints
- at least one heartbeat + source state packet is received
/akm/server/quitreturns ACK and exits cleanly
Troubleshooting:
- Ensure SuperCollider is installed and
sclangis available at/Applications/SuperCollider.app/Contents/MacOS/sclangor override withAKM_SCLANG_BIN. - If ports are in use, set
AKM_SERVER_CONFIG_PATHto a config with free OSC listen/reply ports. - Use
AKM_SMOKE_VERBOSE=1to print all OSC send/receive traffic during the test.
- 36 satellites (
satellite) - 4 low-medium subs (
sub_mid) - 2 low-frequency subs (
sub_lf) - 42 output channels with explicit
outputChannelmapping
Per source:
\spatPannerSourcecomputes gains + delays for three independent pools:- satellites
- sub_mid
- sub_lf
\inputAudioProcessorreadsSoundIn, applies distance attenuation and squared delay law, writes dry/wet buses.
Global:
\satReverbFXand\subMidReverbFX- Group filter + EQ synths:
\groupSatFilterEq\groupSubMidFilterEq\groupSubLfFilterEq
\outputRouterapplies per-speaker gains + system gain and routes to hardware outputs.
All paths start with /akm/.
See full contract in:
packages/akm-config/docs/osc.md
Core paths:
/akm/source/{sourceId}/params/akm/speaker/{speakerId}/gain/akm/group/{role}/eq/akm/group/{role}/filter/akm/system/reverb/akm/system/gain/akm/server/quit
Outbound:
/akm/server/ack/.../akm/server/heartbeat/akm/server/meters/akm/server/state/source/{sourceId}
- SuperCollider 3.12+
- SC3 plugins
- JSONlib quark (
Quarks.install("JSONlib")) — config loading usesJSONlib.parseFile
Use this after booting the 42-channel config:
- In Activity Monitor, observe
scsynthandsclangCPU while sources are moving. - Trigger simultaneous source updates (32 sources) and watch sustained CPU for 5+ minutes.
- Confirm no XRuns/dropouts at target sample rate.
- Tune
telemetry.stateBroadcastHzandtelemetry.metersHzinserver.jsonif needed.
GNU GPLv3.