crates/veilvoice-core/src/window.rs
veilvoice-core · 101 lines · read the source here · or on GitHub
Analysis and synthesis windowing, and the one constant that keeps overlap-add honest.
Two functions, both small, both easy to get subtly wrong in ways that do not look wrong.
Why the periodic Hann window
There are two Hann windows and they differ by one sample. The symmetric variant (cos(2*pi*i / (n-1))) is the right one for designing filters, and it is what most textbook snippets show. The periodic variant (cos(2*pi*i / n), which is what hann returns) is the right one for an STFT, because it is the one that tiles: shifted copies of it sum to a constant, and the symmetric one does not quite.
Using the wrong one does not produce an obvious failure. It produces a faint periodic amplitude ripple at the hop rate -- a quiet buzz that sounds like a codec artefact rather than like a bug, and that nothing in a test suite notices unless the test is looking for exactly it.
Why the gain is computed rather than assumed
VeilVoice windows twice: once on analysis and once on synthesis. That is deliberate -- a synthesis window suppresses the discontinuities that modifying a spectrum introduces at frame edges, and this crate modifies every spectrum it touches. The cost is that the reconstruction gain is no longer the familiar Constant-Overlap-Add value, it is sum(w^2) / hop.
ola_gain returns the reciprocal of that, so a caller multiplies rather than divides -- one multiply per sample in a hot loop instead of one divide. It is derived from the window actually in use rather than hardcoded for a particular size and overlap, so changing either cannot silently change the output level.
The zero-length and single-sample cases are handled explicitly, and the degenerate sum(w^2) == 0 returns unity rather than infinity: this is a gain that gets multiplied into every output sample, and one non-finite value entering an engine with persistent state is permanent.
In plain words
Two small pieces of arithmetic that decide how the overlapping slices of sound are faded in and out.
They are short and they are easy to get subtly wrong in a way that does not look wrong: the sound still comes out, and it quietly has a faint hum through it, or the volume ripples. So both are written here once, with the reason, and checked.
WHAT THIS FILE CONTAINS
101 lines defining 2 functions (2 public), 0 types and 0 constants. Everything below is read out of the source, so it cannot disagree with the code.
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.
hannline 57 · Periodic Hann window of length n (the correct variant for STFT overlap-add, as opposed to the symmetric variant used for filter design).ola_gainline 73 · Overlap-add normalisation for a window applied on both analysis and synthesis at the given hop.
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_hann(["hann<br/>line 57"])
n_ola_gain(["ola_gain<br/>line 73"])
click n_hann href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-core/src/window.rs#L57" "open the source"
click n_ola_gain href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-core/src/window.rs#L73" "open the source"
classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
class n_hann,n_ola_gain entry
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 |
|---|---|---|
hann pub fn | 57 | Periodic Hann window of length n (the correct variant for STFT overlap-add, as opposed to the symmetric variant used for filter design). |
ola_gain pub fn | 73 | Overlap-add normalisation for a window applied on both analysis and synthesis at the given hop. |