README

dowdiness/moondsp/voice does not have a README file

#
BoundVoicePool

pub struct BoundVoicePool {
// private fields
}

#
BoundVoicePool::active_voice_count

fn BoundVoicePool::active_voice_count(self : BoundVoicePool) -> Int

#
BoundVoicePool::apply_voice_control_result

fn BoundVoicePool::apply_voice_control_result(self : BoundVoicePool, handle : VoiceHandle, control :
GraphControl
) -> Result[Unit, VoiceControlError]

Apply one validated graph control to an already-sounding voice.

#
BoundVoicePool::apply_voice_controls_result

fn BoundVoicePool::apply_voice_controls_result(self : BoundVoicePool, handle : VoiceHandle, controls : Array[
GraphControl
]) -> Result[Unit, VoiceControlError]

Apply a graph-control batch transactionally to an already-sounding voice.

#
BoundVoicePool::kill

fn BoundVoicePool::kill(self : BoundVoicePool, handle : VoiceHandle) -> Bool

#
BoundVoicePool::last_sanitized_count

fn BoundVoicePool::last_sanitized_count(self : BoundVoicePool) -> Int

#
BoundVoicePool::note_off

fn BoundVoicePool::note_off(self : BoundVoicePool, handle : VoiceHandle) -> Bool

#
BoundVoicePool::note_off_all

fn BoundVoicePool::note_off_all(self : BoundVoicePool) -> Unit

#
BoundVoicePool::note_on_controls

fn BoundVoicePool::note_on_controls(self : BoundVoicePool, controls : Map[String, Double]) -> VoiceHandle?

#
BoundVoicePool::set_voice_pan

fn BoundVoicePool::set_voice_pan(self : BoundVoicePool, handle : VoiceHandle, pan : Double) -> Bool

#
BoundVoicePool::validate_voice_controls_result

fn BoundVoicePool::validate_voice_controls_result(self : BoundVoicePool, handle : VoiceHandle, controls : Array[
GraphControl
]) -> Result[Unit, VoiceControlError]

Validate a live control batch against an active voice without mutating it.

#
BoundVoicePool::voice_state

fn BoundVoicePool::voice_state(self : BoundVoicePool, handle : VoiceHandle) -> VoiceState

#
BoundVoicePoolError

pub(all) enum BoundVoicePoolError {
InvalidMaxVoices
OrphanAdsr
CompileRejected
Binding(
ControlBindingError
)
} derive(Eq,
Debug
)

#
BoundVoicePoolError::from_voice_pool

Lift a VoicePoolError to a BoundVoicePoolError. Used by BoundVoicePool's constructors after delegating to validate_voice_template (which now returns VoicePoolError after the boundary-type migration per ADR-0010).

#
VoiceControlError

pub(all) enum VoiceControlError {
InvalidVoiceHandle(VoiceHandle)
Graph(
GraphControlError
)
} derive(
Debug
)

#
VoiceHandle

pub struct VoiceHandle {
slot : Int
generation : Int
} derive(Eq,
Debug
)

Generation-tagged voice handle. WHY generation counter: slot indices are reused after voice stealing. Without a generation tag, a stale handle from a stolen note could accidentally gate_off or pan the wrong voice occupying that slot. Every note_on increments the slot's generation; all operations compare the handle's generation against the slot's current generation.
impl Show for VoiceHandle

#
VoicePool

pub struct VoicePool {
// private fields
}

#
VoicePool::active_voice_count

fn VoicePool::active_voice_count(self : VoicePool) -> Int

#
VoicePool::last_sanitized_count

fn VoicePool::last_sanitized_count(self : VoicePool) -> Int

Number of non-finite samples replaced with 0.0 during the most recent process() call, across both L and R output channels after mixdown.

#
VoicePool::new

WHY test_compile: validates the template structurally (reachable Output node, no invalid cycles, valid node indices) before accepting it. This is a correctness gate so that per-voice note_on compiles can assume the template is well-formed. The compiled result is discarded. WHY orphan-ADSR reject: VoicePool::note_on calls gate_on for every ADSR index in the template. If an ADSR is authored into the template but not wired to Output, optimize_graph eliminates it and gate_on would now return Err(OrphanNode). Rejecting at pool-construction time keeps the per-note gate_adsrs_at(...) loop infallible (it can .unwrap()) and surfaces the misconfiguration at the earliest observable point rather than at every note trigger. WHY adsr_authoring_indices snapshot: the pool's long-lived snapshot (used by note_on to gate ADSRs, and refreshed by set_template) stores only the indices needed for gating — not the full template — so the caller's CompiledTemplate can be freely discarded after VoicePool::new returns. optimize_graph does not mutate its input, so neither CompiledTemplate::analyze nor CompiledDsp::compile disturbs the caller's array.

#
VoicePool::note_off

fn VoicePool::note_off(self : VoicePool, handle : VoiceHandle) -> Bool

#
VoicePool::note_off_all

fn VoicePool::note_off_all(self : VoicePool) -> Unit

#
VoicePool::set_template

fn VoicePool::set_template(self : VoicePool, compiled_template :
CompiledTemplate
) -> Result[Unit, VoicePoolError]

#
VoicePool::set_voice_pan

fn VoicePool::set_voice_pan(self : VoicePool, handle : VoiceHandle, pan : Double) -> Bool

#
VoicePool::voice_state

fn VoicePool::voice_state(self : VoicePool, handle : VoiceHandle) -> VoiceState

#
VoicePoolError

pub(all) enum VoicePoolError {
InvalidMaxVoices
OrphanAdsr
CompileRejected
} derive(Eq,
Debug
)

Failure modes for VoicePool construction and template replacement. Mirrors BoundVoicePoolError minus the Binding(...) variant (VoicePool has no bindings).

#
VoiceState

pub enum VoiceState {
Idle
Active
Releasing
} derive(Eq,
Debug
)

impl Show for VoiceState