Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion src/gui/amp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ use crate::sim::stages::{
clipper::ClipperType,
compressor::CompressorStage,
filter::{FilterStage, FilterType},
level::LevelStage,
poweramp::{PowerAmpStage, PowerAmpType},
preamp::PreampStage,
tonestack::{ToneStackModel, ToneStackStage},
};

use crate::gui::widgets::{compressor, filter, poweramp, preamp, tonestack};
use crate::gui::widgets::{compressor, filter, level, poweramp, preamp, tonestack};

pub fn start(processor_manager: ProcessorManager) -> iced::Result {
iced::application("Rustortion", AmplifierGui::update, AmplifierGui::view)
Expand All @@ -40,6 +41,7 @@ pub enum StageType {
Compressor,
ToneStack,
PowerAmp,
Level,
}

impl std::fmt::Display for StageType {
Expand All @@ -50,6 +52,7 @@ impl std::fmt::Display for StageType {
StageType::Compressor => write!(f, "Compressor"),
StageType::ToneStack => write!(f, "Tone Stack"),
StageType::PowerAmp => write!(f, "Power Amp"),
StageType::Level => write!(f, "Level"),
}
}
}
Expand All @@ -62,6 +65,7 @@ pub enum StageConfig {
Compressor(CompressorConfig),
ToneStack(ToneStackConfig),
PowerAmp(PowerAmpConfig),
Level(LevelConfig),
}

#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -103,6 +107,11 @@ pub struct PowerAmpConfig {
pub sag: f32,
}

#[derive(Debug, Clone, Copy)]
pub struct LevelConfig {
pub gain: f32,
}

// Default implementations
impl Default for FilterConfig {
fn default() -> Self {
Expand Down Expand Up @@ -158,6 +167,12 @@ impl Default for PowerAmpConfig {
}
}

impl Default for LevelConfig {
fn default() -> Self {
Self { gain: 1.0 }
}
}

// Main GUI state
#[derive(Debug)]
struct AmplifierGui {
Expand Down Expand Up @@ -203,6 +218,9 @@ pub enum Message {
PowerAmpTypeChanged(usize, PowerAmpType),
PowerAmpDriveChanged(usize, f32),
PowerAmpSagChanged(usize, f32),

// Level messages
LevelGainChanged(usize, f32),
}

// Application implementation
Expand All @@ -218,6 +236,7 @@ impl AmplifierGui {
StageType::Compressor => StageConfig::Compressor(CompressorConfig::default()),
StageType::ToneStack => StageConfig::ToneStack(ToneStackConfig::default()),
StageType::PowerAmp => StageConfig::PowerAmp(PowerAmpConfig::default()),
StageType::Level => StageConfig::Level(LevelConfig::default()),
};
self.stages.push(new_stage);
should_update_chain = true;
Expand Down Expand Up @@ -367,6 +386,14 @@ impl AmplifierGui {
}
should_update_chain = true;
}

// Level updates
Message::LevelGainChanged(idx, gain) => {
if let Some(StageConfig::Level(cfg)) = self.stages.get_mut(idx) {
cfg.gain = gain;
}
should_update_chain = true;
}
}

if should_update_chain {
Expand Down Expand Up @@ -399,6 +426,7 @@ impl AmplifierGui {
StageConfig::PowerAmp(cfg) => {
poweramp::poweramp_widget(idx, cfg, self.stages.len())
}
StageConfig::Level(cfg) => level::level_widget(idx, cfg, self.stages.len()),
};
list = list.push(widget);
}
Expand All @@ -411,6 +439,7 @@ impl AmplifierGui {
StageType::Compressor,
StageType::ToneStack,
StageType::PowerAmp,
StageType::Level,
];

let footer = row![
Expand Down Expand Up @@ -487,6 +516,12 @@ impl AmplifierGui {
sample_rate,
)));
}
StageConfig::Level(cfg) => {
chain.add_stage(Box::new(LevelStage::new(
&format!("Level {}", idx),
cfg.gain,
)));
}
}
}

Expand Down
29 changes: 29 additions & 0 deletions src/gui/widgets/level.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use super::{labeled_slider, stage_header};
use crate::gui::amp::{LevelConfig, Message};
use iced::widget::{column, container};
use iced::{Element, Length};

const HEADER_TEXT: &str = "Level";

pub fn level_widget(idx: usize, cfg: &LevelConfig, total_stages: usize) -> Element<Message> {
let header = stage_header(HEADER_TEXT, idx, total_stages);

let body = column![labeled_slider(
"Gain",
0.0..=2.0,
cfg.gain,
move |v| Message::LevelGainChanged(idx, v),
|v| format!("{:.2}", v),
0.05
),]
.spacing(5);

container(column![header, body].spacing(5).padding(10))
.width(Length::Fill)
.style(|theme: &iced::Theme| {
container::Style::default()
.background(theme.palette().background)
.border(iced::Border::default().rounded(5))
})
.into()
}
1 change: 1 addition & 0 deletions src/gui/widgets/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod compressor;
pub mod filter;
pub mod level;
pub mod poweramp;
pub mod preamp;
pub mod tonestack;
Expand Down
47 changes: 47 additions & 0 deletions src/sim/stages/level.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use crate::sim::stages::Stage;

pub struct LevelStage {
name: String,
gain: f32,
}

impl LevelStage {
pub fn new(name: &str, gain: f32) -> Self {
Self {
name: name.into(),
gain,
}
}
}

impl Stage for LevelStage {
fn name(&self) -> &str {
&self.name
}

fn process(&mut self, input: f32) -> f32 {
input * self.gain
}

fn set_parameter(&mut self, name: &str, value: f32) -> Result<(), &'static str> {
match name {
"gain" => {
if (0.0..=2.0).contains(&value) {
self.gain = value;
Ok(())
} else {
Err("Gain must be between 0.0 and 2.0")
}
}
_ => Err("Unknown parameter"),
}
}

// Get a parameter value by name
fn get_parameter(&self, name: &str) -> Result<f32, &'static str> {
match name {
"gain" => Ok(self.gain),
_ => Err("Unknown parameter name"),
}
}
}
5 changes: 1 addition & 4 deletions src/sim/stages/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod clipper;
pub mod compressor;
pub mod filter;
pub mod level;
pub mod poweramp;
pub mod preamp;
pub mod tonestack;
Expand All @@ -10,15 +11,11 @@ pub trait Stage: Send + Sync + 'static {
// Process a single sample through this stage
fn process(&mut self, input: f32) -> f32;

#[allow(dead_code)]
// Set a parameter value by name
fn set_parameter(&mut self, name: &str, value: f32) -> Result<(), &'static str>;

#[allow(dead_code)]
// Get a parameter value by name
fn get_parameter(&self, name: &str) -> Result<f32, &'static str>;

#[allow(dead_code)]
// Get the name of this stage
fn name(&self) -> &str;
}