Nonlinear Space and Zero-Latency Convolution¶
Pulp has two advanced space processors with different jobs. NonlinAmbience
generates a designed, gated/reverse/nonlinear tap envelope. ZeroLatencyConvolver
runs an imported impulse response with a direct head and scheduled partitioned
tail while reporting zero algorithmic latency.
Nonlinear ambience¶
#include <pulp/signal/nonlin_ambience.hpp>
pulp::signal::NonlinAmbience ambience;
ambience.prepare(sample_rate);
ambience.set_program(pulp::signal::NonlinProgram::gated);
ambience.set_length_ms(900.0);
ambience.set_density_pct(70.0);
ambience.set_width_pct(100.0);
ambience.set_mix_pct(100.0);
ambience.process(left, right, num_frames);
Use set_topology() on a non-audio thread when applying a coherent snapshot.
Use request_topology() for hosted automation; it bounds the audio-thread work
and swaps the prepared tap bank. envelope(tau), tap(), tap_norm(), and
worst_case_gain() expose the actual design for editors and tests.
Zero-latency convolution¶
#include <pulp/signal/zero_latency_convolver.hpp>
pulp::signal::ZeroLatencyConvolver convolver;
convolver.prepare(sample_rate, max_block, 2);
convolver.set_normalize_mode(pulp::signal::IrNormalizeMode::peak);
convolver.load_impulse_response(ir_channels, ir_channel_count,
ir_length, ir_sample_rate);
convolver.process(input_channels, output_channels, num_frames);
prepare() and load_impulse_response() allocate and perform design work; call
both off the audio thread. process() accepts any n <= max_block and remains
allocation-free. IR resampling, trim/fade, normalization, filters, and true
stereo routing are resolved at load time or through the documented controls.
latency_samples() is zero by construction. Predelay is an artistic delay and
is exposed separately through predelay_samples(). The per-level scheduling
accessors and last_block_cost() are intended for tests, diagnostics, and
budget-aware hosts; normal plugins do not need to schedule partitions themselves.
The complete advanced DSP API lists every method on both processors.
Shared GPU convolution trace¶
The experimental GpuConvolver and GpuConvolutionReverb routes accept an
optional trace configuration before prepare():
pulp::gpu_audio::GpuConvolverTraceConfig trace;
trace.enabled = true;
trace.capture_admissions = true;
trace.success_stride = 1;
pulp::gpu_audio::GpuConvolutionReverbConfig config;
config.gpu_enabled = true;
config.trace = trace;
pulp::gpu_audio::GpuConvolutionReverb reverb(config);
// prepare() runs with audio stopped.
reverb.prepare();
The callback only publishes fixed-size records to bounded SPSC queues. It does
not allocate, lock, wait, or call Perfetto. The transport worker emits the
gpu.audio.session, admission, terminal, delivery, and counter events through
the host's active Pulp trace session. It is the sole live queue consumer and
the node's final close drains any records that remain;
release the route before stopping the host's trace owner and verify the flushed
trace. Each lane receives its own engine ID, while (generation, sequence)
identifies a block within that lane and terminal GPU and delivered-audio
dispositions remain separate.