Skip to content

Commit

Permalink
smooth gain in the lin domain
Browse files Browse the repository at this point in the history
for less calls to db_to_gain_fast()
  • Loading branch information
magnetophon committed Dec 5, 2024
1 parent 5c9dd7d commit da09785
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 41 deletions.
12 changes: 8 additions & 4 deletions src/delay_tap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ pub struct DelayTap {
// for modulated delay times from panning
pub smoothed_offset_l: Smoother<f32>,
pub smoothed_offset_r: Smoother<f32>,
pub eq_gain: Smoother<f32>,
pub pan_gain: Smoother<f32>,
pub eq_gain_l: Smoother<f32>,
pub eq_gain_r: Smoother<f32>,
pub pan_gain_l: Smoother<f32>,
pub pan_gain_r: Smoother<f32>,
/// The note's key/note, in `0..128`. Only used for the delay tap terminated event.
pub note: u8,
/// The note's velocity. This is used to interpollate it's dsp parameters.
Expand Down Expand Up @@ -57,8 +59,10 @@ impl DelayTap {
delay_time: 0,
smoothed_offset_l: Smoother::new(SmoothingStyle::Linear(77.0)),
smoothed_offset_r: Smoother::new(SmoothingStyle::Linear(77.0)),
eq_gain: Smoother::new(SmoothingStyle::Linear(77.0)),
pan_gain: Smoother::new(SmoothingStyle::Linear(77.0)),
eq_gain_l: Smoother::new(SmoothingStyle::Linear(77.0)),
eq_gain_r: Smoother::new(SmoothingStyle::Linear(77.0)),
pan_gain_l: Smoother::new(SmoothingStyle::Linear(77.0)),
pan_gain_r: Smoother::new(SmoothingStyle::Linear(77.0)),
note: NO_LEARNED_NOTE,
velocity: 0.0,
releasing: false,
Expand Down
83 changes: 46 additions & 37 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ use nih_plug::prelude::*;
use nih_plug_vizia::ViziaState;
use std::ops::Index;
use std::simd::f32x4;
use std::simd::num::SimdFloat;
use std::sync::atomic::{
AtomicBool, AtomicI32, AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering,
};
Expand Down Expand Up @@ -106,8 +105,10 @@ pub struct Del2 {
delay_tap_amp_envelope: Box<[f32]>,
delay_tap_smoothed_offset_l: Box<[f32]>,
delay_tap_smoothed_offset_r: Box<[f32]>,
delay_tap_eq_gain: Box<[f32]>,
delay_tap_pan_gain: Box<[f32]>,
delay_tap_eq_gain_l: Box<[f32]>,
delay_tap_eq_gain_r: Box<[f32]>,
delay_tap_pan_gain_l: Box<[f32]>,
delay_tap_pan_gain_r: Box<[f32]>,

peak_meter_decay_weight: f32,
input_meter: Arc<AtomicF32>,
Expand Down Expand Up @@ -504,8 +505,10 @@ impl Default for Del2 {
delay_tap_amp_envelope: f32::default_boxed_array::<MAX_BLOCK_SIZE>(),
delay_tap_smoothed_offset_l: f32::default_boxed_array::<MAX_BLOCK_SIZE>(),
delay_tap_smoothed_offset_r: f32::default_boxed_array::<MAX_BLOCK_SIZE>(),
delay_tap_eq_gain: f32::default_boxed_array::<MAX_BLOCK_SIZE>(),
delay_tap_pan_gain: f32::default_boxed_array::<MAX_BLOCK_SIZE>(),
delay_tap_eq_gain_l: f32::default_boxed_array::<MAX_BLOCK_SIZE>(),
delay_tap_eq_gain_r: f32::default_boxed_array::<MAX_BLOCK_SIZE>(),
delay_tap_pan_gain_l: f32::default_boxed_array::<MAX_BLOCK_SIZE>(),
delay_tap_pan_gain_r: f32::default_boxed_array::<MAX_BLOCK_SIZE>(),

peak_meter_decay_weight: 1.0,
input_meter: Arc::new(AtomicF32::new(util::MINUS_INFINITY_DB)),
Expand Down Expand Up @@ -883,10 +886,25 @@ impl Plugin for Del2 {
.smoothed_offset_r
.set_target(sample_rate, offset_r);

let eq_gain_target = MIN_EQ_GAIN * pan;
delay_tap.eq_gain.set_target(sample_rate, eq_gain_target);
let pan_gain_target = MIN_PAN_GAIN * pan;
delay_tap.pan_gain.set_target(sample_rate, pan_gain_target);
let eq_gain_target_l = util::db_to_gain_fast((MIN_EQ_GAIN * pan).min(0.0));
delay_tap
.eq_gain_l
.set_target(sample_rate, eq_gain_target_l);
let eq_gain_target_r =
util::db_to_gain_fast((MIN_EQ_GAIN * pan * -1.0).min(0.0));
delay_tap
.eq_gain_r
.set_target(sample_rate, eq_gain_target_r);
let pan_gain_target_l =
util::db_to_gain_fast((MIN_PAN_GAIN * pan).min(0.0));
delay_tap
.pan_gain_l
.set_target(sample_rate, pan_gain_target_l);
let pan_gain_target_r =
util::db_to_gain_fast((MIN_PAN_GAIN * pan * -1.0).min(0.0));
delay_tap
.pan_gain_r
.set_target(sample_rate, pan_gain_target_r);

let delay_time = delay_tap.delay_time as isize;
let write_index = self.delay_write_index;
Expand All @@ -909,11 +927,17 @@ impl Plugin for Del2 {
.smoothed_offset_r
.next_block(&mut self.delay_tap_smoothed_offset_r, block_len);
delay_tap
.eq_gain
.next_block(&mut self.delay_tap_eq_gain, block_len);
.eq_gain_l
.next_block(&mut self.delay_tap_eq_gain_l, block_len);
delay_tap
.eq_gain_r
.next_block(&mut self.delay_tap_eq_gain_r, block_len);
delay_tap
.pan_gain
.next_block(&mut self.delay_tap_pan_gain, block_len);
.pan_gain_l
.next_block(&mut self.delay_tap_pan_gain_l, block_len);
delay_tap
.pan_gain_r
.next_block(&mut self.delay_tap_pan_gain_r, block_len);
for (value_idx, sample_idx) in (block_start..block_end).enumerate() {
let pre_filter_gain = global_drive[value_idx];
// if self.delay_tap_amp_envelope[value_idx] != 1.0 && self.delay_tap_amp_envelope[value_idx] != 0.0 {
Expand All @@ -939,31 +963,17 @@ impl Plugin for Del2 {
delay_tap.delayed_audio_r.get(i + 1).copied().unwrap_or(0.0),
]);

let (eq_gain_1, eq_gain_2) = (
self.delay_tap_eq_gain[i],
self.delay_tap_eq_gain.get(i + 1).copied().unwrap_or(0.0),
);

// Prepare inputs and perform min operation using SIMD
let gain_values =
f32x4::from_array([eq_gain_1, -eq_gain_1, eq_gain_2, -eq_gain_2]);
let clamped_gain_values = gain_values
.simd_clamp(f32x4::splat(-std::f32::MAX), f32x4::splat(0.0));

// Apply db_to_gain_fast using direct lane access
let mut lin_gains = [0.0; 4];
for i in 0..4 {
lin_gains[i] = util::db_to_gain_fast(clamped_gain_values[i]);
}

let eq_gain_frame = f32x4::from_array(lin_gains);
// let eq_gain_frame = f32x4::from_array(lin_gains.to_array());
let gain_values = f32x4::from_array([
self.delay_tap_eq_gain_l[i],
self.delay_tap_eq_gain_r[i],
self.delay_tap_eq_gain_l.get(i + 1).copied().unwrap_or(1.0),
self.delay_tap_eq_gain_r.get(i + 1).copied().unwrap_or(1.0),
]);

// let frame_out = *delay_tap.ladders.tick_pivotal(frame).as_array();
let frame_filtered = *delay_tap.ladders.tick_pivotal(frame).as_array();
let frame_out = delay_tap
.shelving_eq
.highshelf(frame_filtered.into(), eq_gain_frame);
.highshelf(frame_filtered.into(), gain_values);

// let frame_out = *delay_tap.ladders.tick_linear(frame).as_array();
delay_tap.delayed_audio_l[i] = frame_out[0];
Expand All @@ -981,13 +991,12 @@ impl Plugin for Del2 {
* wet_gain[value_idx]
* self.delay_tap_amp_envelope[value_idx]
/ (drive * global_drive[value_idx]);
let pan_gain = self.delay_tap_pan_gain[value_idx];
let left = delay_tap.delayed_audio_l[sample_idx]
* post_filter_gain
* util::db_to_gain_fast(pan_gain.min(0.0));
* self.delay_tap_pan_gain_l[value_idx];
let right = delay_tap.delayed_audio_r[sample_idx]
* post_filter_gain
* util::db_to_gain_fast((pan_gain * -1.0).min(0.0));
* self.delay_tap_pan_gain_r[value_idx];
output[0][sample_idx] += left;
output[1][sample_idx] += right;
amplitude += (left.abs() + right.abs()) * 0.5;
Expand Down

0 comments on commit da09785

Please sign in to comment.