38template <
typename SampleType =
float>
53 coefficients_ = std::move(coeffs);
54 reversed_.assign(coefficients_.rbegin(), coefficients_.rend());
55 const std::size_t taps = coefficients_.size();
56 history_.assign(taps == 0 ? 0 : (taps - 1) +
kBlockCapacity, SampleType{0});
57 head_ = taps == 0 ? 0 : taps - 1;
61 int order()
const {
return static_cast<int>(coefficients_.size()); }
70 const std::size_t taps = coefficients_.size();
73 if (head_ == history_.size())
75 history_[head_] = input;
76 const SampleType* window = history_.data() + head_ + 1 - taps;
79 SampleType output = SampleType{0};
80 for (std::size_t k = 0; k < taps; ++k)
81 output += window[k] * reversed_[k];
84 return pulp::simd::dot(window, reversed_.data(), taps);
88 void process(SampleType* data,
int num_samples) {
89 process(data, data, num_samples);
98 void process(
const SampleType* input, SampleType* output,
int num_samples) {
99 const std::size_t taps = coefficients_.size();
100 if (num_samples <= 0)
104 std::copy_n(input, num_samples, output);
107 const auto total =
static_cast<std::size_t
>(num_samples);
108 std::size_t done = 0;
109 while (done < total) {
110 if (head_ == history_.size())
112 const std::size_t count = std::min(history_.size() - head_, total - done);
113 std::copy_n(input + done, count, history_.data() + head_);
114 pulp::simd::correlate(history_.data() + head_ + 1 - taps, reversed_.data(),
115 output + done, count, taps);
123 std::fill(history_.begin(), history_.end(), SampleType{0.0f});
124 head_ = coefficients_.empty() ? 0 : coefficients_.size() - 1;
134 int num_taps, SampleType cutoff_hz, SampleType sample_rate) {
135 std::vector<SampleType> h(
static_cast<size_t>(num_taps));
136 SampleType fc = cutoff_hz / sample_rate;
137 int m = num_taps - 1;
138 constexpr SampleType pi = SampleType{3.14159265358979323846f};
140 for (
int i = 0;
i <= m; ++
i) {
141 SampleType n =
static_cast<SampleType
>(
i) -
142 static_cast<SampleType
>(m) / SampleType{2.0f};
143 if (std::abs(n) < SampleType{1e-6f}) {
144 h[
static_cast<size_t>(
i)] = SampleType{2.0f} * fc;
146 h[
static_cast<size_t>(
i)] =
147 std::sin(SampleType{2.0f} * pi * fc * n) / (pi * n);
150 SampleType w = SampleType{0.54f} -
152 std::cos(SampleType{2.0f} * pi *
static_cast<SampleType
>(
i) /
153 static_cast<SampleType
>(m));
154 h[
static_cast<size_t>(
i)] *= w;
158 SampleType sum = std::accumulate(h.begin(), h.end(), SampleType{0.0f});
159 if (sum > SampleType{0.0f}) {
160 for (
auto& v : h) v /= sum;
167 int num_taps, SampleType cutoff_hz, SampleType sample_rate) {
168 auto h =
lowpass(num_taps, cutoff_hz, sample_rate);
169 for (
auto& v : h) v = -v;
170 h[
static_cast<size_t>(num_taps / 2)] += SampleType{1.0f};
176 void compact() noexcept {
177 const std::size_t keep = coefficients_.size() - 1;
178 std::copy(history_.begin() +
static_cast<std::ptrdiff_t
>(head_ - keep),
179 history_.begin() +
static_cast<std::ptrdiff_t
>(head_), history_.begin());
183 std::vector<SampleType> coefficients_;
184 std::vector<SampleType> reversed_;
186 std::vector<SampleType> history_;
187 std::size_t head_ = 0;
FIR filter with arbitrary coefficients.
Definition fir_filter.hpp:39
int order() const
Get current coefficient count (filter order + 1).
Definition fir_filter.hpp:61
static std::vector< SampleType > highpass(int num_taps, SampleType cutoff_hz, SampleType sample_rate)
Generate highpass FIR coefficients using spectral inversion.
Definition fir_filter.hpp:166
static std::vector< SampleType > lowpass(int num_taps, SampleType cutoff_hz, SampleType sample_rate)
Generate lowpass FIR coefficients using windowed-sinc method.
Definition fir_filter.hpp:133
static constexpr std::size_t kBlockCapacity
Definition fir_filter.hpp:43
static constexpr std::size_t kInlineTaps
Definition fir_filter.hpp:47
void process(SampleType *data, int num_samples)
Process a buffer of samples in-place.
Definition fir_filter.hpp:88
SampleType process(SampleType input)
Process a single sample.
Definition fir_filter.hpp:69
const std::vector< SampleType > & coefficients() const noexcept
The taps in time order (h[0] multiplies the newest input).
Definition fir_filter.hpp:64
void reset()
Reset the internal delay buffer to zero.
Definition fir_filter.hpp:122
void set_coefficients(std::vector< SampleType > coeffs)
Set filter coefficients. The number of taps equals coefficients.size().
Definition fir_filter.hpp:52
void process(const SampleType *input, SampleType *output, int num_samples)
Process a buffer into a separate output buffer without an intermediate copy.
Definition fir_filter.hpp:98
Definition additive_bank.hpp:218
@ i
Definition formant_filter_bank.hpp:20
FirFilterT< double > FirFilter64
Definition fir_filter.hpp:191
FirFilterT< float > FirFilter
Definition fir_filter.hpp:190