pvx Mathematical Foundations

May 25, 2026 · View on GitHub

pvx logo

pvx Mathematical Foundations

Generated from commit dff2a4f (commit date: 2026-04-21T21:20:38-04:00).

This document explains the core signal-processing equations used by pvx, with plain-English interpretation. All equations are written in GitHub-renderable LaTeX and are intended to render directly in normal GitHub Markdown view.

Notation

  • Analysis hop: HaH_a
  • Synthesis hop: HsH_s
  • FFT size: NN
  • Frame index: tt
  • Frequency-bin index: kk
  • Frame phase: ϕt[k]\phi_t[k]
  • Bin-center angular frequency: ωk=2πk/N\omega_k=2\pi k/N
  • Selected transform backend: m{fft,dft,czt,dct,dst,hartley}m \in \{\text{fft},\text{dft},\text{czt},\text{dct},\text{dst},\text{hartley}\}

1. STFT Analysis and Synthesis

Analysis transform:

Xt[k]=n=0N1x[n+tHa]w[n]ej2πkn/NX_t[k]=\sum_{n=0}^{N-1} x[n+tH_a]w[n]e^{-j2\pi kn/N}

Plain English: each frame t is windowed by w[n] and transformed into complex frequency bins k.

Weighted overlap-add synthesis:

x^[n]=tx^t[ntHs]w[ntHs]tw2[ntHs]+ε\hat{x}[n]=\frac{\sum_t \hat{x}_t[n-tH_s]w[n-tH_s]}{\sum_t w^2[n-tH_s]+\varepsilon}

Plain English: reconstructed frames are overlap-added, then normalized by accumulated window energy.

2. Transform Backend Families and Tradeoffs

pvx allows selecting the per-frame transform with --transform in STFT/ISTFT paths. The same overlap-add framework is used, but per-bin meaning and phase behavior differ by transform family.

Complex Fourier family (fft, dft):

Xt[k]=n=0N1xt[n]ej2πkn/N,xt[n]=1Nk=0N1Xt[k]ej2πkn/NX_t[k]=\sum_{n=0}^{N-1} x_t[n]e^{-j2\pi kn/N},\qquad x_t[n]=\frac{1}{N}\sum_{k=0}^{N-1}X_t[k]e^{j2\pi kn/N}

Chirp-Z (czt, Bluestein-style contour):

Xt[k]=n=0N1xt[n]AnWnkX_t[k]=\sum_{n=0}^{N-1}x_t[n]A^{-n}W^{nk}

With pvx defaults A=1A=1 and W=ej2π/NW=e^{-j2\pi/N}, CZT matches DFT samples but uses a different numerical path.

DCT-II / IDCT-II (dct):

Ct[k]=αkn=0N1xt[n]cos(πN(n+12)k)C_t[k]=\alpha_k\sum_{n=0}^{N-1}x_t[n]\cos\left(\frac{\pi}{N}(n+\tfrac{1}{2})k\right)

DST-II / IDST-II (dst):

St[k]=βkn=0N1xt[n]sin(πN(n+12)(k+1))S_t[k]=\beta_k\sum_{n=0}^{N-1}x_t[n]\sin\left(\frac{\pi}{N}(n+\tfrac{1}{2})(k+1)\right)

Discrete Hartley (hartley):

Ht[k]=n=0N1xt[n]cas(2πknN),cas(θ)=cos(θ)+sin(θ)H_t[k]=\sum_{n=0}^{N-1}x_t[n]\,\mathrm{cas}\left(\frac{2\pi kn}{N}\right),\quad \mathrm{cas}(\theta)=\cos(\theta)+\sin(\theta)
TransformStrengthsTradeoffsRecommended use cases
fftFastest common path, stable, native one-sided complex bins, best CUDA coverage.Needs careful window/hop tuning for extreme nonstationarity.Default for most time-stretch, pitch-shift, and batch processing.
dftCanonical Fourier definition, deterministic parity baseline versus FFT implementations.Usually slower than fft, little practical quality advantage in normal runs.Cross-checking, verification, or research comparisons.
cztUseful alternative numerical path for awkward frame sizes; can be robust for prime/non-power sizes.Requires SciPy; typically CPU-only and slower than FFT.Edge-case frame-size experiments and diagnostic reruns.
dctReal-valued compact basis with strong energy compaction for smooth envelopes.Loses explicit complex phase; less transparent for strict phase-coherent resynthesis.Spectral shaping, denoise-like creative processing, coefficient-domain experiments.
dstReal-valued odd-symmetry basis; emphasizes different boundary behavior than DCT.Same phase limitations as DCT; content-dependent coloration.Creative timbre variants and odd-symmetry analysis experiments.
hartleyReal transform using cas, often helpful for CPU-friendly exploratory analysis.Different bin semantics vs complex STFT; can alter artifact profile.Alternative real-basis phase-vocoder experiments and pedagogical comparisons.

Plain English: choose fft first, then move to other transforms when you specifically need different numerical behavior, basis structure, or artifact character.

Sample Transform Use Cases

pvx voc dialog.wav --transform fft --time-stretch 1.08 --transient-preserve --output-dir out
pvx voc test_tones.wav --transform dft --time-stretch 1.00 --output-dir out
pvx voc archival_take.wav --transform czt --n-fft 1536 --win-length 1536 --hop-size 384 --output-dir out
pvx voc strings.wav --transform dct --pitch-shift-cents -17 --soft-clip-level 0.94 --output-dir out
pvx voc percussion.wav --transform dst --time-stretch 0.92 --output-dir out
pvx voc synth.wav --transform hartley --phase-locking off --time-stretch 1.30 --output-dir out

3. Phase-Vocoder Frequency and Phase Update

