pub struct AudioVae {
pub sample_rate: usize,
/* private fields */
}Fields§
§sample_rate: usizeImplementations§
Source§impl AudioVae
impl AudioVae
pub fn from_cmf(model: &Arc<CmfModel>) -> Result<Self, String>
Sourcepub fn decode(&self, z: &[f32], c: usize, t: usize) -> (Vec<f32>, usize)
pub fn decode(&self, z: &[f32], c: usize, t: usize) -> (Vec<f32>, usize)
Normalized latents [C, 2, T] → stereo [2, L] in [-1, 1].
THE REMAINING WIN IS THIS LOOP: the two stereo channels are two complete, independent decoder passes and they run one after the other. That is a factor of two sitting outside the exact place the inside cannot use — the convolutions parallelize over output channels, and this decoder narrows to a handful of those near the output where the samples are longest (measured: parallelizing the per-channel FIR bought only 9.2 s → 8.1 s, so the time is in the convolutions, not the filter).
The nesting question is ANSWERED, and the answer forbids the
obvious version: Pool keeps ONE job slot (inner.slot), and
run() writes it on the stated assumption that no job is in
flight. Two concurrent callers would overwrite each other’s job.
So wrapping this loop in a thread::scope while the passes still
call into the pool is a data race, not an optimization.
Two shapes remain. Drive the pool from the OUTSIDE — one row per
stereo channel, None inside — which is correct but caps the
whole decode at two threads and would lose the wide layers what
it wins the narrow ones. Or split the narrow convolutions over
TIME instead of output channels, which keeps every thread busy
at both ends. Measure before choosing: this decoder still has no
phase profiler, and the FIR already proved the shape of the code
is a poor guide to where its seconds are.