|
MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
|
Network of IIR biquad bandpass filters driven by external excitation. More...
#include <ResonatorNetwork.hpp>
Inheritance diagram for MayaFlux::Nodes::Network::ResonatorNetwork:
Collaboration diagram for MayaFlux::Nodes::Network::ResonatorNetwork:Classes | |
| struct | ParameterMapping |
| struct | ResonatorNode |
| State of a single biquad bandpass resonator. More... | |
Public Types | |
| enum class | FormantPreset : uint8_t { NONE , VOWEL_A , VOWEL_E , VOWEL_I , VOWEL_O , VOWEL_U } |
| Common vowel and spectral formant configurations. More... | |
Public Member Functions | |
| ResonatorNetwork (size_t num_resonators, FormantPreset preset=FormantPreset::NONE) | |
| Construct a ResonatorNetwork with a formant preset. | |
| ResonatorNetwork (const std::vector< double > &frequencies, const std::vector< double > &q_values) | |
| Construct a ResonatorNetwork with explicit frequency and Q vectors. | |
| void | process_batch (unsigned int num_samples) override |
| Processes num_samples through all resonators and accumulates output. | |
| size_t | get_node_count () const override |
| Returns the number of resonators in the network. | |
| std::optional< std::vector< double > > | get_audio_buffer () const override |
| Returns the mixed audio buffer from the last process_batch() call. | |
| std::optional< double > | get_node_output (size_t index) const override |
| Returns the last output sample of the resonator at index. | |
| void | map_parameter (const std::string ¶m_name, const std::shared_ptr< Node > &source, MappingMode mode=MappingMode::BROADCAST) override |
| Map a scalar node output to a named networkparameter (BROADCAST) | |
| void | map_parameter (const std::string ¶m_name, const std::shared_ptr< NodeNetwork > &source_network) override |
| Map a NodeNetwork's per-node outputs to a named network parameter (ONE_TO_ONE) | |
| void | unmap_parameter (const std::string ¶m_name) override |
| Remove a parameter mapping by name. | |
| void | set_exciter (const std::shared_ptr< Node > &exciter) |
| Set a shared exciter node for all resonators. | |
| void | clear_exciter () |
| Clear the network-level exciter. | |
| void | set_resonator_exciter (size_t index, const std::shared_ptr< Node > &exciter) |
| Set a per-resonator exciter. | |
| void | clear_resonator_exciter (size_t index) |
| Clear per-resonator exciter, reverting to network-level exciter. | |
| void | set_network_exciter (const std::shared_ptr< NodeNetwork > &network) |
| Set a NodeNetwork as a source of per-resonator excitation (ONE_TO_ONE) | |
| void | clear_network_exciter () |
| Clear the network exciter. | |
| void | set_frequency (size_t index, double frequency) |
| Set centre frequency of a single resonator and recompute its coefficients. | |
| void | set_q (size_t index, double q) |
| Set Q factor of a single resonator and recompute its coefficients. | |
| void | set_resonator_gain (size_t index, double gain) |
| Set amplitude gain of a single resonator. | |
| void | set_all_frequencies (double frequency) |
| Set centre frequency of all resonators uniformly. | |
| void | set_all_q (double q) |
| Set Q factor of all resonators uniformly. | |
| void | apply_preset (FormantPreset preset) |
| Apply a FormantPreset to the current network. | |
| const std::vector< ResonatorNode > & | get_resonators () const |
| Read-only access to all resonator descriptors. | |
| double | get_sample_rate () const |
| Current audio sample rate. | |
| std::optional< std::span< const double > > | get_node_audio_buffer (size_t index) const override |
| Get output of specific internal node as audio buffer (for ONE_TO_ONE mapping) | |
| std::unordered_map< std::string, std::string > | get_metadata () const override |
| Returns network metadata for debugging and visualisation. | |
Public Member Functions inherited from MayaFlux::Nodes::Network::NodeNetwork | |
| virtual | ~NodeNetwork ()=default |
| void | set_output_mode (OutputMode mode) |
| Set the network's output routing mode. | |
| OutputMode | get_output_mode () const |
| Get the current output routing mode. | |
| virtual void | set_topology (Topology topology) |
| Set the network's topology. | |
| Topology | get_topology () const |
| Get the current topology. | |
| void | set_enabled (bool enabled) |
| Enable/disable the network. | |
| bool | is_enabled () const |
| Check if network is enabled. | |
| virtual void | initialize () |
| Called once before first process_batch() | |
| virtual void | reset () |
| Reset network to initial state. | |
| void | set_output_scale (double scale) |
| Set the scalar multiplier applied to the network's output buffer after processing. | |
| double | get_output_scale () const |
| Get the current output scale factor. | |
| void | add_channel_usage (uint32_t channel_id) |
| Register network usage on a specific channel. | |
| void | remove_channel_usage (uint32_t channel_id) |
| Unregister network from a specific channel. | |
| bool | is_registered_on_channel (uint32_t channel_id) const |
| Check if network is registered on a channel. | |
| std::vector< uint32_t > | get_registered_channels () const |
| Get all channels this network is registered on. | |
| uint32_t | get_channel_mask () const |
| Get channel mask (bitfield of registered channels) | |
| void | set_channel_mask (uint32_t mask) |
| Set channel mask directly. | |
| bool | is_processed_this_cycle () const |
| Check if network has been processed this cycle (lock-free) | |
| void | mark_processing (bool processing) |
| Mark network as processing or not (lock-free) | |
| void | mark_processed (bool processed) |
| Mark network as processed this cycle (lock-free) | |
| bool | is_processing () const |
| Check if network is currently processing (lock-free) | |
| void | request_reset_from_channel (uint32_t channel_id) |
| Request a reset from a specific channel. | |
| virtual NetworkOperator * | get_operator () |
| virtual const NetworkOperator * | get_operator () const |
| virtual bool | has_operator () const |
| const RoutingState & | get_routing_state () const |
| Retrieves the current routing state of the network. | |
| RoutingState & | get_routing_state () |
| Retrieves the current routing state of the network (non-const) | |
| bool | needs_channel_routing () const |
| Checks if the network is currently in a routing transition phase. | |
| void | set_sample_rate (uint32_t sample_rate) |
| uint32_t | get_sample_rate () const |
| void | set_block_size (uint32_t block_size) |
| uint32_t | get_block_size () const |
Private Member Functions | |
| void | compute_biquad (ResonatorNode &r) |
| Compute RBJ biquad bandpass coefficients and push them into a resonator's IIR. | |
| void | build_resonators (const std::vector< double > &frequencies, const std::vector< double > &qs) |
| Initialise all resonators from a frequency/Q pair list. | |
| void | update_mapped_parameters () |
| Apply all registered parameter mappings for the current cycle. | |
| void | apply_broadcast_parameter (const std::string ¶m, double value) |
| Apply a BROADCAST value to the named parameter across all resonators. | |
| void | apply_one_to_one_parameter (const std::string ¶m, const std::shared_ptr< NodeNetwork > &source) |
| Apply ONE_TO_ONE values from a source network to the named parameter. | |
Static Private Member Functions | |
| static void | preset_to_vectors (FormantPreset preset, size_t n, std::vector< double > &out_freqs, std::vector< double > &out_qs) |
| Translate a FormantPreset into parallel frequency/Q vectors. | |
Private Attributes | |
| std::vector< ResonatorNode > | m_resonators |
| std::shared_ptr< Node > | m_exciter |
| networ-level shared exciter (may be nullptr) | |
| std::shared_ptr< NodeNetwork > | m_network_exciter |
| Optional NodeNetwork exciter for ONE_TO_ONE mapping (may be nullptr) | |
| std::vector< double > | m_last_audio_buffer |
| Mixed output from last process_batch() | |
| std::vector< std::vector< double > > | m_node_buffers |
| Per-resonator sample buffers populated each process_batch() | |
| std::vector< ParameterMapping > | m_parameter_mappings |
Additional Inherited Members | |
Protected Member Functions inherited from MayaFlux::Nodes::Network::NodeNetwork | |
| void | ensure_initialized () |
| Ensure initialize() is called exactly once. | |
| void | apply_output_scale () |
| Apply m_output_scale to m_last_audio_buffer. | |
Static Protected Member Functions inherited from MayaFlux::Nodes::Network::NodeNetwork | |
| static std::unordered_map< size_t, std::vector< size_t > > | build_grid_2d_neighbors (size_t width, size_t height) |
| Build neighbor map for GRID_2D topology. | |
| static std::unordered_map< size_t, std::vector< size_t > > | build_grid_3d_neighbors (size_t width, size_t height, size_t depth) |
| Build neighbor map for GRID_3D topology. | |
| static std::unordered_map< size_t, std::vector< size_t > > | build_ring_neighbors (size_t count) |
| Build neighbor map for RING topology. | |
| static std::unordered_map< size_t, std::vector< size_t > > | build_chain_neighbors (size_t count) |
| Build neighbor map for CHAIN topology. | |
Protected Attributes inherited from MayaFlux::Nodes::Network::NodeNetwork | |
| Topology | m_topology = Topology::INDEPENDENT |
| OutputMode | m_output_mode = OutputMode::NONE |
| bool | m_enabled = true |
| bool | m_initialized = false |
| uint32_t | m_sample_rate { 48000 } |
| uint32_t | m_block_size { 512 } |
| std::vector< ParameterMapping > | m_parameter_mappings |
| std::atomic< uint32_t > | m_channel_mask { 0 } |
| Bitfield of channels this network is registered on. | |
| std::atomic< uint32_t > | m_pending_reset_mask { 0 } |
| std::atomic< bool > | m_processing_state { false } |
| Per-channel processing state (lock-free atomic flags) | |
| std::atomic< bool > | m_processed_this_cycle { false } |
| std::vector< double > | m_last_audio_buffer |
| double | m_output_scale { 1.0 } |
| Post-processing scalar applied to m_last_audio_buffer each batch. | |
Network of IIR biquad bandpass filters driven by external excitation.
ResonatorNetwork implements N second-order IIR bandpass sections (biquads), each tuned to an independent centre frequency and Q factor. Unlike ModalNetwork, which synthesises resonance through decaying sinusoidal oscillators in the frequency domain, ResonatorNetwork operates purely in the time domain: it shapes the spectrum of whatever signal is injected into it. Feed white noise and the Network becomes a formant synthesiser; feed a pitched glottal pulse and it voices a vowel; feed an arbitrary signal and it performs spectral morphing toward the target formant profile.
Each resonator computes the RBJ Audio EQ cookbook bilinear-transform biquad bandpass (constant 0 dB peak gain form):
H(z) = (1 - z^{-2}) * (b0/a0) / (1 + (a1/a0)*z^{-1} + (a2/a0)*z^{-2})
Coefficients derived at construction and on every parameter change:
w0 = 2π f0 / Fs alpha = sin(w0) / (2 Q) b0 = sin(w0) / 2 = alpha b1 = 0 b2 = -sin(w0) / 2 = -alpha a0 = 1 + alpha a1 = -2 cos(w0) a2 = 1 - alpha
A single shared exciter node can drive all resonators simultaneously (the classic formant synthesis topology). Alternatively, per-resonator exciter nodes allow independent spectral injection. If no exciter is set, the network accepts external samples passed directly to process_sample() / process_batch().
Supports BROADCAST and ONE_TO_ONE modes via the NodeNetwork interface:
Each process_batch() call sums all resonator outputs into a single mixed audio buffer, normalised by the number of active resonators to prevent clipping. Alternatively, get_node_output(index) exposes the most recent individual resonator output for cross-domain routing.
Definition at line 79 of file ResonatorNetwork.hpp.