36 constexpr RealType sinc(
const RealType x)
noexcept {
return x == 0 ? 1.0 : std::sin(x *
PI) / (x *
PI); }
45 std::vector<RealType> blackmanFir(
const RealType cutoff,
unsigned& filtLength)
noexcept
48 std::vector<RealType> coeffs(filtLength);
54 std::ranges::for_each(coeffs,
55 [cutoff, n, pi_n, i = 0u](
RealType& coeff)
mutable
57 const RealType sinc_val = sinc(cutoff * (i - n));
60 coeff = sinc_val * window;
70 void upsample(
const std::span<const ComplexType> in,
const unsigned size, std::span<ComplexType> out)
77 const auto coeffs = blackmanFir(1 /
static_cast<RealType>(ratio), filt_length);
79 std::vector tmp(size * ratio + filt_length,
ComplexType{0.0, 0.0});
81 for (
unsigned i = 0; i < size; ++i)
83 tmp[i * ratio] = in[i];
89 const auto delay = filt_length / 2 - 1;
90 std::ranges::copy_n(tmp.begin() + delay, size * ratio, out.begin());
93 std::vector<ComplexType>
downsample(std::span<const ComplexType> in)
97 throw std::invalid_argument(
"Input span is empty in Downsample");
102 unsigned filt_length = 0;
103 const auto coeffs = blackmanFir(1 /
static_cast<RealType>(ratio), filt_length);
105 std::vector tmp(in.size() + filt_length,
ComplexType{0, 0});
107 std::ranges::copy(in, tmp.begin());
112 const auto downsampled_size = in.size() / ratio;
113 std::vector<ComplexType> out(downsampled_size);
114 for (
unsigned i = 0; i < downsampled_size; ++i)
116 out[i] = tmp[i * ratio + filt_length / 2] /
static_cast<RealType>(ratio);
123 _a(denCoeffs, denCoeffs + order), _b(numCoeffs, numCoeffs + order), _w(order, 0.0), _order(order)
129 std::ranges::rotate(_w, _w.end() - 1);
133 for (
unsigned j = 1; j < _order; ++j)
135 _w[0] -= _a[j] * _w[j];
138 return std::inner_product(_b.begin(), _b.end(), _w.begin(), 0.0);
143 for (
auto& sample : samples)
145 std::ranges::rotate(_w, _w.end() - 1);
149 for (
unsigned j = 1; j < _order; ++j)
151 _w[0] -= _a[j] * _w[j];
154 sample = std::inner_product(_b.begin(), _b.end(), _w.begin(), 0.0);
162 for (
auto& sample : samples)
167 result = std::transform_reduce(line.rbegin(), line.rend(), _filter.begin(),
ComplexType{0.0, 0.0},
168 std::plus<ComplexType>{},
173 std::rotate(line.rbegin(), line.rbegin() + 1, line.rend());
180 constexpr std::array den_coeffs = {1.0,
193 constexpr std::array num_coeffs = {2.7301694322809e-06, -1.8508123430239e-05, 5.75739466753894e-05,
194 -0.000104348734423658, 0.000111949190289715, -4.9384188225528e-05,
195 -4.9384188225522e-05, 0.00011194919028971, -0.000104348734423656,
196 5.75739466753884e-05, -1.85081234302388e-05, 2.73016943228086e-06};
198 _filter = std::make_unique<IirFilter>(den_coeffs.data(), num_coeffs.data(), den_coeffs.size());
203 if (out.size() != 10)
205 throw std::invalid_argument(
"Output span must have a size of 10.");
208 std::fill(out.begin() + 1, out.end(), 0);
209 _filter->filter(out);
void upsample(RealType sample, std::span< RealType > out) const
Upsamples a single sample.
Implements a Finite Impulse Response (FIR) filter.
RealType filter(RealType) override
Filters a single sample.
IirFilter(const RealType *denCoeffs, const RealType *numCoeffs, unsigned order) noexcept
Constructs an IIR filter with given numerator and denominator coefficients and order.
RealType filter(RealType sample) noexcept override
Filters a single sample.
double RealType
Type for real numbers.
std::complex< RealType > ComplexType
Type for complex numbers.
constexpr RealType PI
Mathematical constant π (pi).
constexpr RealType BLACKMAN_A2
constexpr RealType BLACKMAN_A1
constexpr RealType BLACKMAN_A0
Header file for Digital Signal Processing (DSP) filters and upsampling/downsampling functionality.
void upsample(const std::span< const ComplexType > in, const unsigned size, std::span< ComplexType > out)
Upsamples a signal by a given ratio.
std::vector< ComplexType > downsample(std::span< const ComplexType > in)
Downsamples a signal by a given ratio.
unsigned oversampleRatio() noexcept
Get the oversampling ratio.
unsigned renderFilterLength() noexcept
Get the render filter length.
Defines the Parameters struct and provides methods for managing simulation parameters.