MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Filter.hpp
Go to the documentation of this file.
1#pragma once
2
4
6
7enum coefficients : uint8_t {
10 ALL
11};
12
13/**
14 * @brief Minimum permissible magnitude for the leading denominator coefficient
15 *
16 * Normalization divides by a[0]. Coefficients arriving from
17 * update_coefs_from_node carry arbitrary signal values, so a magnitude
18 * floor bounds the resulting gain rather than rejecting only exact zero.
19 */
20inline constexpr double k_min_leading_coef = 1e-6;
21
22/**
23 * @class FilterContext
24 * @brief Specialized context for filter node callbacks
25 *
26 * FilterContext extends the base NodeContext to provide filter-specific
27 * information to callbacks. It includes references to the filter's internal
28 * state, including input and output history buffers and coefficient vectors.
29 *
30 * This rich context enables callbacks to perform sophisticated analysis and
31 * monitoring of filter behavior, such as:
32 * - Detecting resonance conditions or instability
33 * - Analyzing filter response characteristics in real-time
34 * - Implementing adaptive processing based on filter state
35 * - Visualizing filter behavior through external interfaces
36 * - Recording filter state for later analysis or debugging
37 */
38class MAYAFLUX_API FilterContext : public NodeContext {
39public:
40 /**
41 * @brief Constructs a FilterContext with the current filter state
42 * @param value Current output sample value
43 * @param input_history Reference to the filter's input history buffer
44 * @param output_history Reference to the filter's output history buffer
45 * @param coefs_a Reference to the filter's feedback coefficients
46 * @param coefs_b Reference to the filter's feedforward coefficients
47 *
48 * Creates a context object that provides a complete snapshot of the
49 * filter's current state, including its most recent output value,
50 * history buffers, and coefficient vectors.
51 */
53 const std::vector<double>& input_history,
54 const std::vector<double>& output_history,
55 const std::vector<double>& coefs_a,
56 const std::vector<double>& coefs_b)
58 , input_history(input_history)
59 , output_history(output_history)
60 , coefs_a(coefs_a)
61 , coefs_b(coefs_b)
62 {
63 }
64
65 /**
66 * @brief Current input history buffer
67 *
68 * Contains the most recent input samples processed by the filter,
69 * with the newest sample at index 0. The size of this buffer depends
70 * on the filter's feedforward path configuration.
71 */
72 const std::vector<double>& input_history;
73
74 /**
75 * @brief Current output history buffer
76 *
77 * Contains the most recent output samples processed by the filter,
78 * with the newest sample at index 0. The size of this buffer depends
79 * on the filter's feedback path configuration.
80 */
81 const std::vector<double>& output_history;
82
83 /**
84 * @brief Current coefficients for input
85 */
86 const std::vector<double>& coefs_a;
87
88 /**
89 * @brief Current coefficients for output
90 */
91 const std::vector<double>& coefs_b;
92};
93
94/**
95 * @class FilterContextGpu
96 * @brief GPU-augmented filter context for callbacks
97 *
98 * Extends FilterContext to include GPU-uploadable data, allowing
99 * callbacks to access both CPU-side filter state and GPU-resident
100 * data for advanced processing and visualization.
101 */
102class MAYAFLUX_API FilterContextGpu : public FilterContext, public GpuVectorData {
103public:
105 const std::vector<double>& input_history,
106 const std::vector<double>& output_history,
107 const std::vector<double>& coefs_a,
108 const std::vector<double>& coefs_b,
109 std::span<const float> gpu_data)
110 : FilterContext(value, input_history, output_history, coefs_a, coefs_b)
111 , GpuVectorData(gpu_data)
112 {
113 }
114
115 friend class Filter;
116
117 std::vector<float> gpu_float_buffer;
118};
119
120/**
121 * @class Filter
122 * @brief Base class for computational signal transformers implementing difference equations
123 *
124 * The Filter class provides a comprehensive framework for implementing digital
125 * transformations based on difference equations. It transcends traditional audio
126 * filtering concepts, offering a flexible foundation for:
127 *
128 * - Complex resonant systems for generative synthesis
129 * - Computational physical modeling components
130 * - Recursive signal transformation algorithms
131 * - Data-driven transformation design from frequency responses
132 * - Dynamic coefficient modulation for emergent behaviors
133 *
134 * At its core, the Filter implements the general difference equation:
135 * y[n] = (b₀x[n] + b₁x[n-1] + ... + bₘx[n-m]) - (a₁y[n-1] + ... + aₙy[n-n])
136 *
137 * Where:
138 * - x[n] are input values
139 * - y[n] are output values
140 * - b coefficients apply to input values (feedforward)
141 * - a coefficients apply to previous output values (feedback)
142 *
143 * This mathematical structure can represent virtually any linear time-invariant system,
144 * making it a powerful tool for signal transformation across domains. The same
145 * equations can process audio, control data, or even be applied to visual or
146 * physical simulation parameters.
147 */
148class MAYAFLUX_API Filter : public Node {
149public:
150 /**
151 * @brief Constructor using explicit coefficient vectors
152 * @param input Source node providing input samples
153 * @param a_coef Feedback (denominator) coefficients
154 * @param b_coef Feedforward (numerator) coefficients
155 *
156 * Creates a filter with the specified input node and coefficient vectors.
157 * This allows direct specification of filter coefficients for precise
158 * control over filter behavior.
159 */
160 Filter(const std::shared_ptr<Node>& input, const std::vector<double>& a_coef, const std::vector<double>& b_coef);
161
162 /**
163 * @brief Constructor using explicit coefficient vectors (no input node)
164 * @param a_coef Feedback (denominator) coefficients
165 * @param b_coef Feedforward (numerator) coefficients
166 *
167 * Creates a filter with the specified coefficient vectors but no input node.
168 * This can be used in scenarios where the filter operates on external data
169 * or is part of a larger processing chain.
170 */
171 Filter(const std::vector<double>& a_coef, const std::vector<double>& b_coef);
172
173 /**
174 * @brief Virtual destructor
175 */
176 ~Filter() override = default;
177
178 /**
179 * @brief Gets the current processing latency of the filter
180 * @return Latency in samples
181 *
182 * The latency is determined by the maximum of the input and output
183 * buffer sizes, representing how many samples of delay the filter introduces.
184 */
185 [[nodiscard]] inline int get_current_latency() const
186 {
187 return static_cast<int>(std::max(m_coef_b.size(), m_coef_a.size())) - 1;
188 }
189
190 /**
191 * @brief Updates filter coefficients
192 * @param new_coefs New coefficient values
193 * @param type Which set of coefficients to update (input, output, or both)
194 *
195 * Provides a flexible way to update filter coefficients, allowing
196 * dynamic modification of filter characteristics during processing.
197 */
198 void set_coefs(const std::vector<double>& new_coefs, coefficients type = coefficients::ALL);
199
200 /**
201 * @brief Updates coefficients from another node's output
202 * @param length Number of coefficients to update
203 * @param source Node providing coefficient values
204 * @param type Which set of coefficients to update (input, output, or both)
205 *
206 * Enables cross-domain interaction by deriving transformation coefficients from
207 * another node's output. This creates dynamic relationships between different
208 * parts of the computational graph, allowing one signal path to influence
209 * the behavior of another - perfect for generative systems where parameters
210 * evolve based on the system's own output.
211 */
212 void update_coefs_from_node(int length, const std::shared_ptr<Node>& source, coefficients type = coefficients::ALL);
213
214 /**
215 * @brief Updates coefficients from the filter's own input
216 * @param length Number of coefficients to update
217 * @param type Which set of coefficients to update (input, output, or both)
218 *
219 * Creates a self-modifying transformation where the input signal itself
220 * influences the transformation characteristics. This enables complex
221 * emergent behaviors and feedback systems where the signal's own properties
222 * determine how it will be processed, leading to evolving, non-linear responses.
223 */
224 void update_coef_from_input(int length, coefficients type = coefficients::ALL);
225
226 /**
227 * @brief Modifies a specific coefficient
228 * @param index Index of the coefficient to modify
229 * @param value New value for the coefficient
230 * @param type Which set of coefficients to update (input, output, or both)
231 *
232 * Allows precise control over individual coefficients, useful for
233 * fine-tuning filter behavior or implementing parameter automation.
234 */
235 void add_coef(int index, double value, coefficients type = coefficients::ALL);
236
237 /**
238 * @brief Mutable view of the feedback taps, excluding a[0]
239 *
240 * a[0] is held at 1.0 by setACoefficients and is not addressable here:
241 * index 0 of the returned span is a[1]. The span has fixed extent, so
242 * coefficient count changes remain the province of setACoefficients.
243 *
244 * Edits are visible to the recursion immediately and are not atomic with
245 * respect to a sample in flight. A sweep requiring sample-accurate
246 * coefficient changes should drive update_coefs_from_node instead.
247 */
248 [[nodiscard]] inline std::span<double> edit_feedback_coefs()
249 {
250 return std::span<double>(m_coef_a).subspan(1);
251 }
252
253 /**
254 * @brief Mutable view of the feedforward coefficients
255 *
256 * Carries no invariant; every element is freely assignable. Fixed extent,
257 * with the same non-atomicity caveat as edit_feedback_coefs().
258 */
259 [[nodiscard]] inline std::span<double> edit_feedforward_coefs()
260 {
261 return std::span<double>(m_coef_b);
262 }
263
264 /**
265 * @brief Largest pole magnitude of the current denominator
266 *
267 * Below 1.0 the recurrence converges; at or above 1.0 it diverges and
268 * the filter will run away on the next sample. Useful after writing
269 * through edit_feedback_coefs, which places poles without any check.
270 *
271 * Delegates to Kinesis::Discrete::max_pole_magnitude. Orders 1 and 2
272 * are closed-form; higher orders solve a companion matrix and are not
273 * suitable for the audio thread.
274 */
275 [[nodiscard]] double max_pole_magnitude() const;
276
277 /**
278 * @brief Resets the filter's internal state
279 *
280 * Clears the input and output history buffers, effectively
281 * resetting the filter to its initial state. This is useful
282 * when switching between audio segments to prevent artifacts.
283 */
284 virtual void reset();
285
286 /**
287 * @brief Sets the filter's output gain
288 * @param new_gain New gain value
289 *
290 * Adjusts the overall output level of the filter without
291 * changing its frequency response characteristics.
292 */
293 inline void set_gain(double new_gain) { m_gain = new_gain; }
294
295 /**
296 * @brief Gets the current gain value
297 * @return Current gain value
298 */
299 [[nodiscard]] inline double get_gain() const { return m_gain; }
300
301 /**
302 * @brief Enables or disables filter bypass
303 * @param enable True to enable bypass, false to disable
304 *
305 * When bypass is enabled, the filter passes input directly to output
306 * without applying any filtering, useful for A/B testing or
307 * temporarily disabling filters.
308 */
309 inline void set_bypass(bool enable) { m_bypass_enabled = enable; }
310
311 /**
312 * @brief Checks if bypass is currently enabled
313 * @return True if bypass is enabled, false otherwise
314 */
315 [[nodiscard]] inline bool is_bypass_enabled() const { return m_bypass_enabled; }
316
317 /**
318 * @brief Gets the filter's order
319 * @return Maximum order of the filter
320 *
321 * The filter order is determined by the maximum of the input and output
322 * coefficient counts minus one, representing the highest power of z⁻¹
323 * in the filter's transfer function.
324 */
325 [[nodiscard]] inline int get_order() const { return std::max(m_coef_a.size() - 1, m_coef_b.size() - 1); }
326
327 /**
328 * @brief Gets the input history buffer
329 * @return Constant reference to the input history vector
330 *
331 * Provides access to the filter's internal input history buffer,
332 * useful for analysis and visualization.
333 */
334 [[nodiscard]] inline const std::vector<double>& get_input_history() const { return m_input_history; }
335
336 /**
337 * @brief Gets the output history buffer
338 * @return Constant reference to the output history vector
339 *
340 * Provides access to the filter's internal output history buffer,
341 * useful for analysis and visualization.
342 */
343 [[nodiscard]] inline const std::vector<double>& get_output_history() const { return m_output_history; }
344
345 /**
346 * @brief Normalizes filter coefficients
347 * @param type Which set of coefficients to normalize (input, output, or both)
348 *
349 * Scales coefficients to ensure a[0] = 1.0 and/or maintain consistent
350 * gain at DC or Nyquist, depending on the filter type.
351 */
352 void normalize_coefficients(coefficients type = coefficients::ALL);
353
354 /**
355 * @brief Calculates the complex frequency response at a specific frequency
356 * @param frequency Frequency in Hz to analyze
357 * @param sample_rate Sample rate in Hz
358 * @return Complex frequency response (magnitude and phase)
359 *
360 * Computes the transformation's complex response at the specified frequency.
361 * This mathematical analysis can be used for visualization, further algorithmic
362 * processing, or to inform cross-domain mappings between audio properties
363 * and other computational parameters.
364 */
365 [[nodiscard]] std::complex<double> get_frequency_response(double frequency, double sample_rate) const;
366
367 /**
368 * @brief Calculates the magnitude response at a specific frequency
369 * @param frequency Frequency in Hz to analyze
370 * @param sample_rate Sample rate in Hz
371 * @return Magnitude response in linear scale
372 *
373 * Computes the filter's magnitude response at the specified frequency,
374 * representing how much the filter amplifies or attenuates that frequency.
375 */
376 [[nodiscard]] double get_magnitude_response(double frequency, double sample_rate) const;
377
378 /**
379 * @brief Calculates the phase response at a specific frequency
380 * @param frequency Frequency in Hz to analyze
381 * @param sample_rate Sample rate in Hz
382 * @return Phase response in radians
383 *
384 * Computes the filter's phase response at the specified frequency,
385 * representing the phase shift introduced by the filter at that frequency.
386 */
387 [[nodiscard]] double get_phase_response(double frequency, double sample_rate) const;
388
389 /**
390 * @brief Processes a single sample through the filter
391 * @param input The input sample
392 * @return The filtered output sample
393 *
394 * This is the core processing method that implements the difference
395 * equation for a single sample. It must be implemented by derived
396 * filter classes to define their specific filtering behavior.
397 */
398 double process_sample(double input = 0.) override = 0;
399
400 /**
401 * @brief Calculates the phase response at a specific frequency
402 * @param frequency Frequency in Hz to analyze
403 * @param sample_rate Sample rate in Hz
404 * @return Phase response in radians
405 *
406 * Computes the filter's phase response at the specified frequency,
407 * representing the phase shift introduced by the filter at that frequency.
408 */
409 std::vector<double> process_batch(unsigned int num_samples) override;
410
411 /**
412 * @brief Sets the input node for the filter
413 * @param input_node Node providing input samples
414 *
415 * Connects the filter to a source of input samples, allowing
416 * filters to be chained together or connected to generators.
417 */
418 inline void set_input_node(const std::shared_ptr<Node>& input_node) { m_input_node = input_node; }
419
420 /**
421 * @brief Gets the input node for the filter
422 * @return Node providing input samples
423 */
424 inline std::shared_ptr<Node> get_input_node() { return m_input_node; }
425
426 /**
427 * @brief Updates the feedback (denominator) coefficients
428 * @param new_coefs New coefficient values
429 *
430 * Sets the 'a' coefficients in the difference equation, which are applied
431 * to previous output samples. The vector is normalized on entry so that
432 * a[0] is 1.0; getACoefficients() therefore returns the normalized form,
433 * not the values as supplied. Rejects vectors whose leading coefficient
434 * magnitude falls below k_min_leading_coef.
435 */
436 void setACoefficients(const std::vector<double>& new_coefs);
437
438 /**
439 * @brief Updates the feedforward (numerator) coefficients
440 * @param new_coefs New coefficient values
441 *
442 * Sets the 'b' coefficients in the difference equation, which
443 * are applied to current and previous input samples. The method
444 * ensures proper buffer sizing.
445 */
446 void setBCoefficients(const std::vector<double>& new_coefs);
447
448 /**
449 * @brief Gets the feedback (denominator) coefficients
450 * @return Constant reference to the 'a' coefficient vector
451 *
452 * Provides access to the filter's feedback coefficients for
453 * analysis and visualization.
454 */
455 [[nodiscard]] inline const std::vector<double>& getACoefficients() const { return m_coef_a; }
456
457 /**
458 * @brief Gets the feedforward (numerator) coefficients
459 * @return Constant reference to the 'b' coefficient vector
460 *
461 * Provides access to the filter's feedforward coefficients for
462 * analysis and visualization.
463 */
464 [[nodiscard]] inline const std::vector<double>& getBCoefficients() const { return m_coef_b; }
465
466 /**
467 * @brief Provide external buffer context for input history
468 * @param context View into buffer data to use instead of internal input accumulation
469 */
470 inline void set_input_context(std::span<double> context)
471 {
472 m_external_input_context = context;
473 m_use_external_input_context = true;
474 }
475
476 /**
477 * @brief Clear external input context, resume internal accumulation
478 */
480 {
481 m_use_external_input_context = false;
482 m_external_input_context = {};
483 }
484
485 [[nodiscard]] inline bool using_external_input_context() const
486 {
487 return m_use_external_input_context;
488 }
489
490 /**
491 * @brief Gets the last created context object
492 * @return Reference to the last FilterContext object
493 */
494 NodeContext& get_last_context() override;
495
496 void set_gpu_compatible(bool compatible) override
497 {
498 Node::set_gpu_compatible(compatible);
499 if (compatible) {
500 m_node_capability |= NodeCapability::VECTOR;
501 } else {
502 m_node_capability &= ~NodeCapability::VECTOR;
503 }
504 }
505
506 /**
507 * @brief Registers a callback to be called on each tick with the filter context
508 * @param callback Typed hook that receives a FilterContext object
509 */
510 void on_tick(const TypedHook<FilterContext>& callback);
511
512 /**
513 * @brief Registers a conditional callback to be called on each tick if the condition is met
514 * @param condition NodeCondition that determines whether the callback should be called
515 * @param callback Typed hook that receives a FilterContext object
516 */
517 void on_tick_if(const NodeCondition& condition, const TypedHook<FilterContext>& callback);
518
519 /**
520 * @brief Retrieves the current modulators connected to this node
521 * @return Vector of pairs containing the modulator role and the corresponding node
522 */
523 [[nodiscard]] std::vector<std::pair<ModulatorRole, std::shared_ptr<Node>>> get_modulators() const override;
524
525protected:
526 /**
527 * @brief Modifies a specific coefficient in a coefficient buffer
528 * @param index Index of the coefficient to modify
529 * @param value New value for the coefficient
530 * @param buffer Reference to the coefficient buffer to modify
531 *
532 * Internal implementation for adding or modifying a coefficient
533 * in either the 'a' or 'b' coefficient vectors.
534 */
535 void add_coef_internal(uint64_t index, double value, std::vector<double>& buffer);
536
537 /**
538 * @brief Updates the input history buffer with a new sample
539 * @param current_sample The new input sample
540 *
541 * Shifts the input history buffer and adds the new sample at the
542 * beginning. This maintains the history of input samples needed
543 * for the filter's feedforward path.
544 */
545 virtual void update_inputs(double current_sample);
546
547 /**
548 * @brief Updates the output history buffer with a new sample
549 * @param current_sample The new output sample
550 *
551 * Shifts the output history buffer and adds the new sample at the
552 * beginning. This maintains the history of output samples needed
553 * for the filter's feedback path.
554 */
555 virtual void update_outputs(double current_sample);
556
557 /**
558 * @brief Updates filter-specific context object
559 * @param value The current output sample value
560 *
561 * Updates FilterContext object that contains information about the filter's
562 * current state, including the current sample value, input/output history buffers,
563 * and coefficients. This context is passed to callbacks and conditions to provide
564 * them with the information they need to execute properly.
565 *
566 * The FilterContext allows callbacks to access filter-specific information
567 * beyond just the current sample value, enabling more sophisticated monitoring
568 * and analysis of filter behavior.
569 */
570 void update_context(double value) override;
571
572 /**
573 * @brief Notifies all registered callbacks with the current filter context
574 * @param value The current output sample value
575 *
576 * This method is called by the filter implementation when a new output value
577 * is produced. It creates a FilterContext object using create_context(), then
578 * calls all registered callbacks with that context.
579 *
580 * For unconditional callbacks (registered with on_tick()), the callback
581 * is always called. For conditional callbacks (registered with on_tick_if()),
582 * the callback is called only if its condition returns true.
583 *
584 * Filter implementations should call this method at appropriate points in their
585 * processing flow to trigger callbacks, typically after computing a new output value.
586 */
587 void notify_tick(double value) override;
588
589 /**
590 * @brief Builds input history from external context or internal accumulation
591 * @param current_sample Current input sample being processed
592 */
593 void build_input_history(double current_sample);
594
595 /**
596 * @brief The most recent sample value generated by this oscillator
597 *
598 * This value is updated each time process_sample() is called and can be
599 * accessed via get_last_output() without triggering additional processing.
600 * It's useful for monitoring the oscillator's state and for implementing
601 * feedback loops.
602 */
603 // double m_last_output;
604
605 /**
606 * @brief Input node providing samples to filter
607 *
608 * The filter processes samples from this node, allowing filters
609 * to be chained together or connected to generators.
610 */
611 std::shared_ptr<Node> m_input_node;
612
613 /**
614 * @brief Buffer storing previous input samples
615 *
616 * Maintains a history of input samples needed for the filter's
617 * feedforward path (b coefficients).
618 */
619 std::vector<double> m_input_history;
620
621 /**
622 * @brief Buffer storing previous output samples
623 *
624 * Maintains a history of output samples needed for the filter's
625 * feedback path (a coefficients).
626 */
627 std::vector<double> m_output_history;
628
629 /**
630 * @brief External input context for input history
631 *
632 * If set, the filter uses this external context for input history
633 * instead of its internal buffer. This allows sharing input history
634 * across multiple filters or nodes or from AudioBuffer sources.
635 */
636 std::span<double> m_external_input_context;
637
638 /**
639 * @brief Feedback (denominator) coefficients
640 *
641 * The 'a' coefficients in the difference equation, applied to
642 * previous output samples. a[0] is typically normalized to 1.0.
643 */
644 std::vector<double> m_coef_a;
645
646 /**
647 * @brief Feedforward (numerator) coefficients
648 *
649 * The 'b' coefficients in the difference equation, applied to
650 * current and previous input samples.
651 */
652 std::vector<double> m_coef_b;
653
654 /**
655 * @brief Overall gain factor applied to the filter output
656 *
657 * Provides a simple way to adjust the filter's output level
658 * without changing its frequency response characteristics.
659 */
660 double m_gain = 1.0;
661
662 /**
663 * @brief Flag to bypass filter processing
664 *
665 * When enabled, the filter passes input directly to output
666 * without applying any filtering.
667 */
668 bool m_bypass_enabled {};
669
670 std::vector<double> m_saved_input_history;
671 std::vector<double> m_saved_output_history;
672
673 bool m_use_external_input_context {};
674
677};
678}
Core::GlobalInputConfig input
Definition Config.cpp:38
double frequency
vk::PhysicalDeviceType type
Definition VKDevice.cpp:146
uint32_t index
Definition VKDevice.cpp:142
float value
FilterContextGpu(double value, const std::vector< double > &input_history, const std::vector< double > &output_history, const std::vector< double > &coefs_a, const std::vector< double > &coefs_b, std::span< const float > gpu_data)
Definition Filter.hpp:104
GPU-augmented filter context for callbacks.
Definition Filter.hpp:102
const std::vector< double > & coefs_b
Current coefficients for output.
Definition Filter.hpp:91
const std::vector< double > & input_history
Current input history buffer.
Definition Filter.hpp:72
const std::vector< double > & coefs_a
Current coefficients for input.
Definition Filter.hpp:86
FilterContext(double value, const std::vector< double > &input_history, const std::vector< double > &output_history, const std::vector< double > &coefs_a, const std::vector< double > &coefs_b)
Constructs a FilterContext with the current filter state.
Definition Filter.hpp:52
const std::vector< double > & output_history
Current output history buffer.
Definition Filter.hpp:81
Specialized context for filter node callbacks.
Definition Filter.hpp:38
void set_gain(double new_gain)
Sets the filter's output gain.
Definition Filter.hpp:293
std::vector< double > m_saved_output_history
Definition Filter.hpp:671
void set_gpu_compatible(bool compatible) override
Sets whether the node is compatible with GPU processing.
Definition Filter.hpp:496
std::span< double > edit_feedback_coefs()
Mutable view of the feedback taps, excluding a[0].
Definition Filter.hpp:248
void set_input_context(std::span< double > context)
Provide external buffer context for input history.
Definition Filter.hpp:470
std::vector< double > m_coef_b
Feedforward (numerator) coefficients.
Definition Filter.hpp:652
std::vector< double > m_output_history
Buffer storing previous output samples.
Definition Filter.hpp:627
const std::vector< double > & get_input_history() const
Gets the input history buffer.
Definition Filter.hpp:334
const std::vector< double > & getBCoefficients() const
Gets the feedforward (numerator) coefficients.
Definition Filter.hpp:464
std::span< double > edit_feedforward_coefs()
Mutable view of the feedforward coefficients.
Definition Filter.hpp:259
int get_order() const
Gets the filter's order.
Definition Filter.hpp:325
bool is_bypass_enabled() const
Checks if bypass is currently enabled.
Definition Filter.hpp:315
std::shared_ptr< Node > m_input_node
The most recent sample value generated by this oscillator.
Definition Filter.hpp:611
std::vector< double > m_saved_input_history
Definition Filter.hpp:670
const std::vector< double > & getACoefficients() const
Gets the feedback (denominator) coefficients.
Definition Filter.hpp:455
~Filter() override=default
Virtual destructor.
void set_input_node(const std::shared_ptr< Node > &input_node)
Sets the input node for the filter.
Definition Filter.hpp:418
int get_current_latency() const
Gets the current processing latency of the filter.
Definition Filter.hpp:185
double get_gain() const
Gets the current gain value.
Definition Filter.hpp:299
std::vector< double > m_input_history
Buffer storing previous input samples.
Definition Filter.hpp:619
void clear_input_context()
Clear external input context, resume internal accumulation.
Definition Filter.hpp:479
FilterContextGpu m_context_gpu
Definition Filter.hpp:676
std::span< double > m_external_input_context
External input context for input history.
Definition Filter.hpp:636
const std::vector< double > & get_output_history() const
Gets the output history buffer.
Definition Filter.hpp:343
std::vector< double > m_coef_a
Feedback (denominator) coefficients.
Definition Filter.hpp:644
double process_sample(double input=0.) override=0
Processes a single sample through the filter.
void set_bypass(bool enable)
Enables or disables filter bypass.
Definition Filter.hpp:309
std::shared_ptr< Node > get_input_node()
Gets the input node for the filter.
Definition Filter.hpp:424
bool using_external_input_context() const
Definition Filter.hpp:485
Base class for computational signal transformers implementing difference equations.
Definition Filter.hpp:148
GPU-uploadable 1D array data interface.
Base context class for node callbacks.
Definition Node.hpp:53
Base interface for all computational processing nodes.
Definition Node.hpp:126
constexpr double k_min_leading_coef
Minimum permissible magnitude for the leading denominator coefficient.
Definition Filter.hpp:20
NodeCapability
Bitmask flags declaring what data shapes a node's context can produce.
Definition NodeSpec.hpp:104
std::function< void(ContextT &)> TypedHook
Callback function type for node processing events, parameterised on context type.
Definition NodeUtils.hpp:28
std::function< bool(NodeContext &)> NodeCondition
Predicate function type for conditional callbacks.
Definition NodeUtils.hpp:54