Who picks the sound
The use cases mix two different kinds of sound, and the protocol handles them differently. Getting this wrong in either direction is expensive, so it has its own rule.
The rule
Section titled “The rule”If a teacher, a story or a game script decides what the sound is, the engine names it. If the sound is feedback on something that happened, SuperCollider chooses it.
| Kind | Examples | Who names it | How |
|---|---|---|---|
| Content | A child’s uploaded poem, story narration, the giraffe in the savanna story, “Hull breach detected”, a jungle ambience bed | Engine | /sample/load then /sample/play, or a mode message carrying a sample key |
| Feedback | The chime when a Chase hold is hit, the pattern tone in Find the Match, the arpeggiator itself, a success fanfare | SuperCollider | A mode message saying what happened; SuperCollider maps it to sound using the mode’s soundSet |
Why the split:
- Content changes without code. A teacher uploads a new recording, a story gets a new narrator. If SuperCollider had to know those sounds, every new story would be a SuperCollider change.
- Feedback is sound design. Whether a hit rises in pitch with progress, how a wrong answer sounds so it never feels like a buzzer at a five-year-old — that is the sound designer’s decision, and it belongs where the sound designer works.
Modes that are mostly content — Sound Wall, Memory Game, Arcade — carry sample
keys in their own messages (/mode/memory/correct … "savanna/giraffe"). That
keeps the message semantic, so SuperCollider still knows it is a correct
answer: it pans it to the hold, ducks the ambience, and lets the growl land
harder near the top of the wall.
Samples
Section titled “Samples”Audio never travels over OSC — a 1400-byte UDP packet holds about 15 ms of CD audio. Files live in the asset directory both programs can read:
/sys/assets "/Users/wall/ClimbingWall/assets" the root, once/sample/load "savanna/giraffe" "stories/savanna/giraffe.wav"/sample/loaded "savanna/giraffe" 1 2.4 "" ← wait for this/sample/play "savanna/giraffe" "sfx" 1.0 0.0 0/sample/ended "savanna/giraffe" 1 ← sequence on thisLoad everything a mode will name before /mode/load, and wait for every
/sample/loaded. A sample played before it has loaded is silence that looks
like a bug somewhere else.
The set of loaded samples is state: /sample/load is rate: state, so after a
SuperCollider restart the engine re-sends every load as part of /sys/sync.
Sequencing narration
Section titled “Sequencing narration”Memory Game lights each animal as the story mentions it. Only SuperCollider
knows when a line of narration actually finishes — the engine can only guess
from the duration, and the guess drifts. So the engine plays a line, waits for
its /sample/ended, then lights the next hold and plays the next line.
Every sound belongs to exactly one bus, and each bus has a level:
| Bus | Carries |
|---|---|
voice | Narration, spoken instructions, arcade radio voices |
music | The Climbing Synth arpeggiator, background music |
ambience | Looping soundscapes — jungle, space station |
sfx | Feedback SuperCollider chooses, plus story sound effects |
content | Teacher-uploaded audio in Sound Wall |
/audio/bus/volume sets a level; /sample/play names its bus. SuperCollider
ducks music and ambience under voice automatically, so a story stays
intelligible without the engine riding levels line by line.
Placement
Section titled “Placement”SuperCollider pans every hold-related sound to that hold’s position, using the
live /wall/config — a child on the left hears their hit from the left. In
zoned modes that is what keeps four simultaneous games audibly apart.
/sample/play has an explicit pan for sounds with no hold, such as narration,
which stays centred.
Recording
Section titled “Recording”/audio/record/start and /audio/record/stop capture the master output — what
the room heard, effects included. /audio/record/saved returns a path relative
to the asset root, so a recording can go straight back into /sample/load.
That is what turns Climbing Synth sessions into the class library the use case
asks for.