Sounds
Vector does not have sound files in any normal sense. He has a small games-industry audio engine with 474 named events baked in, and his animations do not play sounds — they ask for an event by number, and the audio engine decides which of the recordings behind that name you actually hear.
That last part is the useful bit, and it was mostly unused.
Everything below was read from the firmware tree and the soundbanks the robot ships with. Nothing was played on a robot to produce it.
The three layers
Section titled “The three layers”Soundbanks: where the audio lives
Section titled “Soundbanks: where the audio lives”Seven soundbanks sit on the robot and are loaded at boot by the animation process — not the engine, and nothing to do with the server.
| Bank | Size | What is in it |
|---|---|---|
Victor_SFX | 5.5 MB | Everything cute: grunts, chirps, purrs, motor sounds |
Victor_Global_Data | 269 kB | Shared containers, state and switch definitions |
Victor_Dev | 94 kB | Internal test tones |
Victor_Alexa | 61 kB | Assistant earcons |
Victor_VO | 1.2 kB | The hook for text-to-speech |
Init | 6 kB | Bus and state setup |
Victor_UI | 32 bytes | Empty; those were the phone app’s sounds |
Alongside them sit 927 loose numbered files — the actual recordings, in the audio engine’s Vorbis flavour, 32 kHz mono. The bank itself mostly holds a 1,864-byte prefetch head of each one and streams the rest off flash, which is why pulling a sound straight out of a bank gives you a fragment rather than the noise you wanted.
Animation clips: how a sound is asked for
Section titled “Animation clips: how a sound is asked for”455 binary files hold 1,185 animation clips, and 954 of them — 80% — make a noise. They do it with an audio keyframe:
{ "Name": "RobotAudioKeyFrame", "triggerTime_ms": 300, "eventGroups": [{ "eventIds": [2483759946], "audioName": ["Play__Robot_Vic_Sfx__Emote_Happy_Short"], "volumes": [1.0], "probabilities": [1.0] }] }Three things are worth knowing about that structure, and all three are easy to get wrong silently:
- Only
eventIdsmatters. The name is not read by anything; it is there so the file is legible. Get the number wrong and the frame is dropped without a word. Get the name wrong and nobody notices at all. eventIds,volumesandprobabilitiesmust be the same length, or the whole group is thrown away with an error in the log.- The probabilities in one group must add up to 1.0 or less, or the clip fails to load outright.
The engine
Section titled “The engine”A few sounds are fired directly by the engine rather than through a clip: the wake-word chirp, the thinking loop, the purr while you pet him. There are only about seventy of those; the animation clips do the overwhelming majority of the work.
The variety mechanism
Section titled “The variety mechanism”One event name is not one sound. Ask for the short happy emote and the audio engine picks one of five different recorded takes. Across all 474 events there are 2,027 separate recordings. That is why he never sounds quite the same twice, and it costs nothing.
On top of that, one keyframe can list several events and let the robot pick one, weighted:
"eventIds": [2091194049, 146478435],"probabilities": [0.45, 0.45]The robot rolls a number between zero and one and walks the list adding up the weights; the first event whose slice contains the number wins. If the weights do not reach 1.0, the remainder is the chance he stays quiet — a 0.45/0.45 split is a 10% chance of silence, which is exactly what stops a repeated idle animation feeling mechanical.
Of 4,254 event groups across every stock clip, only 227 list more than one event. The mechanism was built and barely used.
There is a third lever. Some events make no noise at all; they set a state or turn a parameter that changes what later sounds do. The petting levels are pure state changes, and one event turns the purr-depth knob. Fire one of those first and the purr that follows is deeper and further in.
What he has, and what nobody uses
Section titled “What he has, and what nobody uses”A catalogue of all 474 events is generated from the soundbanks, the decoded animation clips and a grep of the engine. Its columns are: the event name, a bucket, how many stock clips fire it, how many keyframes in total, how many places the engine fires it directly, how many separate recordings are behind it, its duration, its numeric id, and which bank it lives in.
| Group | Events | Never fired by anything |
|---|---|---|
| Movement (head, lift, treads) | 145 | 30 |
| Show (weather, holiday, games) | 80 | 19 |
| Alert (wake word, timer, volume, wifi, power) | 52 | 7 |
| Development test tones | 44 | 36 |
| Assistant | 32 | 32 |
| Chirp (the eye noises) | 32 | 6 |
| Grunt (the vocal noises) | 31 | 3 |
| Purr and petting | 16 | 0 |
| Greeting | 12 | 1 |
| Scene | 8 | 6 |
| Attention | 7 | 2 |
| Cube | 5 | 0 |
| Sleep | 4 | 0 |
147 events are never fired by any stock animation or by the engine. Ignoring the test tones and the assistant earcons, that still leaves a decent pile. And the distribution is more lopsided than the table suggests: 101 events are used by exactly one clip, while a single curious-eyes chirp is fired by 380 of them.
The best of the unused:
- The procedural blink, squint and shift chirps — twenty recorded takes between them, and not one stock clip asks for any of it. The names suggest they were made for code-driven faces rather than canned animation, which is exactly what a styleable eye is.
- A real looping purr, used by nothing. It wants its stop event afterwards or it runs forever.
- The quieter, to-himself versions of the normal grunts — five takes each, barely used.
- Four escalating head-petting levels and four lift-high ones, one stock clip each. Played in sequence they are a proper “he settles into it”.
- Sleepy muttering, one clip each.
Two bugs this turned up in Ember’s own clips, both since fixed: one clip was asking for an event with no recording behind it and playing nothing, and three were starting a loop and never stopping it.
Ember’s own clips
Section titled “Ember’s own clips”Thirteen new clips, built on under-used events and nearly all using the weighted random pick so they do not repeat themselves: the four petting levels in sequence; the looping purr with its level raised twice and then stopped; lift tickling at a random level; a good-morning greeting; goodbye weighted against sad-goodbye; a fist bump; the face-scan loop and its stop; the three unused procedural chirps; the quiet grunts; a look-at-device, gaze-scan and touch reaction; sleepy muttering; a cube search ping; and the concentrate loop, properly stopped.
They are staged only. They reach the robot the same way every other Ember clip does, through the install-animations route, and none of them has been installed.
The generator cross-checks every event it uses against the finished catalogue, so a wrong id or a silent event fails the build rather than the robot.
Ember’s own recordings
Section titled “Ember’s own recordings”Separate from all of the above, Ember can stream ordinary audio to the robot’s speaker. Those are the sound sets described in Modes and sound sets: plain 16 kHz mono WAV files, played through the SDK’s external audio playback, with no behaviour control taken so a reaction noise does not interrupt what he is doing.