Skip to main content

beamer_core/
sample.rs

1//! Sample type abstraction for f32/f64 audio processing.
2//!
3//! Enables zero-cost generic buffer processing through monomorphization.
4
5use std::ops::{Add, Div, Mul, Sub};
6
7/// Trait for audio sample types (f32, f64).
8///
9/// Designed for zero-cost abstraction - all methods inline for monomorphization.
10/// Only includes operations commonly needed in audio DSP inner loops.
11///
12/// # Design Philosophy
13///
14/// - **Minimal but complete**: Only essential operations
15/// - **Inline everything**: Trust LLVM to optimize
16/// - **Includes Div**: For cleaner RMS/average calculations
17///
18/// # Example: Generic Gain Plugin
19///
20/// ```ignore
21/// fn process_generic<S: Sample>(&mut self, buffer: &mut Buffer<S>) {
22///     let gain = S::from_f32(self.parameters.gain_linear());
23///     for (input, output) in buffer.zip_channels() {
24///         for (i, o) in input.iter().zip(output.iter_mut()) {
25///             *o = *i * gain;
26///         }
27///     }
28/// }
29/// ```
30pub trait Sample:
31    Copy
32    + Default
33    + Send
34    + Sync
35    + 'static
36    + Add<Output = Self>
37    + Sub<Output = Self>
38    + Mul<Output = Self>
39    + Div<Output = Self>
40    + PartialOrd
41{
42    /// Zero value (0.0).
43    const ZERO: Self;
44
45    /// Unit value (1.0).
46    const ONE: Self;
47
48    /// Convert from f32.
49    fn from_f32(value: f32) -> Self;
50
51    /// Convert to f32.
52    fn to_f32(self) -> f32;
53
54    /// Convert from f64.
55    fn from_f64(value: f64) -> Self;
56
57    /// Convert to f64.
58    fn to_f64(self) -> f64;
59
60    /// Absolute value.
61    fn abs(self) -> Self;
62
63    /// Square root.
64    fn sqrt(self) -> Self;
65
66    /// Sine.
67    fn sin(self) -> Self;
68
69    /// Cosine.
70    fn cos(self) -> Self;
71
72    /// Minimum of two values.
73    fn min(self, other: Self) -> Self;
74
75    /// Maximum of two values.
76    fn max(self, other: Self) -> Self;
77
78    /// Clamp value between min and max.
79    fn clamp(self, min: Self, max: Self) -> Self {
80        self.max(min).min(max)
81    }
82}
83
84impl Sample for f32 {
85    const ZERO: Self = 0.0;
86    const ONE: Self = 1.0;
87
88    #[inline(always)]
89    fn from_f32(value: f32) -> Self {
90        value
91    }
92
93    #[inline(always)]
94    fn to_f32(self) -> f32 {
95        self
96    }
97
98    #[inline(always)]
99    fn from_f64(value: f64) -> Self {
100        value as f32
101    }
102
103    #[inline(always)]
104    fn to_f64(self) -> f64 {
105        self as f64
106    }
107
108    #[inline(always)]
109    fn abs(self) -> Self {
110        f32::abs(self)
111    }
112
113    #[inline(always)]
114    fn sqrt(self) -> Self {
115        f32::sqrt(self)
116    }
117
118    #[inline(always)]
119    fn sin(self) -> Self {
120        f32::sin(self)
121    }
122
123    #[inline(always)]
124    fn cos(self) -> Self {
125        f32::cos(self)
126    }
127
128    #[inline(always)]
129    fn min(self, other: Self) -> Self {
130        f32::min(self, other)
131    }
132
133    #[inline(always)]
134    fn max(self, other: Self) -> Self {
135        f32::max(self, other)
136    }
137
138    #[inline(always)]
139    fn clamp(self, min: Self, max: Self) -> Self {
140        f32::clamp(self, min, max)
141    }
142}
143
144impl Sample for f64 {
145    const ZERO: Self = 0.0;
146    const ONE: Self = 1.0;
147
148    #[inline(always)]
149    fn from_f32(value: f32) -> Self {
150        value as f64
151    }
152
153    #[inline(always)]
154    fn to_f32(self) -> f32 {
155        self as f32
156    }
157
158    #[inline(always)]
159    fn from_f64(value: f64) -> Self {
160        value
161    }
162
163    #[inline(always)]
164    fn to_f64(self) -> f64 {
165        self
166    }
167
168    #[inline(always)]
169    fn abs(self) -> Self {
170        f64::abs(self)
171    }
172
173    #[inline(always)]
174    fn sqrt(self) -> Self {
175        f64::sqrt(self)
176    }
177
178    #[inline(always)]
179    fn sin(self) -> Self {
180        f64::sin(self)
181    }
182
183    #[inline(always)]
184    fn cos(self) -> Self {
185        f64::cos(self)
186    }
187
188    #[inline(always)]
189    fn min(self, other: Self) -> Self {
190        f64::min(self, other)
191    }
192
193    #[inline(always)]
194    fn max(self, other: Self) -> Self {
195        f64::max(self, other)
196    }
197
198    #[inline(always)]
199    fn clamp(self, min: Self, max: Self) -> Self {
200        f64::clamp(self, min, max)
201    }
202}