Process the network for the given number of samples.
314{
316
319 std::this_thread::yield();
320
323 return;
324 }
325
326 thread_local std::vector<double> scratch;
327 scratch.assign(num_samples, 0.0);
328
330
333 nb.reserve(num_samples);
334
338
341 if (!peaks.empty()) {
342 const double peak_scale = 1.0 / static_cast<double>(peaks.size());
343 for (size_t peak_idx : peaks) {
347 const double target =
mode.initial_amplitude * strength;
348 mode.amplitude = std::max(
mode.amplitude, target);
349 }
350 }
351 }
356 if (!peaks.empty()) {
357 const auto max_peak = *std::ranges::max_element(peaks,
358 [
this](
size_t a,
size_t b) {
360 });
363 const double target =
mode.initial_amplitude * strength;
364 mode.amplitude = std::max<double>(
mode.amplitude, target);
365 }
366 }
367 }
368 }
369 }
370
371 for (size_t i = 0; i < num_samples; ++i) {
373
374 if (exciter_signal != 0.0) {
377 mode.amplitude += exciter_signal *
mode.initial_amplitude
379 }
380 }
381 }
382
385
386 for (
size_t m = 0; m <
m_modes.size(); ++m) {
388
389 if (
mode.amplitude > 0.0001) {
390 mode.amplitude *=
mode.decay_coefficient;
391 } else {
392 mode.amplitude = 0.0;
393 }
394
395 double sample =
mode.oscillator->process_sample(0.0) *
mode.amplitude;
397 scratch[i] += sample;
398 }
399 }
400
402 std::this_thread::yield();
403
407}
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.
static 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.
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< double > mode(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Mode per window via tolerance-bucketed frequency count.
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.