Δϕt[k]=princarg(ϕt[k]ϕt1[k]ωkHa)\Delta\phi_t[k]=\mathrm{princarg}\left(\phi_t[k]-\phi_{t-1}[k]-\omega_kH_a\right) ω^t[k]=ωk+Δϕt[k]Ha\hat{\omega}_t[k]=\omega_k+\frac{\Delta\phi_t[k]}{H_a} ϕ^t[k]=ϕ^t1[k]+ω^t[k]Hs\hat{\phi}_t[k]=\hat{\phi}_{t-1}[k]+\hat{\omega}_t[k]H_s

Plain English: pvx estimates true per-bin frequency from wrapped phase deviation, then re-accumulates phase at the synthesis hop.

4. Time Stretch and Pitch Ratio

Pitch shift ratio from semitones/cents:

rpitch=2Δs/12=2Δc/1200r_{\text{pitch}}=2^{\Delta s/12}=2^{\Delta c/1200}

Plain English: semitone and cent controls map to the same multiplicative ratio.

5. Dynamic Control Interpolation (CSV/JSON)

When a numeric flag receives a CSV/JSON control track, pvx samples a control function u(t)u(t) over render time.

Polynomial mode fits a global polynomial of degree dd:

u(t)=i=0daiti,d=min(order,M1)u(t)=\sum_{i=0}^{d} a_i t^i,\qquad d=\min(\texttt{order}, M-1)

where MM is the number of control points. In command-line interface (CLI) usage, --order accepts any integer 1\ge 1. The effective degree is automatically capped to avoid over-specification when there are too few points.

Nearest/linear/cubic/exponential/S-curve are local interpolation modes; none is sample-and-hold (stairstep). exponential uses piecewise exponential easing and s_curve/smootherstep use Hermite S-shaped easing between adjacent control points. Legend used in each plot: blue solid line = interpolated control curve u(t)u(t), red dashed line = piecewise connection of control points, red circles labeled pip_i = original control points.

Interpolation modeCLI formExample plot
none (stairstep)--interp nonenone (stairstep)
nearest--interp nearestnearest
linear--interp linearlinear
cubic--interp cubiccubic
exponential--interp exponentialexponential
S-curve (smoothstep)--interp s_curveS-curve (smoothstep)
S-curve (smootherstep)--interp smootherstepS-curve (smootherstep)
polynomial order 1--interp polynomial --order 1polynomial order 1
polynomial order 2--interp polynomial --order 2polynomial order 2
polynomial order 3--interp polynomial --order 3polynomial order 3
polynomial order 5--interp polynomial --order 5polynomial order 5

6. Microtonal Retune Mapping

For a detected frequency ff, pvx scale-aware retuning chooses the nearest permitted scale target fscalef_{\text{scale}} and applies:

Δs=12log2(fscalef)\Delta s = 12\log_2\left(\frac{f_{\text{scale}}}{f}\right)

Plain English: each frame is shifted only as much as needed to land on the selected microtonal scale degree.

7. Loudness and Dynamics

LUFS target gain:

gLUFS=10(LtargetLin)/20,y[n]=gLUFSx[n]g_{\text{LUFS}}=10^{(L_{\text{target}}-L_{\text{in}})/20},\qquad y[n]=g_{\text{LUFS}}x[n]

Compressor gain law (conceptual):

g(x)={1,xT(T+(xT)/Rx),x>Tg(x)=\begin{cases} 1, & |x|\le T \\ \left(\frac{T+(|x|-T)/R}{|x|}\right), & |x|>T \end{cases}

Plain English: level is reduced above threshold TT by ratio RR, then makeup/loudness stages may be applied.

8. Spatial Coherence and Channel Alignment

Inter-channel phase difference:

Δϕij(k,t)=ϕi(k,t)ϕj(k,t)\Delta\phi_{ij}(k,t)=\phi_i(k,t)-\phi_j(k,t)

Phase-drift objective:

J=k,tΔϕijout(k,t)Δϕijin(k,t)J=\sum_{k,t}\left|\Delta\phi^{\text{out}}_{ij}(k,t)-\Delta\phi^{\text{in}}_{ij}(k,t)\right|

Channel delay estimate by phase-weighted cross-correlation:

τ=argmaxτF1{Xi(ω)Xj(ω)Xi(ω)Xj(ω)+ε}(τ)\tau^*=\arg\max_\tau\,\mathcal{F}^{-1}\left\{\frac{X_i(\omega)X_j^*(\omega)}{|X_i(\omega)X_j^*(\omega)|+\varepsilon}\right\}(\tau)

Plain English: pvx spatial modules prioritize channel coherence, stable image cues, and robust delay alignment for multichannel processing chains.

The plots below visualize core transfer functions and parameter curves used across pvx processing modules.

Function familyPlotWhy this matters
Pitch ratio from semitonesPitch ratio from semitonesr = 2^(semitones/12) conversion used by pitch-shift flags.
Pitch ratio from centsPitch ratio from centsr = 2^(cents/1200) conversion for microtonal cent controls.
Dynamics transfer functionsDynamics transfer functionsCompressor/expander/limiter conceptual transfer curves used in mastering stages.
Soft-clip transfer functionsSoft-clip transfer functionsShows tanh, arctan, and cubic soft clipping behavior.
Morph blend magnitude curvesMorph blend magnitude curvesCompares linear, geometric, product, max_mag, and min_mag blend behaviors.
Mask exponent responseMask exponent responseShows how --mask-exponent shapes cross-synthesis mask gain.
Phase mix to output anglePhase mix to output angleExample of complex-vector phase blending used by morph phase mix.

Attribution

See ATTRIBUTION.md.