Skip to main content

truce_rack_core/
sample.rs

1//! Audio sample type abstraction.
2//!
3//! Host code is generic over `f32` (the wire format for CLAP /
4//! VST2 / LV2 / AAX) and `f64` (supported by VST3, AU v2, AU v3).
5//! Each format wrapper picks the sample type at load time based
6//! on what the plugin asks for and what the host configured.
7
8/// Audio sample scalar — `f32` or `f64`.
9///
10/// Implemented by `f32` and `f64` only. The bound exists so the
11/// [`crate::Plugin`] trait can be parameterised over precision
12/// without leaking the full numeric trait surface.
13pub trait Sample: Copy + Send + Sync + 'static + private::Sealed {
14    /// Zero value of this precision.
15    const ZERO: Self;
16
17    /// Whether this sample type is `f64`. Lets format wrappers
18    /// pick the `processSetup::symbolicSampleSize` field
19    /// (VST3) or equivalent without runtime branching past the
20    /// constant-fold.
21    const IS_F64: bool;
22
23    /// Widen a `f32` to this precision (`f32 → f32` is identity).
24    fn from_f32(value: f32) -> Self;
25
26    /// Narrow to `f32` for handing back to the host.
27    fn to_f32(self) -> f32;
28}
29
30impl Sample for f32 {
31    const ZERO: Self = 0.0;
32    const IS_F64: bool = false;
33    #[inline]
34    fn from_f32(value: f32) -> Self {
35        value
36    }
37    #[inline]
38    fn to_f32(self) -> f32 {
39        self
40    }
41}
42
43impl Sample for f64 {
44    const ZERO: Self = 0.0;
45    const IS_F64: bool = true;
46    #[inline]
47    fn from_f32(value: f32) -> Self {
48        f64::from(value)
49    }
50    #[inline]
51    #[allow(clippy::cast_possible_truncation)]
52    fn to_f32(self) -> f32 {
53        self as f32
54    }
55}
56
57mod private {
58    pub trait Sealed {}
59    impl Sealed for f32 {}
60    impl Sealed for f64 {}
61}