Vixen
02b45cc4
csharp
public static class SincTable

A windowed-sinc interpolator, precomputed once and shared by every voice.

No guide page documents this yet — the page shows what the code says about itself.

Remarks

Linear interpolation is a filter, and a bad one. Reading between two samples with a straight line is a convolution with a triangle, whose response falls away from the first sample and never reaches zero — so it dulls what it keeps and lets through everything it should have removed. Pitched down by an octave it is barely audible; pitched up by one it folds the top half of the spectrum back over the music as inharmonic noise, which is the gritty edge every cheap sampler has.

The right filter is a sinc, and the whole art is where to cut it off. An infinite sinc is a perfect low-pass and cannot be computed; truncating it rings. Windowing the truncation trades ripple for transition width, and a Blackman window over sixteen taps is about eighty decibels of stopband for a transition of a couple of per cent — well past audibility, and sixteen multiply-accumulates a sample.

Polyphase, because the phase is not arbitrary. The filter is evaluated at a fractional position between samples, and precomputing it at a few hundred positions turns a transcendental per tap per sample into a table lookup. The residual error from snapping to the nearest phase is the same order as the window's own ripple, so a finer table would buy nothing.

Static, immutable, and half a megabyte. One table serves every voice in the process — it depends on nothing about the device or the sound — so it is built on first use and never again. First use means the first voice that is actually pitched: a ratio of one never reaches here.

Fields and properties (3)

  • public const int Taps

    How many samples each output is made from.

  • public const int Phases

    How many fractional positions between two samples the filter is precomputed at.

  • public const int Bands

    How many cutoffs it is precomputed at, half an octave apart.

Methods (3)

  • public static ReadOnlySpan<float> Window(double fraction, double ratio = 1)

    The filter for a fractional position and a playback ratio.

  • public static int BandFor(double ratio)

    Which band a playback ratio needs.

  • public static float Cutoff(int band)

    The cutoff a band filters at, as a fraction of Nyquist.

Used by (2)

  • ResamplerTestsVixen.Audio.Tests
  • VoiceVixen.Audio