crates/veilvoice-audio/src/live.rs
veilvoice-audio · 859 lines · read the source here · or on GitHub
Live microphone scrambling.
Structure
Capture and playback run as two independent callbacks driven by the audio hardware, joined by a lock-free SPSC ring buffer. The de-identification runs inside the output callback, which is the shortest path: adding a worker thread would mean a second buffer and a second scheduling delay for no benefit, and veilvoice_core::Deidentifier::process is explicitly allocation-free and safe to call from an audio callback.
Rules the callbacks follow
An audio callback that blocks produces a dropout, so neither callback ever allocates, locks, or waits. Statistics are published through a mutex the callback only ever tries to take: if the UI thread happens to hold it, the update is skipped rather than the audio stalling.
Latency
Total latency is the input buffer, plus the ring backlog, plus the engine's one-frame group delay (~21 ms at the defaults), plus the output buffer. The ring is intentionally short, enough to absorb jitter between two clocks that are not synchronised, not enough to accumulate a delay the user would notice while speaking.
In plain words
This is live mode: your microphone in one end, a voice that is not yours out the other, fast enough to hold a conversation.
Sound arrives from the microphone in small pieces, and each one has to be dealt with before the next arrives. There is no room to be late. So the veiling happens on the same short path the sound is already travelling, with nothing queued up behind it and nothing that could pause to allocate memory or wait for another part of the program.
If the computer ever cannot keep up, that is counted and shown rather than hidden. A gap in the sound you can see explained is far better than one you cannot.
WHAT THIS FILE CONTAINS
859 lines defining 12 functions (6 public), 7 types and 1 constant. Everything below is read out of the source, so it cannot disagree with the code.
The types it owns.
enum Sideline 56 · Which side of the engine something happened to.struct Interferenceline 86 · Something that happened to the audio path while it was running.struct LiveStatsline 104 · A snapshot of what the live path is doing, safe to read from the UI.struct Keepingline 133 · Which sides of the engine a session keeps.struct Keptline 156 · The recorders a session was asked for, one per side of Keeping.struct LiveSessionline 164 · A running live-scramble session.struct Sharedline 172
What happens when it runs. These are the ways in: public, and nothing else in this file calls them, so they are what an outside caller reaches first.
Side::wordline 65 · The word for this side, as a person reading a warning would meet it.Keeping::is_anythingline 144 · Whether anything at all is being kept.LiveSession::startline 410 · Start scrambling from input into output.
reachesstart_recording,agree_on_a_rate,agree_on_a_rate_for,at_rate,input_ranges,rate_they_agree_onLiveSession::statsline 624 · Read the current statistics, resetting the peak meters.LiveSession::interferenceline 643 · What the platform last reported about either stream.
WHAT CALLS WHAT
The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.
The same graph as Mermaid source
%%{init: {"theme":"base","themeVariables":{"background":"#1a1b26","primaryColor":"#1f2335","primaryTextColor":"#c0caf5","primaryBorderColor":"#7aa2f7","secondaryColor":"#16161e","tertiaryColor":"#16161e","lineColor":"#737aa2","textColor":"#c0caf5","mainBkg":"#1f2335","nodeBorder":"#7aa2f7","clusterBkg":"#16161e","clusterBorder":"#2f3549","fontFamily":"ui-monospace, SFMono-Regular, Consolas, monospace","fontSize":"14px"}}}%%
flowchart TD
n_word(["Side::word<br/>line 65"])
n_is_anything(["Keeping::is_anything<br/>line 144"])
n_report["Shared::report<br/>line 190"]
n_rate_they_agree_on["rate_they_agree_on<br/>line 223"]
n_input_ranges["input_ranges<br/>line 255"]
n_at_rate["at_rate<br/>line 270"]
n_agree_on_a_rate["agree_on_a_rate<br/>line 301"]
n_agree_on_a_rate_for["agree_on_a_rate_for<br/>line 315"]
n_start(["LiveSession::start<br/>line 410"])
n_start_recording["LiveSession::start_recording<br/>line 452"]
n_stats(["LiveSession::stats<br/>line 624"])
n_interference(["LiveSession::interference<br/>line 643"])
n_agree_on_a_rate --> n_agree_on_a_rate_for
n_agree_on_a_rate_for --> n_at_rate
n_agree_on_a_rate_for --> n_input_ranges
n_agree_on_a_rate_for --> n_rate_they_agree_on
n_start --> n_start_recording
n_start_recording --> n_agree_on_a_rate
click n_word href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L65" "open the source"
click n_is_anything href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L144" "open the source"
click n_report href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L190" "open the source"
click n_rate_they_agree_on href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L223" "open the source"
click n_input_ranges href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L255" "open the source"
click n_at_rate href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L270" "open the source"
click n_agree_on_a_rate href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L301" "open the source"
click n_agree_on_a_rate_for href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L315" "open the source"
click n_start href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L410" "open the source"
click n_start_recording href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L452" "open the source"
click n_stats href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L624" "open the source"
click n_interference href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/live.rs#L643" "open the source"
classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
class n_word,n_is_anything,n_start,n_stats,n_interference entry
classDef api fill:#1f2335,stroke:#7dcfff,color:#c0caf5
class n_start_recording api
classDef helper fill:#1f2335,stroke:#bb9af7,color:#c0caf5
class n_report,n_rate_they_agree_on,n_input_ranges,n_at_rate,n_agree_on_a_rate,n_agree_on_a_rate_for helper
This site loads no third-party script, so it cannot run Mermaid; the diagram above is the same nodes and edges drawn by the generator instead. GitHub renders the source below directly.
ITEMS
| Item | Line | Documentation |
|---|---|---|
RING_MILLIS pub(crate) const | 52 | How much jitter the ring absorbs before it starts dropping samples. |
Side pub enum | 56 | Which side of the engine something happened to. |
Side::word pub fn | 65 | The word for this side, as a person reading a warning would meet it. |
Interference pub struct | 86 | Something that happened to the audio path while it was running. |
LiveStats pub struct | 104 | A snapshot of what the live path is doing, safe to read from the UI. |
Keeping pub struct | 133 | Which sides of the engine a session keeps. |
Keeping::is_anything pub fn | 144 | Whether anything at all is being kept. |
Kept pub struct | 156 | The recorders a session was asked for, one per side of Keeping. |
LiveSession pub struct | 164 | A running live-scramble session. |
Shared struct | 172 | |
Shared::report fn | 190 | Record what the platform said about a stream. |
rate_they_agree_on fn | 223 | Which sample rate a set of devices can all run at, if any. |
input_ranges pub(crate) fn | 255 | The ranges a device reports, as plain numbers. |
at_rate fn | 270 | One of a device's configurations at rate, preferring f32. |
agree_on_a_rate fn | 301 | A microphone and an output, configured to one rate. |
agree_on_a_rate_for pub(crate) fn | 315 | The same, for any number of microphones. |
LiveSession::start pub fn | 410 | Start scrambling from input into output. |
LiveSession::start_recording pub fn | 452 | Start scrambling, keeping the sides of it Keeping asks for. |
LiveSession::stats pub fn | 624 | Read the current statistics, resetting the peak meters. |
LiveSession::interference pub fn | 643 | What the platform last reported about either stream. |