Proximity voice over the existing wire protocol (sim side) #32
Labels
No labels
agent
agent:ci
agent:done
agent:failed
agent:needs-input
agent:refined
agent:refining
agent:running
agent:shipped
agent:skip
autonomous
autopilot
driven
local
plan
proposal
qa
qa-gap
research
retro
ship
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jeroen/cartopolis#32
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The sim has text chat but no voice.
crates/simulator/src/chat.rs(85 lines) isalready the routing fabric spatial voice needs — it deals in pre-encoded frames
(
mpsc::UnboundedSender<Vec<u8>>,chat.rs:18), and already does the threedeliveries voice wants:
deliver_all,deliver_room,deliver_to(
chat.rs:59-81), with proximity radii already chosen (SAY_RADIUS_M = 50.0,SHOUT_RADIUS_M = 300.0,chat.rs:14-15).Decisively,
chat.rs:3-4records that proximity (Local) already encodes perrecipient because each frame carries its own
distance_m. Per-recipientframing is exactly what distance attenuation needs — the design decision is made,
implemented and documented, for text.
ADR-028:276-289 leans toward str0m and an embedded SFU. That is superseded: an
SFU reimplements
ChatHub's job while knowing nothing about avatar positions,which then have to be fed to it.
Approach
Server and protocol only — the half that needs no audio device and no browser
transport.
crates/core/src/protocol.rs—VoiceFrame(client→server) andVoiceData(server→client) at kinds 20/21, reusing
ChatScopeunchanged. One appendedProtocolRevision(13); the version is derived from it.crates/simulator/src/chat.rs— no generalising was needed:ChatHubalreadydeals in encoded
Vec<u8>, so its payload was always opaque. Addsdeliver_room_exceptand extractswithin_radius.crates/simulator/src/net.rs— handle the new kinds; voice rides the existingLinkand its existing auth. No second connection.Acceptance criteria
PROTOCOL_HISTORYgains exactly one row; the gapless-run test still passes.Localreaches only avatars withinSAY_RADIUS_M, andshoutextends that toSHOUT_RADIUS_M.distance_m, as text already does.crates/simulator/tests/chat.rspassesuntouched.
Added while building, each with a test:
confirmation).
One line to enable if that call is revisited.
VoiceFramecarriesseq, because the intended transport is unreliable,unordered datagrams where arrival order is not send order.
Verification
cargo test -p viberfox_core(20 passed) andcargo test -p viberfox_simulator(24 passed across lib + 3 integration targets), plus
cargo check -p viberfox.The radius is covered by a unit test in
chat::testsrather than through thesocket: both test clients authenticate as the same account and spawn co-located,
and
SimHandleexposes no way to move them apart.Nothing audible is verified. The agent container has no audio device and no
microphone.
pcm.nullexists in libasound but does not clock, so it cannotexercise callback pacing; a properly-clocked fake needs either a PulseAudio
null-sink in the agent image or
snd-aloopon the host.Out of scope
platform::audio), Opus, and acoustic echo cancellation.AEC decides whether DIY voice sounds professional;
getUserMediasupplies it onweb, native is ours. Separate ticket.
voice actually flowing on web, valuable alone, and its own ticket.
ChatHub'sMutex<HashMap>+ per-recipientframe.to_vec()is left as-is.Free at chat rates; wants measuring at 50 packets/sec × N listeners. That
measurement belongs in a note, not this ticket.