Skip to main content

rill_router/eq/
band.rs

1//! Equalizer band implementation
2
3use crate::{Filter, FilterType};
4use rill_core_dsp::filters::FilterParams;
5
6/// Type of EQ band
7#[derive(Debug, Clone, Copy, PartialEq)]
8pub enum BandType {
9    /// Peaking/parametric band
10    Peak,
11    /// Low shelf filter
12    LowShelf,
13    /// High shelf filter
14    HighShelf,
15    /// Low pass filter
16    LowPass,
17    /// High pass filter
18    HighPass,
19    /// Band pass filter
20    BandPass,
21    /// Notch filter
22    Notch,
23}
24
25impl BandType {
26    /// Get band type from string
27    #[allow(clippy::should_implement_trait)]
28    pub fn from_str(s: &str) -> Option<Self> {
29        match s {
30            "peak" => Some(BandType::Peak),
31            "lowshelf" | "low_shelf" => Some(BandType::LowShelf),
32            "highshelf" | "high_shelf" => Some(BandType::HighShelf),
33            "lowpass" | "low_pass" => Some(BandType::LowPass),
34            "highpass" | "high_pass" => Some(BandType::HighPass),
35            "bandpass" | "band_pass" => Some(BandType::BandPass),
36            "notch" => Some(BandType::Notch),
37            _ => None,
38        }
39    }
40
41    /// Get string representation
42    pub fn as_str(&self) -> &'static str {
43        match self {
44            BandType::Peak => "peak",
45            BandType::LowShelf => "low_shelf",
46            BandType::HighShelf => "high_shelf",
47            BandType::LowPass => "low_pass",
48            BandType::HighPass => "high_pass",
49            BandType::BandPass => "band_pass",
50            BandType::Notch => "notch",
51        }
52    }
53
54    /// Convert to FilterType
55    pub fn to_filter_type(&self) -> FilterType {
56        match self {
57            BandType::Peak => FilterType::Peak,
58            BandType::LowShelf => FilterType::LowShelf,
59            BandType::HighShelf => FilterType::HighShelf,
60            BandType::LowPass => FilterType::LowPass,
61            BandType::HighPass => FilterType::HighPass,
62            BandType::BandPass => FilterType::BandPass,
63            BandType::Notch => FilterType::Notch,
64        }
65    }
66}
67
68/// A single band of an equalizer
69pub struct EqBand<F: Filter<f32>> {
70    /// The filter for this band
71    pub(crate) filter: F,
72    /// Center/corner frequency in Hz
73    pub(crate) frequency: f32,
74    /// Quality factor (for peaking/parametric bands)
75    pub(crate) q: f32,
76    /// Gain in dB (for peaking/shelving bands)
77    pub(crate) gain_db: f32,
78    /// Whether this band is enabled
79    pub(crate) enabled: bool,
80    /// Band type
81    pub(crate) band_type: BandType,
82}
83
84impl<F: Filter<f32>> EqBand<F> {
85    /// Create a new EQ band
86    pub fn new(filter: F, band_type: BandType, frequency: f32, q: f32, gain_db: f32) -> Self {
87        Self {
88            filter,
89            band_type,
90            frequency,
91            q,
92            gain_db,
93            enabled: true,
94        }
95    }
96
97    /// Process a single sample through this band
98    pub fn process(&mut self, input: f32) -> f32 {
99        if !self.enabled {
100            return input;
101        }
102
103        let input_slice = [input];
104        let mut output = [0.0];
105
106        self.filter
107            .process(Some(&input_slice[..]), &mut output)
108            .unwrap();
109        output[0]
110    }
111
112    /// Update the filter with current parameters
113    pub fn update_filter(&mut self) {
114        let params = FilterParams {
115            filter_type: self.band_type.to_filter_type(),
116            cutoff: self.frequency,
117            q: self.q,
118            gain_db: self.gain_db,
119        };
120        self.filter.set_params(params);
121    }
122
123    /// Set frequency
124    pub fn set_frequency(&mut self, freq: f32) {
125        self.frequency = freq.clamp(20.0, 20000.0);
126    }
127
128    /// Set Q factor
129    pub fn set_q(&mut self, q: f32) {
130        self.q = q.clamp(0.1, 20.0);
131    }
132
133    /// Set gain in dB
134    pub fn set_gain_db(&mut self, gain: f32) {
135        self.gain_db = gain.clamp(-24.0, 24.0);
136    }
137
138    /// Enable/disable band
139    pub fn set_enabled(&mut self, enabled: bool) {
140        self.enabled = enabled;
141    }
142
143    /// Get current frequency
144    pub fn frequency(&self) -> f32 {
145        self.frequency
146    }
147
148    /// Get current Q
149    pub fn q(&self) -> f32 {
150        self.q
151    }
152
153    /// Get current gain in dB
154    pub fn gain_db(&self) -> f32 {
155        self.gain_db
156    }
157
158    /// Check if band is enabled
159    pub fn is_enabled(&self) -> bool {
160        self.enabled
161    }
162
163    /// Get band type
164    pub fn band_type(&self) -> BandType {
165        self.band_type
166    }
167
168    /// Initialize filter with sample rate
169    pub fn init(&mut self, sample_rate: f32) {
170        self.filter.init(sample_rate);
171    }
172
173    /// Reset filter state
174    pub fn reset(&mut self) {
175        self.filter.reset();
176    }
177}