Processes num_samples through all resonators and accumulates output.
For each sample, each resonator draws from its individual exciter (or the network-level exciter, or zero if none) and processes one sample. All resonator outputs are summed and RMS-normalised (divided by sqrt(resonator_count)) into m_last_audio_buffer before set_output_scale() is applied.
210{
213 std::this_thread::yield();
214
217 return;
218 }
219
221
222 thread_local std::vector<double> scratch;
223 scratch.assign(num_samples, 0.0);
224
225 const double norm =
m_norm_factor.load(std::memory_order_acquire);
226
229 nb.reserve(num_samples);
230
231 std::vector<std::optional<std::span<const double>>> net_exc_bufs;
236 }
237
238 for (size_t s = 0; s < num_samples; ++s) {
241 double excitation = 0.0;
242
243 if (r.exciter) {
244 excitation = r.exciter->process_sample(0.0);
245 } else if (!net_exc_bufs.empty() && net_exc_bufs[ri] && s < net_exc_bufs[ri]->size()) {
246 excitation = (*net_exc_bufs[ri])[s];
248 excitation =
m_exciter->process_sample(0.0);
249 }
250
251 const double out = r.filter->process_sample(excitation) * r.gain;
252 r.last_output = out;
254 scratch[s] += out * norm;
255 }
256 }
257
259 std::this_thread::yield();
260
264}
void apply_output_scale()
Apply m_output_scale to m_last_audio_buffer.
std::atomic_flag m_audio_buffer_lock
Spinlock guarding m_last_audio_buffer.
std::vector< double > m_last_audio_buffer
std::atomic< double > m_norm_factor
Normalisation factor for summed output, rms scaled by number of active resonators.
std::vector< std::vector< double > > m_node_buffers
Per-resonator sample buffers populated each process_batch()
std::vector< ResonatorNode > m_resonators
std::shared_ptr< Node > m_exciter
networ-level shared exciter (may be nullptr)
void update_mapped_parameters()
Apply all registered parameter mappings for the current cycle.
std::shared_ptr< NodeNetwork > m_network_exciter
Optional NodeNetwork exciter for ONE_TO_ONE mapping (may be nullptr)