From 4cb83acddbe154312b74d2d63985ac1100bad7c5 Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Mon, 28 Nov 2022 20:16:46 +0100 Subject: Initial --- lib/filter.h | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 lib/filter.h (limited to 'lib/filter.h') diff --git a/lib/filter.h b/lib/filter.h new file mode 100644 index 0000000..b6ca66e --- /dev/null +++ b/lib/filter.h @@ -0,0 +1,181 @@ +/* Copyright 2012 Dietrich Epp */ +#pragma once +#include "types.h" +#include "param.h" + +#include + +/* Bits used for interpolating between two filters. The scalar + implementation supports up to 16 bits, but the SIMD implementations + generally only support 14 so the values can fit in a signed 16-bit + word. We bring all implementations to the same accuracy in order + to ensure that all implementations produce the same results. */ +#define INTERP_BITS 14 + +/* + Filter types +*/ +enum lfr_ftype_t { + LFR_FTYPE_S16, + LFR_FTYPE_F32 +}; + +/* + Array of FIR filters. + + Let N=2^log2nfilt, M=nsamp. + + This is an array of N+1 filters, 0..N, with each filter M samples + long. Filter number I will be centered on the sample with offset: + + floor(M/2) + I/N + + This means that filter N will be a copy of filter 0, except shifted + to the right by one sample. This extra filter makes the + interpolation code simpler. +*/ + + +/* + Information queries that a filter responds to. Each query gives an + integer or floating point result, automatically cast to the type + requested. +*/ +enum LFR_INFO_TYPE { + /* + The size of the filter, also known as the filter's order. This + does not include oversampling. The resampler will read this + many samples, starting with the current position (rounded down), + whenever it calculates a sample. + + In other words, this is the amount of overlap needed when + resampling consecutive buffers. + */ + LFR_INFO_SIZE, + + /* + Filter delay. Note that lfr_filter_delay returns a fixed point + number and is usually preferable. + */ + LFR_INFO_DELAY, + + /* + The is the number of bytes used by filter coefficients. + */ + LFR_INFO_MEMSIZE, + + /* + The normalized pass frequency the filter was designed with. + */ + LFR_INFO_FPASS, + + /* + The normalized stop frequency the filter was designed with. + */ + LFR_INFO_FSTOP, + + /* + The stopband attenuation, in dB, that the filter was designed + with. + */ + LFR_INFO_ATTEN, + + LFR_INFO_COUNT +}; + +/* + * A filter for resampling audio. + */ +struct lfr_filter { + /* + FIR filter coefficient data type. + */ + lfr_ftype_t type; + + /* + FIR filter data. + */ + std::vector data; + + /* + Length of each filter, in samples. This is chosen to make each + filter size a multiple of the SIMD register size. Most SIMD + implementations today use 16 byte registers, so this will + usually be a multiple of 8 or 4, depending on the coefficient + type. + */ + int nsamp; + + /* + Base 2 logarithm of the number of different filters. There is + always an additional filter at the end of the filter array to + simplify interpolation, this extra filter is a copy of the first + filter shifted right by one sample. + */ + int log2nfilt; + + /* + Filter delay. Filters are causal, so this should be + non-negative. + */ + lfr_fixed_t delay; + + /* + Design parameters of the filter. + */ + double f_pass, f_stop, atten; + + lfr_filter(lfr_param& param); + int geti(LFR_INFO_TYPE iname, bool convert = true) const; + double getf(LFR_INFO_TYPE iname, bool convert = true) const; + + +/* + Resample an audio buffer. Note that this function may need to + create intermediate buffers if there is no function which can + directly operate on the input and output formats. No intermediate + buffers will be necessary if the following conditions are met: + + - Input and output formats are identical. + + - Sample format is either S16_NATIVE or F32_NATIVE. + + - The number of channels is either 1 (mono) or 2 (stereo). + + pos: Current position relative to the start of the input buffer, + expressed as a 32.32 fixed point number. On return, this will + contain the updated position. Positions outside the input buffer + are acceptable, it will be treated as if the input buffer were + padded with an unlimited number of zeroes on either side. + + inv_ratio: Inverse of the resampling ratio, expressed as a 32.32 + fixed point number. This number is equal to the input sample rate + divided by the output sample rate. + + dither: State of the PRNG used for dithering. + + nchan: Number of interleaved channels. + + out, in: Input and output buffers. The buffers are not permitted to + alias each other. + + outlen, inlen: Length of buffers, in frames. Note that the length + type is 'int' instead of 'size_t'; this matches the precision of + buffer positions. + + outfmt, infmt: Format of input and output buffers. + + filter: A suitable low-pass filter for resampling at the given + ratio. +*/ + void resample( + lfr_fixed_t *pos, lfr_fixed_t inv_ratio, + unsigned *dither, int nchan, + void *out, lfr_fmt_t outfmt, int outlen, + const void *in, lfr_fmt_t infmt, int inlen); +private: + /* + Create a Kaiser-windowed sinc filter. + */ + void setup_window(double cutoff, double beta); +}; \ No newline at end of file -- cgit v1.2.3-54-g00ecf