crates/veilvoice-audio/src/io.rs
veilvoice-audio · 574 lines · read the source here · or on GitHub
Reading and writing audio files.
Decoding goes through symphonia, which is pure Rust and covers WAV, MP3, FLAC, OGG/Vorbis, MP4/AAC and friends without shelling out to a codec library. Writing is WAV only, on purpose: VeilVoice's job is to hand back audio that has not been degraded, and re-encoding to a lossy format after de-identification would throw away quality for no benefit. Callers who want MP3 can transcode with whatever they already trust.
A decoder is a parser, and this one reads files somebody else made
symphonia is the largest attacker-facing surface in this crate: it is handed whole files of a format VeilVoice does not itself define. It is pure Rust, which removes the memory-corruption class outright, but it does not remove panics -- and this workspace builds with panic = "abort", so a panic inside a decoder is not an error a caller can handle, it is the process ending.
That is why a pre-flight check runs before a file reaches the decoder, and why the honest position is recorded in the audit rather than glossed: decoding in a separate process is the only complete answer to "the next malformed file in a format we do not parse ourselves", and it is not built.
Writing is WAV only, and that is a decision
Re-encoding to a lossy format after de-identification would throw away quality for no privacy benefit -- the voiceprint is already gone, and what remains is the words, which is the part worth keeping intact.
In-memory encoding, so plaintext never reaches the disk
wav_bytes exists so a recording can be encoded and then sealed without ever being written in the clear. It has an awkward shape for a real reason: hound::WavWriter::finalize consumes the writer, so the encode has to borrow the cursor (WavWriter::new(&mut cursor, spec)) and read the bytes back through cursor.into_inner() after the writer has been dropped.
In plain words
This opens sound files and writes them back out.
It can read the usual formats, and it always writes plain WAV. That is deliberate: WAV throws nothing away. Saving as MP3 after the voice has been veiled would lose quality for no reason, and anybody who wants a smaller file can convert it afterwards with whatever they already use.
Opening a sound file means reading a file somebody else made, which is the part of any program most worth being careful in. A file that is damaged, or built on purpose to cause trouble, is refused with a reason rather than being allowed to bring the program down.
WHAT THIS FILE CONTAINS
574 lines defining 7 functions (6 public), 1 type and 1 constant. Everything below is read out of the source, so it cannot disagree with the code.
The types it owns.
struct Audioline 151 · Mono audio in memory.
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.
Audio::duration_secsline 160 · Duration in seconds.Audio::peakline 168 · Peak absolute sample value.loadline 179 · Decode any supported audio file to mono f32.
reachespreflight,read_up_tosave_wavline 328 · Write mono f32 audio to a 16-bit PCM WAV file.
reacheswav_bytes
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_preflight["preflight<br/>line 106"]
n_duration_secs(["Audio::duration_secs<br/>line 160"])
n_peak(["Audio::peak<br/>line 168"])
n_load(["load<br/>line 179"])
n_read_up_to["read_up_to<br/>line 287"]
n_wav_bytes["wav_bytes<br/>line 308"]
n_save_wav(["save_wav<br/>line 328"])
n_load --> n_preflight
n_load --> n_read_up_to
n_save_wav --> n_wav_bytes
click n_preflight href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/io.rs#L106" "open the source"
click n_duration_secs href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/io.rs#L160" "open the source"
click n_peak href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/io.rs#L168" "open the source"
click n_load href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/io.rs#L179" "open the source"
click n_read_up_to href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/io.rs#L287" "open the source"
click n_wav_bytes href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/io.rs#L308" "open the source"
click n_save_wav href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/io.rs#L328" "open the source"
classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
class n_duration_secs,n_peak,n_load,n_save_wav entry
classDef api fill:#1f2335,stroke:#7dcfff,color:#c0caf5
class n_preflight,n_wav_bytes api
classDef helper fill:#1f2335,stroke:#bb9af7,color:#c0caf5
class n_read_up_to 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 |
|---|---|---|
MAX_DECODED_SAMPLES pub const | 76 | The most decoded audio load will hold, in mono f32 samples. |
preflight pub fn | 106 | Reject a file whose own header carries a value that will crash the decoder, before the decoder is given the file. |
Audio pub struct | 151 | Mono audio in memory. |
Audio::duration_secs pub fn | 160 | Duration in seconds. |
Audio::peak pub fn | 168 | Peak absolute sample value. |
load pub fn | 179 | Decode any supported audio file to mono f32. |
read_up_to fn | 287 | Fill as much of buf as the file has, tolerating short reads. |
wav_bytes pub fn | 308 | Encode mono f32 audio as a 16-bit PCM WAV, in memory. |
save_wav pub fn | 328 | Write mono f32 audio to a 16-bit PCM WAV file. |