Process the network for the given number of samples.
336{
338
341 std::this_thread::yield();
342
345 return;
346 }
347
348 thread_local std::vector<double> scratch;
349 scratch.assign(num_samples, 0.0);
350
352
355 nb.reserve(num_samples);
356
360
363 if (!peaks.empty()) {
364 const double peak_scale = 1.0 / static_cast<double>(peaks.size());
365 for (size_t peak_idx : peaks) {
369 const double target =
mode.initial_amplitude * strength;
370 mode.amplitude = std::max(
mode.amplitude, target);
371 }
372 }
373 }
378 if (!peaks.empty()) {
379 const auto max_peak = *std::ranges::max_element(peaks,
380 [
this](
size_t a,
size_t b) {
382 });
385 const double target =
mode.initial_amplitude * strength;
386 mode.amplitude = std::max<double>(
mode.amplitude, target);
387 }
388 }
389 }
390 }
391 }
392
393 for (size_t i = 0; i < num_samples; ++i) {
395
396 if (exciter_signal != 0.0) {
399 mode.amplitude += exciter_signal *
mode.initial_amplitude
401 }
402 }
403 }
404
407
408 for (
size_t m = 0; m <
m_modes.size(); ++m) {
410
411 if (
mode.amplitude > 0.0001) {
412 mode.amplitude *=
mode.decay_coefficient;
413 } else {
414 mode.amplitude = 0.0;
415 }
416
417 double sample =
mode.oscillator->process_sample(0.0) *
mode.amplitude;
419 scratch[i] += sample;
420 }
421 }
422
424 std::this_thread::yield();
425
429}
std::vector< std::vector< double > > m_node_buffers
Per-mode sample buffers populated each process_batch()
@ FILTERED_NOISE
Spectrally-shaped noise burst.
@ CONTINUOUS
External node as continuous exciter.
@ NOISE_BURST
Short white noise burst.
ExciterType m_exciter_type
size_t m_exciter_node_buffer_pos
double m_exciter_strength
std::vector< ModeCoupling > m_couplings
void compute_mode_coupling()
Apply modal coupling energy transfer.
double generate_exciter_sample()
Generate exciter signal for current sample.
std::vector< ModalNode > m_modes
std::vector< double > m_exciter_node_buffer
std::shared_ptr< Node > m_exciter_node
void update_mapped_parameters()
Update mapped parameters before processing.
void apply_output_scale()
Apply m_output_scale to m_last_audio_buffer.
bool is_enabled() const
Check if network is enabled.
std::atomic_flag m_audio_buffer_lock
Spinlock guarding m_last_audio_buffer.
void ensure_initialized()
Ensure initialize() is called exactly once.
std::vector< double > m_last_audio_buffer
std::vector< size_t > peak_positions(std::span< const double > data, double threshold, size_t min_distance)
Sample indices of local peak maxima in the full span.
void extract_node_samples(const std::shared_ptr< Nodes::Node > &node, std::vector< double > &buffer, size_t &buffer_pos, size_t num_samples)
Extract num_samples from node into buffer using snapshot guard.