mirror of
https://github.com/storytold/soundcraft.git
synced 2026-11-10 04:09:58 -06:00
Workspace for SoundCraft, a clean-room pure-Rust Pro Tools-class DAW: timebases and tempo maps, WAV/AIFF/FLAC/symphonia audio IO with peaks, SMF and MIDI ops, 26 original DSP plugins, the session model, the mix engine, ~180 registered commands with undo, a cpal player, and the agent rules (AGENTS.md, ATTRIBUTION.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
96 lines
3.4 KiB
Rust
96 lines
3.4 KiB
Rust
//! Parameter storage and const constructors for static parameter tables.
|
|
|
|
use crate::{ParamInfo, Taper, Unit};
|
|
|
|
/// A continuous parameter.
|
|
pub(crate) const fn p(id: &'static str, name: &'static str, min: f32, max: f32, default: f32, unit: Unit, taper: Taper) -> ParamInfo {
|
|
ParamInfo { id, name, min, max, default, unit, taper, choices: &[] }
|
|
}
|
|
|
|
/// A linear-taper parameter.
|
|
pub(crate) const fn lin(id: &'static str, name: &'static str, min: f32, max: f32, default: f32, unit: Unit) -> ParamInfo {
|
|
p(id, name, min, max, default, unit, Taper::Linear)
|
|
}
|
|
|
|
/// A log-taper parameter (frequencies, times, ratios).
|
|
pub(crate) const fn log(id: &'static str, name: &'static str, min: f32, max: f32, default: f32, unit: Unit) -> ParamInfo {
|
|
p(id, name, min, max, default, unit, Taper::Log)
|
|
}
|
|
|
|
/// An on/off switch.
|
|
pub(crate) const fn toggle(id: &'static str, name: &'static str, default_on: bool) -> ParamInfo {
|
|
ParamInfo { id, name, min: 0.0, max: 1.0, default: if default_on { 1.0 } else { 0.0 }, unit: Unit::Toggle, taper: Taper::Linear, choices: &[] }
|
|
}
|
|
|
|
/// A list choice; the value is the index.
|
|
pub(crate) const fn choice(id: &'static str, name: &'static str, choices: &'static [&'static str], default: usize) -> ParamInfo {
|
|
let max = if choices.is_empty() { 0.0 } else { (choices.len() - 1) as f32 };
|
|
ParamInfo { id, name, min: 0.0, max, default: default as f32, unit: Unit::Choice, taper: Taper::Linear, choices }
|
|
}
|
|
|
|
/// Current values for a plugin's parameter table (allocated once at construction).
|
|
#[derive(Debug, Clone)]
|
|
pub(crate) struct Params {
|
|
info: &'static [ParamInfo],
|
|
values: Vec<f32>,
|
|
}
|
|
|
|
impl Params {
|
|
pub(crate) fn new(info: &'static [ParamInfo]) -> Self {
|
|
Self { info, values: info.iter().map(|p| p.default).collect() }
|
|
}
|
|
|
|
/// Clamps and stores; returns the parameter index, or `None` for an unknown id.
|
|
pub(crate) fn set(&mut self, id: &str, value: f32) -> Option<usize> {
|
|
let idx = self.info.iter().position(|p| p.id == id)?;
|
|
let info = self.info.get(idx)?;
|
|
let slot = self.values.get_mut(idx)?;
|
|
*slot = info.clamp(value);
|
|
Some(idx)
|
|
}
|
|
|
|
pub(crate) fn get(&self, id: &str) -> Option<f32> {
|
|
let idx = self.info.iter().position(|p| p.id == id)?;
|
|
self.values.get(idx).copied()
|
|
}
|
|
|
|
/// Value by index (0.0 if out of range, which only a table/index mismatch could cause).
|
|
#[inline]
|
|
pub(crate) fn v(&self, idx: usize) -> f32 {
|
|
self.values.get(idx).copied().unwrap_or(0.0)
|
|
}
|
|
|
|
#[inline]
|
|
pub(crate) fn on(&self, idx: usize) -> bool {
|
|
self.v(idx) >= 0.5
|
|
}
|
|
|
|
#[inline]
|
|
pub(crate) fn choice(&self, idx: usize) -> usize {
|
|
let v = self.v(idx);
|
|
if v.is_finite() && v > 0.0 { v.round() as usize } else { 0 }
|
|
}
|
|
}
|
|
|
|
/// Implements `info`, `set_param` and `param` for a plugin struct with a `p: Params` field and an
|
|
/// `update(&mut self)` method that pushes new values to smoothers/coefficients.
|
|
macro_rules! param_plumbing {
|
|
($info:expr) => {
|
|
fn info(&self) -> &'static $crate::PluginInfo {
|
|
&$info
|
|
}
|
|
fn set_param(&mut self, id: &str, value: f32) -> bool {
|
|
if self.p.set(id, value).is_some() {
|
|
self.update();
|
|
true
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
fn param(&self, id: &str) -> Option<f32> {
|
|
self.p.get(id)
|
|
}
|
|
};
|
|
}
|
|
pub(crate) use param_plumbing;
|