Native-precision convolution schedules and banks¶
Convolver32 and Convolver64 own one prepared finite response of 1..=262,144
taps and run every operation (direct head, FFT butterflies, spectral products and
sums, overlap and output) in the named native sample precision. FFT twiddles are
computed in f64 during preparation and, for f32, explicitly rounded to Complex32.
ConvolutionPartitioning fixes the schedule at preparation:
UniformDelayed { partition }: one overlap-add stage; algorithmic latency is exactlypartitionframes (16..=4,096, power of two). For f64 this matchesPartitionedConvolversample-for-sample.ZeroLatency { head }: taps0..headrun as a direct FIR, taps fromheadin ahead-partitioned stage whose intrinsic delay equals their original offset. Zero algorithmic latency. Responses no longer thanheadhave no FFT stage.NonUniform { head, tail }: direct head, ahead-partitioned middle stage for tapshead..tailand atail-partitioned late stage (tailpower of two,head..=16,384). Zero latency; empty intervals are omitted. This is a fixed two-stage schedule, not an optimal arbitrary partitioning.
info() reports original taps, direct taps, each stage's offset, taps, partition
count and FFT size, the exact latency, the tail (taps - 1 + latency) and declared
and actual numeric bytes. stage_work() reports completed FFT blocks per stage
(saturating counters, no timing). Every processed source frame produces one output
frame; supply explicit zeros to drain the tail. Reset clears all history and keeps
the response and schedule.
Preparation checks the schedule, response finiteness, a maximum block of 1..=65,536 frames and a caller numeric byte budget of 1 byte..=256 MiB before any allocation, reserves storage fallibly, and rechecks actual capacities. Allocator overhead is excluded from the budget. Processing and reset do not allocate or deallocate. Calls whose frame count exceeds the prepared maximum, or whose slices are shorter than the requested prefix, are refused before any history or output changes; unused slice suffixes are untouched.
ConvolutionBank32/ConvolutionBank64 own 1..=64 independent diagonal channels
sharing one schedule, each with its own response. The aggregate budget and every
response are checked before any channel is built. Planar and in-place calls are
admitted for the whole bank (channel count, maximum, all prefixes) before any
channel runs; reset_channel affects one channel only. There is no stereo
crossfeed, true-stereo matrix or linked normalization.
ravet-signal does not implement the Foundation Processor trait for these
types. A processor wrapper reports info().latency_samples and the largest
channel tail_samples so Graph latency compensation uses the actual algorithmic
delay; engine_mut gives per-channel access for frame-interleaved processing. The
crate tests include such a wrapper in an actual Graph.
Nonfinite and overflowing values propagate until reset; there is no denormal, gain, trim or sample-rate policy. Direct-head cost is O(head) per sample and FFT work is concentrated at partition boundaries; no real-time deadline is claimed. The engines do not load, convert, trim or normalize responses, and do not replace them live. Explicit preparation and live transitions are described below.
Tests compare against independent f64 direct sums and an analytic frequency response, check bit-identical output across arbitrary block sizes including 1 and odd sizes, single taps at every stage boundary, maximum-length responses, empty stage intervals, zero and subnormal responses, bank refusals and channel isolation, allocation-free processing and reset, and an actual Graph with a downstream FIR and a latency-compensated dry path. See decision 0270.
Native f32 FFT¶
FftPlan32::try_new(size, maximum_twiddle_bytes) prepares a 1..=1,048,576-point
radix-two complex f32 FFT with the same sign and 1/N inverse convention as
FftPlan. FftPlan::try_new is an additive bounded constructor for the f64 plan;
FftPlan::new and all f64 transform results are unchanged. Both return
FftPreparationError::{InvalidSize, Capacity, Allocation}. At the maximum size, the
f32 plan shows about 3.2e-11 coherent leakage on an exact quarter-cycle tone because
the f64 value of cos(pi/2) is not exactly zero before rounding; this is recorded,
not corrected.