feat: serial low-level shaper (Low Slope + Low Curve) before the compressor
Add a per-channel below-threshold shaper composed in series ahead of the comp: gain = low_shape(level) + comp(level + low_shape(level)). The compressor's threshold now sees the shaped level, so a Low Slope boost lifts quiet material up into compression (and a cut pulls it out). Anchored at the -60 dB silence floor. Low Curve bends the shaper toward a bounded saturation so the serial composition doesn't blow up (0 = straight line). gain_computer split into comp_gain_db + low_gain_db and composed; shared with the editor gain-curve display. Slider order rearranged to read in signal order (pre-gain -> low shaper -> compressor -> output). Defaults (slope 1, curve 0) reproduce the plain compressor; 17 tests pass. Known: the bipolar behaviour isn't final yet (milestone commit). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -68,6 +68,12 @@ pub struct CompressorParams {
|
||||
pub ratio: FloatParam,
|
||||
#[id = "knee"]
|
||||
pub knee_db: FloatParam,
|
||||
/// Low shaper slope at the silence floor (1 = unity; >1 fans up/boost, <1 fans down/cut).
|
||||
#[id = "lowslope"]
|
||||
pub low_slope: FloatParam,
|
||||
/// Low shaper curvature (0 = straight line, 1 = max bend toward a bounded saturation).
|
||||
#[id = "lowcurve"]
|
||||
pub low_curve: FloatParam,
|
||||
#[id = "attack"]
|
||||
pub attack_ms: FloatParam,
|
||||
#[id = "release"]
|
||||
@@ -168,6 +174,19 @@ impl Default for CompressorParams {
|
||||
.with_unit(" dB")
|
||||
.with_value_to_string(formatters::v2s_f32_rounded(1)),
|
||||
|
||||
low_slope: FloatParam::new(
|
||||
"Low Slope",
|
||||
1.0,
|
||||
FloatRange::Skewed { min: 0.5, max: 3.0, factor: FloatRange::skew_factor(-1.0) },
|
||||
)
|
||||
.with_smoother(SmoothingStyle::Linear(20.0))
|
||||
.with_value_to_string(formatters::v2s_f32_rounded(2)),
|
||||
|
||||
low_curve: FloatParam::new("Low Curve", 0.0, FloatRange::Linear { min: 0.0, max: 1.0 })
|
||||
.with_smoother(SmoothingStyle::Linear(20.0))
|
||||
.with_value_to_string(formatters::v2s_f32_percentage(0))
|
||||
.with_string_to_value(formatters::s2v_f32_percentage()),
|
||||
|
||||
attack_ms: FloatParam::new(
|
||||
"Attack",
|
||||
10.0,
|
||||
@@ -207,6 +226,8 @@ pub fn build_settings(
|
||||
threshold_db: p.threshold_db.value(),
|
||||
ratio: p.ratio.value(),
|
||||
knee_db: p.knee_db.value(),
|
||||
low_slope: p.low_slope.value(),
|
||||
low_curve: p.low_curve.value(),
|
||||
attack_coef: Compressor::time_to_coef(p.attack_ms.value(), sample_rate),
|
||||
release_coef: Compressor::time_to_coef(p.release_ms.value(), sample_rate),
|
||||
makeup_db: 0.0,
|
||||
|
||||
Reference in New Issue
Block a user