window.rs

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.

  • hann line 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 line 73 · Overlap-add normalisation for a window applied on both analysis and synthesis at the given hop.

WHAT CALLS WHAT

hann line 57 ola_gain line 73 entry: a way in: public, and nothing in this file calls it dashed: a call that goes back up, or across a wrapped rank 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 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

ItemLineDocumentation
hann pub fn57Periodic 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 fn73Overlap-add normalisation for a window applied on both analysis and synthesis at the given hop.