pub struct AudioRenderer { /* private fields */ }Expand description
Mixes a project’s audio tracks into one project-rate block.
Implementations§
Source§impl AudioRenderer
impl AudioRenderer
Sourcepub fn new(
snapshot: &EngineProject,
channels: usize,
max_block: usize,
) -> Result<Self, EngineError>
pub fn new( snapshot: &EngineProject, channels: usize, max_block: usize, ) -> Result<Self, EngineError>
Builds every track and master processor for a project snapshot, and measures every clip’s; a clip’s are built when it is mixed.
§Errors
Returns EngineError::InvalidAudioConfiguration for an unsupported
channel count, a zero sample rate, or an oversized block.
Sourcepub const fn sample_rate(&self) -> u32
pub const fn sample_rate(&self) -> u32
Returns the project sample rate every block uses.
Sourcepub fn track_ids(&self) -> Vec<&TrackId>
pub fn track_ids(&self) -> Vec<&TrackId>
Returns the audio tracks this renderer mixes, in bus order.
Sourcepub fn channel(&self, index: usize) -> &[f32]
pub fn channel(&self, index: usize) -> &[f32]
Returns one mixed output channel from the most recent render.
Sourcepub fn required_lookahead_samples(&self) -> u32
pub fn required_lookahead_samples(&self) -> u32
How far ahead of a block, in samples, the renderer reads its sources.
A lookahead effect (a compressor’s lookahead_ms) delays what passes
through it. Rather than delay the mix, the renderer reads each path’s
input early by the latency between it and the output, so the output
lines up with the timeline. Use Self::audio_needs for source supply:
a cold seek also needs recursive-state history, beyond this delay.
Sourcepub fn audio_needs(
&self,
snapshot: &EngineProject,
start_sample: i64,
frames: usize,
) -> Result<Vec<AudioNeed>, EngineError>
pub fn audio_needs( &self, snapshot: &EngineProject, start_sample: i64, frames: usize, ) -> Result<Vec<AudioNeed>, EngineError>
The source intervals rendering frames samples from start_sample
reads, for a host to decode first.
They are what Self::render would read, found the way it reads
them: the same blocks (on a discontinuity it does not continue across
(AudioContinuity), the replay of each stage’s settling history,
which stops at timeline zero, then the block), the
same clips (heard, on a bus the mix hears, once their stages have
begun settling), and the same source window per read, interpolation
neighbours included. A host that holds them needs no margin.
Clips reading one source share a need where their intervals overlap or touch; disjoint intervals of one source stay separate needs, so two clips cut from far apart in one source do not ask for everything between them.
§Errors
Returns EngineError::InvalidAudioConfiguration for a negative
start, an empty block, one larger than Self::max_block, or a block
whose timeline span does not fit in ticks, and an evaluation error when
the snapshot cannot be evaluated over a block’s span.
Sourcepub const fn required_history_samples(&self) -> i64
pub const fn required_history_samples(&self) -> i64
Finite state-settling history requested on discontinuities, in samples.
This is separate from latency; Self::audio_needs includes the
history each clip’s stages replay. It is at most
MAX_SETTLING_SECONDS of samples.
Sourcepub fn set_continuity(&mut self, continuity: AudioContinuity)
pub fn set_continuity(&mut self, continuity: AudioContinuity)
Chooses what Self::render does with a block that does not start
where the previous one ended (AudioContinuity); new renderers are
AudioContinuity::Exact. Choosing another policy than the current
one resets the renderer (Self::reset), so no state mixed under one
carries into the other: an exact renderer mixes what a fresh one would
from its next block on.
Sourcepub const fn continuity(&self) -> AudioContinuity
pub const fn continuity(&self) -> AudioContinuity
The policy Self::set_continuity last chose.
Sourcepub fn reset(&mut self)
pub fn reset(&mut self)
Clears every processor history without changing authored parameters.
Self::render does this itself whenever a block does not continue
the previous one. A host calls it only to start fresh at the very
position the last block ended, such as an export beginning where
preview stopped.
Sourcepub fn render(
&mut self,
snapshot: &EngineProject,
start_sample: i64,
frames: usize,
provider: &dyn AudioBlockProvider,
transport: TransportState,
) -> Result<AudioRenderStatus, EngineError>
pub fn render( &mut self, snapshot: &EngineProject, start_sample: i64, frames: usize, provider: &dyn AudioBlockProvider, transport: TransportState, ) -> Result<AudioRenderStatus, EngineError>
Mixes frames samples starting at an absolute project-rate sample index.
A block that does not start where the previous one ended, a seek or an
export after preview, first resets every processor, so its output is
what a fresh renderer would produce and no reverb tail, compressor
envelope, or ducking gain carries over from elsewhere on the timeline.
That is the default policy, AudioContinuity::Exact; under
AudioContinuity::ContinueSmallGaps, which live preview may choose
(Self::set_continuity), a block at most Self::max_block samples
from where the previous one ended continues instead, and only a longer
jump resets.
After a reset it replays the history Self::audio_needs asks for in
bounded blocks, cut where each stage starts, so the mix after a seek
does not depend on the block size. Recursive effects use a finite
settling horizon (32 exponential time constants, with filter/feedback
margins, and no stage leads by more than MAX_SETTLING_SECONDS), not
a bit-exact promise for arbitrary infinite-history DSP. Each stage joins
the replay only when its own horizon, plus everything downstream of it,
begins: a long reverb on one track replays that track, not every track.
A block that continues the previous one resets and replays nothing.
§Errors
Returns EngineError::InvalidAudioConfiguration for a negative start,
a block larger than Self::max_block, or a block whose timeline span
does not fit in ticks, and an evaluation error when the snapshot cannot
be evaluated over the block’s timeline span.
Sourcepub fn set_normalization_gain_db(
&mut self,
gain_db: f64,
) -> Result<(), EngineError>
pub fn set_normalization_gain_db( &mut self, gain_db: f64, ) -> Result<(), EngineError>
Applies a static gain, in dB, after the master gain and before the
limiter: loudness normalization. Zero removes it, and so does starting
to meter (Self::set_loudness_metering). It takes any gain
alpha2_audio::LoudnessNormalization::plan gives.
§Errors
Returns EngineError::InvalidNormalizationGain for a non-finite
gain, or one whose linear factor a 32-bit float cannot hold as a
finite, positive number (past about 760 dB either way).
Sourcepub const fn set_hold_incomplete_blocks(&mut self, hold: bool)
pub const fn set_hold_incomplete_blocks(&mut self, hold: bool)
Whether a block a source is missing from is held: mixed as silence with nothing advanced, so that rendering it again once the host has supplied the source continues exactly as an uninterrupted render would. Off (the default), such a block mixes the clips it has and moves on, as live playback wants; an export turns it on.
Sourcepub fn set_loudness_metering(
&mut self,
enabled: bool,
) -> Result<(), EngineError>
pub fn set_loudness_metering( &mut self, enabled: bool, ) -> Result<(), EngineError>
Starts (or restarts, from empty) measuring the loudness of what
reaches the limiter, over the blocks rendered from now on; false
stops. The measurement is of the complete requested blocks only:
never of the history the renderer replays after a seek, nor of a block
a source was missing from, which the host renders again.
Starting removes the normalization gain
(Self::set_normalization_gain_db), so a measurement is of the mix
as authored however many times one is planned from: a gain set after
starting is measured, which checks a normalized mix.
§Errors
Returns EngineError::InvalidAudioConfiguration for a layout or
rate the meter does not support.
Sourcepub fn loudness_report(&self) -> Option<LoudnessReport>
pub fn loudness_report(&self) -> Option<LoudnessReport>
What the meter has measured, if metering is on.
Sourcepub fn limiter_threshold(&self) -> Option<f64>
pub fn limiter_threshold(&self) -> Option<f64>
The linear threshold of the master limiter the meter reads in front
of, or None for a project without one. A loudness plan takes it
(alpha2_audio::LoudnessNormalization::plan) so the gain it plans
stops short of the limiter, which would otherwise cut it back.
Sourcepub fn set_output_loudness_metering(
&mut self,
enabled: bool,
) -> Result<(), EngineError>
pub fn set_output_loudness_metering( &mut self, enabled: bool, ) -> Result<(), EngineError>
Starts (or restarts, from empty) measuring the loudness of what the
renderer outputs, after the limiter and the normalization gain, over
the blocks rendered from now on; false stops. It measures the same
blocks Self::set_loudness_metering does, and leaves the gain as it
is: an export measures what it hands its encoder.
§Errors
Returns EngineError::InvalidAudioConfiguration for a layout or
rate the meter does not support.
Sourcepub fn output_loudness_report(&self) -> Option<LoudnessReport>
pub fn output_loudness_report(&self) -> Option<LoudnessReport>
What the output meter has measured, if output metering is on.
Sourcepub fn block(&self, status: &AudioRenderStatus) -> AudioBlock
pub fn block(&self, status: &AudioRenderStatus) -> AudioBlock
Copies the most recent render into an owned block for offline sinks.