The csound engine runs a full Csound 7 instance as a synth on the spotykach. An orchestra (a .csd text document) is compiled and performed at runtime, so the patch — not the firmware — defines the sound. You load orchestras from the SD card, switch between them live, and play them from the panel knobs and over MIDI.

It behaves like any other engine on the panel, but is built and flashed a little differently: Csound's code is ~2 MB (too big for SRAM), so this is a QSPI build that executes from flash. Internals (memory model, allocator, bring-up notes, roadmap) are in docs/dev/csound-impl.md.

Csound control surface
Csound control surface - open full size download PDF

_Generated from docs/diagrams/controls/csound.json via make diagrams._

Build & flash

One-time: build the Csound library (needs cmake and the arm-none-eabi GCC toolchain):

scripts/fetch_csound.sh          # download Csound 7 + cross-build libcsound.a

Then build + flash the engine (put the board in DFU first):

make engine-csound               # clean + build the QSPI image + flash
make program-csound              # re-flash the last build without rebuilding

Recover the board at any time by flashing any normal engine.

Controls

With the built-in orchestra (used when no SD patch is loaded):

ControlEffect
PITCHpitch
SIZEbrightness (filter cutoff)
MIXlevel
MIDI NoteOnplays a note (channel 1 → deck A, channel 2 → deck B)
centre mode LEDwhite = built-in orchestra, cyan = an SD patch is loaded

What each knob actually does is up to the patch (it reads named control channels) — the table above is the convention the bundled patches follow.

Loading patches from the SD card

Put full CSD documents in a csound/ folder at the card root, named 0.csd7.csd:

<card>/csound/0.csd
<card>/csound/1.csd

Ready-to-copy examples are in examples/csound/ — a drone+pluck, a fat bass, and a polyphonic MIDI lead, with a README.

Writing a patch

A patch is an ordinary CSD. To be driven by the panel, read these control channels with chnget (deck A / deck B):

KnobChannel
PITCHspeedA / speedB
MIXmixA / mixB
SIZEsizeA / sizeB
ENVenvA / envB
modifier layerfbA, modspA, modampA (+ B)

Define instr MidiNote (with p4 = note frequency in Hz) to make the patch playable from MIDI. The examples/csound/ orchestras are the templates.

Format rules that matter — the on-device CSD parser is line-oriented and strict:

<CsoundSynthesizer>
<CsOptions>
</CsOptions>
<CsInstruments>
  ; sr / 0dbfs / nchnls, then your instr 1.. and instr MidiNote
</CsInstruments>
<CsScore>
</CsScore>
</CsoundSynthesizer>

MIDI is NoteOn-only on this platform (no note-off, no velocity), so MIDI notes are fixed-length stabs, not hold-while-pressed. For clean polyphony, sum your voices through a limiter rather than each calling outs (otherwise overlapping notes clip) — see examples/csound/2.csd.

Limitations