9 size_t underscore = str.find(
'_');
10 if (underscore == std::string::npos) {
11 throw std::invalid_argument(
"Invalid format. Supply numberical format of nInputs_nOutpits like 25_2");
14 int inputs = std::stoi(str.substr(0, underscore));
15 int outputs = std::stoi(str.substr(underscore + 1));
16 return std::make_pair(inputs, outputs);
19Filter::Filter(
const std::shared_ptr<Node>& input,
const std::string& zindex_shifts)
28Filter::Filter(
const std::shared_ptr<Node>& input,
const std::vector<double>& a_coef,
const std::vector<double>& b_coef)
36 throw std::invalid_argument(
"IIR coefficients cannot be empty");
39 throw std::invalid_argument(
"First denominator coefficient (a[0]) cannot be zero");
45Filter::Filter(
const std::vector<double>& a_coef,
const std::vector<double>& b_coef)
46 :
Filter(nullptr, a_coef, b_coef)
76 for (
size_t i = 0; i < lookback; ++i) {
102 if (new_coefs.empty()) {
103 throw std::invalid_argument(
"Denominator coefficients cannot be empty");
105 if (new_coefs[0] == 0.0F) {
106 throw std::invalid_argument(
"First denominator coefficient (a[0]) cannot be zero");
119 if (new_coefs.empty()) {
120 throw std::invalid_argument(
"Numerator coefficients cannot be empty");
133 std::vector<double> samples = source->process_batch(length);
140 std::vector<double> samples =
m_input_node->process_batch(length);
143 std::cerr <<
"No input node set for Filter. Use Filter::setInputNode() to set an input node.\n Alternatively, use Filter::updateCoefficientsFromNode() to specify a different source node.\n";
149 if (index > buffer.size()) {
150 buffer.resize(index + 1, 1.F);
152 buffer.at(index) = value;
190 double max_coef = 0.0;
192 max_coef = std::max(max_coef, std::abs(coef));
195 if (max_coef > 0.0) {
206 double omega = 2.0 * M_PI * frequency / sample_rate;
207 std::complex<double> z = std::exp(std::complex<double>(0, omega));
209 std::complex<double> numerator = 0.0;
210 for (
size_t i = 0; i <
m_coef_b.size(); ++i) {
211 numerator +=
m_coef_b[i] * std::pow(z, -
static_cast<int>(i));
214 std::complex<double> denominator = 0.0;
215 for (
size_t i = 0; i <
m_coef_a.size(); ++i) {
216 denominator +=
m_coef_a[i] * std::pow(z, -
static_cast<int>(i));
219 return numerator / denominator;
234 std::vector<double> output(num_samples);
235 for (
unsigned int i = 0; i < num_samples; ++i) {
void add_coef_internal(uint64_t index, double value, std::vector< double > &buffer)
Modifies a specific coefficient in a coefficient buffer.
void add_coef(int index, double value, coefficients type=coefficients::ALL)
Modifies a specific coefficient.
std::vector< double > process_batch(unsigned int num_samples) override
Calculates the phase response at a specific frequency.
virtual void reset()
Resets the filter's internal state.
void build_input_history(double current_sample)
Builds input history from external context or internal accumulation.
std::vector< double > m_coef_b
Feedforward (numerator) coefficients.
std::vector< double > m_output_history
Buffer storing previous output samples.
virtual void update_outputs(double current_sample)
Updates the output history buffer with a new sample.
std::shared_ptr< Node > m_input_node
The most recent sample value generated by this oscillator.
void update_coef_from_input(int length, coefficients type=coefficients::ALL)
Updates coefficients from the filter's own input.
virtual void initialize_shift_buffers()
Initializes the input and output history buffers.
std::complex< double > get_frequency_response(double frequency, double sample_rate) const
Calculates the complex frequency response at a specific frequency.
std::unique_ptr< NodeContext > create_context(double value) override
Creates a filter-specific context object.
void set_coefs(const std::vector< double > &new_coefs, coefficients type=coefficients::ALL)
Updates filter coefficients.
Filter(const std::shared_ptr< Node > &input, const std::string &zindex_shifts)
Constructor using string-based filter configuration.
bool m_use_external_input_context
void normalize_coefficients(coefficients type=coefficients::ALL)
Normalizes filter coefficients.
void setACoefficients(const std::vector< double > &new_coefs)
Updates the feedback (denominator) coefficients.
std::vector< double > m_input_history
Buffer storing previous input samples.
void setBCoefficients(const std::vector< double > &new_coefs)
Updates the feedforward (numerator) coefficients.
virtual void update_inputs(double current_sample)
Updates the input history buffer with a new sample.
void update_coefs_from_node(int length, const std::shared_ptr< Node > &source, coefficients type=coefficients::ALL)
Updates coefficients from another node's output.
void notify_tick(double value) override
Notifies all registered callbacks with the current filter context.
std::pair< int, int > m_shift_config
Configuration for input and output buffer sizes.
std::span< double > m_external_input_context
External input context for input history.
double get_phase_response(double frequency, double sample_rate) const
Calculates the phase response at a specific frequency.
std::vector< double > m_coef_a
Feedback (denominator) coefficients.
double get_magnitude_response(double frequency, double sample_rate) const
Calculates the magnitude response at a specific frequency.
double process_sample(double input=0.) override=0
Processes a single sample through the filter.
Base class for computational signal transformers implementing difference equations.
std::vector< NodeHook > m_callbacks
Collection of standard callback functions.
std::vector< std::pair< NodeHook, NodeCondition > > m_conditional_callbacks
Collection of conditional callback functions with their predicates.
bool m_gpu_compatible
Flag indicating if the node supports GPU processing This flag is set by derived classes to indicate w...
std::unique_ptr< NodeContext > m_last_context
The last context object created for callbacks.
std::span< const float > get_gpu_data_buffer() const
Provides access to the GPU data buffer.
std::pair< int, int > shift_parser(const std::string &str)
Parses a string representation of filter order into input/output shift configuration.