#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ChannelMode {
Mono,
Stereo,
}
#[derive(Debug, Clone)]
pub struct ChannelConfig {
pub name: String,
pub mode: ChannelMode,
pub volume: f32,
pub pan: f32,
pub muted: bool,
pub soloed: bool,
}
impl Default for ChannelConfig {
fn default() -> Self {
Self {
name: "Channel".to_string(),
mode: ChannelMode::Mono,
volume: 1.0,
pan: 0.0,
muted: false,
soloed: false,
}
}
}
#[derive(Debug, Clone)]
pub struct ChannelState {
config: ChannelConfig,
current_volume: f32,
current_pan: f32,
smoothing: f32,
}
impl ChannelState {
pub fn new(config: ChannelConfig) -> Self {
let current_volume = config.volume;
let current_pan = config.pan;
Self {
config,
current_volume,
current_pan,
smoothing: 0.1, }
}
pub fn process_mono(&mut self, input: f32) -> (f32, f32) {
if self.config.muted {
return (0.0, 0.0);
}
self.current_volume += (self.config.volume - self.current_volume) * self.smoothing;
self.current_pan += (self.config.pan - self.current_pan) * self.smoothing;
let (left_gain, right_gain) = if self.current_pan <= 0.0 {
(1.0, 1.0 + self.current_pan)
} else {
(1.0 - self.current_pan, 1.0)
};
let left_out = input * self.current_volume * left_gain;
let right_out = input * self.current_volume * right_gain;
(left_out, right_out)
}
pub fn process_stereo(&mut self, left: f32, right: f32) -> (f32, f32) {
if self.config.muted {
return (0.0, 0.0);
}
self.current_volume += (self.config.volume - self.current_volume) * self.smoothing;
self.current_pan += (self.config.pan - self.current_pan) * self.smoothing;
let (left_gain, right_gain) = if self.current_pan <= 0.0 {
(1.0, 1.0 + self.current_pan)
} else {
(1.0 - self.current_pan, 1.0)
};
let left_out = left * self.current_volume * left_gain;
let right_out = right * self.current_volume * right_gain;
(left_out, right_out)
}
pub fn set_config(&mut self, config: ChannelConfig) {
self.config = config;
}
pub fn config(&self) -> &ChannelConfig {
&self.config
}
pub fn set_smoothing(&mut self, factor: f32) {
self.smoothing = factor.clamp(0.0, 1.0);
}
pub fn current_volume(&self) -> f32 {
self.current_volume
}
pub fn current_pan(&self) -> f32 {
self.current_pan
}
}