diff --git a/src/delay_tap.rs b/src/delay_tap.rs index 8176fbd..d959d1c 100644 --- a/src/delay_tap.rs +++ b/src/delay_tap.rs @@ -23,7 +23,7 @@ pub struct DelayTap { pub amp_envelope: Smoother, /// If this delay tap has polyphonic gain modulation applied, then this contains the normalized /// offset and a smoother. - pub delay_tap_gain: Option<(f32, Smoother)>, + pub per_tap_gain: Option<(f32, Smoother)>, /// Are we currently muting? To determine if we need to trigger the amp envelope, pub is_muted: bool, diff --git a/src/editor.rs b/src/editor.rs index abae036..f22c71c 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -386,12 +386,8 @@ impl View for DelayGraph { let output_meter = self.output_meter.clone(); // Compute the time scaling factor - let target_time_scaling_factor = Self::compute_time_scaling_factor( - params.clone(), - bounds.w, - border_width, - outline_width, - ); + let target_time_scaling_factor = + Self::compute_time_scaling_factor(¶ms, bounds.w, border_width, outline_width); let time_scaling_factor = Self::gui_smooth( target_time_scaling_factor, @@ -401,7 +397,7 @@ impl View for DelayGraph { Self::draw_background(canvas, bounds, background_color); Self::draw_delay_times_as_lines( canvas, - params.clone(), + ¶ms, bounds, border_color, border_width, @@ -409,7 +405,7 @@ impl View for DelayGraph { ); Self::draw_time_line( canvas, - params.clone(), + ¶ms, bounds, selection_color, outline_width, @@ -418,10 +414,10 @@ impl View for DelayGraph { ); Self::draw_tap_velocities( canvas, - params.clone(), - tap_meters.clone(), - input_meter.clone(), - output_meter.clone(), + ¶ms, + &tap_meters, + &input_meter, + &output_meter, bounds, outline_color, border_color, @@ -431,7 +427,7 @@ impl View for DelayGraph { ); Self::draw_tap_notes_and_pans( canvas, - params.clone(), + ¶ms, bounds, selection_color, outline_width, @@ -484,7 +480,7 @@ impl DelayGraph { } fn compute_time_scaling_factor( - params: Arc, + params: &Arc, rect_width: f32, border_width: f32, outline_width: f32, @@ -523,8 +519,8 @@ impl DelayGraph { (total_delay / denominator).recip() } - /// Smoothly updates the value stored within an AtomicF32 based on a target value. - /// If the current value is f32::MAX, it initializes with the target value. + /// Smoothly updates the value stored within an `AtomicF32` based on a target value. + /// If the current value is `f32::MAX`, it initializes with the target value. fn gui_smooth(target_value: f32, atomic_value: &AtomicF32) -> f32 { // Define the threshold relative to the target value let threshold = 0.001 * target_value.abs(); @@ -546,7 +542,7 @@ impl DelayGraph { // Compute the smoothed value let smoothed_value = current_value.mul_add( ZOOM_SMOOTH_POLE, - target_value - target_value * ZOOM_SMOOTH_POLE, + target_value.mul_add(-ZOOM_SMOOTH_POLE, target_value), ); // Store the change @@ -558,7 +554,7 @@ impl DelayGraph { fn draw_delay_times_as_lines( canvas: &mut Canvas, - params: Arc, + params: &Arc, bounds: BoundingBox, border_color: vg::Color, border_width: f32, @@ -566,7 +562,7 @@ impl DelayGraph { ) { let mut path = vg::Path::new(); - let current_tap_value = params.current_tap.load(Ordering::SeqCst) as usize; + let current_tap_value = params.current_tap.load(Ordering::SeqCst); for i in 0..current_tap_value { let delay_time_value = params.delay_times[i].load(Ordering::SeqCst) as f32; @@ -594,7 +590,7 @@ impl DelayGraph { fn draw_time_line( canvas: &mut Canvas, - params: Arc, + params: &Arc, bounds: BoundingBox, color: vg::Color, line_width: f32, @@ -617,7 +613,7 @@ impl DelayGraph { if current_time > max_delay_time { // Compute offset using mul_add for precision and performance - let x_offset = current_time as f32 * scaling_factor + border_width * 0.5; + let x_offset = (current_time as f32).mul_add(scaling_factor, border_width * 0.5); // Calculate y_move using mul_add let y_move = border_width.mul_add(-0.5, bounds.y + bounds.h); @@ -633,10 +629,10 @@ impl DelayGraph { fn draw_tap_velocities( canvas: &mut Canvas, - params: Arc, - tap_meters: Arc, - input_meter: Arc, - output_meter: Arc, + params: &Arc, + tap_meters: &Arc, + input_meter: &Arc, + output_meter: &Arc, bounds: BoundingBox, velocity_color: vg::Color, meter_color: vg::Color, @@ -661,11 +657,11 @@ impl DelayGraph { let mut path = vg::Path::new(); path.move_to( - bounds.x + x_offset - (line_width * 0.75), + line_width.mul_add(-0.75, bounds.x + x_offset), bounds.y + bounds.h - velocity_height, ); path.line_to( - bounds.x + x_offset - (line_width * 0.75), + line_width.mul_add(-0.75, bounds.x + x_offset), bounds.y + bounds.h, ); @@ -676,11 +672,11 @@ impl DelayGraph { path = vg::Path::new(); path.move_to( - bounds.x + x_offset + (line_width * 0.75), + line_width.mul_add(0.75, bounds.x + x_offset), bounds.y + bounds.h - meter_height, ); path.line_to( - bounds.x + x_offset + (line_width * 0.75), + line_width.mul_add(0.75, bounds.x + x_offset), bounds.y + bounds.h, ); @@ -698,10 +694,10 @@ impl DelayGraph { }; let mut path = vg::Path::new(); path.move_to( - bounds.x + (line_width * 0.75), + line_width.mul_add(0.75, bounds.x), bounds.y + bounds.h - input_height, ); - path.line_to(bounds.x + (line_width * 0.75), bounds.y + bounds.h); + path.line_to(line_width.mul_add(0.75, bounds.x), bounds.y + bounds.h); canvas.stroke_path( &path, &vg::Paint::color(meter_color).with_line_width(line_width * 1.5), @@ -715,11 +711,11 @@ impl DelayGraph { }; path = vg::Path::new(); path.move_to( - bounds.x + bounds.w - (line_width * 0.75), + line_width.mul_add(-0.75, bounds.x + bounds.w), bounds.y + bounds.h - output_height, ); path.line_to( - bounds.x + bounds.w - (line_width * 0.75), + line_width.mul_add(-0.75, bounds.x + bounds.w), bounds.y + bounds.h, ); canvas.stroke_path( @@ -730,7 +726,7 @@ impl DelayGraph { fn draw_tap_notes_and_pans( canvas: &mut Canvas, - params: Arc, + params: &Arc, bounds: BoundingBox, color: vg::Color, line_width: f32, @@ -776,14 +772,13 @@ impl DelayGraph { let margin = 10.0 * line_width; let available_height = (-(margin + note_size + border_width)).mul_add(2.0, bounds.h); - fn get_normalized_value(value: u8, min: f32, max: f32) -> f32 { + let get_normalized_value = |value: u8, min: f32, max: f32| -> f32 { if max == min { value as f32 / 127.0 } else { (value as f32 - min) / (max - min) } - } - + }; // Draw half a note for panning center if first_note != NO_LEARNED_NOTE { let normalized_panning_center = @@ -1015,7 +1010,7 @@ impl ActionTrigger { }) } - pub fn start_learning(&mut self) { + pub fn start_learning(&self) { let index = self.learning_index.load(Ordering::SeqCst); self.learned_notes .store(index, self.last_learned_notes.load(index)); @@ -1058,7 +1053,7 @@ impl ActionTrigger { } } - fn get_note_color(note_nr: u8) -> Color { + const fn get_note_color(note_nr: u8) -> Color { if note_nr == LEARNING { // blue Color::rgb(88, 121, 175) diff --git a/src/lib.rs b/src/lib.rs index 6e76233..8d4c470 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,11 @@ https://github.com/neodsp/simper-filter #![allow(clippy::cast_possible_truncation)] #![allow(clippy::cast_possible_wrap)] #![allow(clippy::cast_sign_loss)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::cast_lossless)] +#![allow(clippy::cognitive_complexity)] +#![allow(clippy::type_complexity)] #![feature(portable_simd)] #![feature(get_mut_unchecked)] use array_init::array_init; @@ -94,7 +99,7 @@ struct Del2 { dry_wet: Box<[f32]>, output_gain: Box<[f32]>, global_drive: Box<[f32]>, - delay_tap_gain: Box<[f32]>, + per_tap_gain: Box<[f32]>, delay_tap_amp_envelope: Box<[f32]>, // N counters to know where in the fade in we are: 0 is the start @@ -354,8 +359,7 @@ impl TapsParams { } } -/// This struct contains the parameters for either the high or low tap. The `Params` -/// trait is implemented manually to avoid copy-pasting parameters for both types of compressor. +/// This struct contains the parameters for either the high or low tap. /// Both versions will have a parameter ID and a parameter name prefix to distinguish them. #[derive(Params)] pub struct FilterGuiParams { @@ -486,7 +490,7 @@ impl Default for Del2 { dry_wet: f32::default_boxed_array::(), output_gain: f32::default_boxed_array::(), global_drive: f32::default_boxed_array::(), - delay_tap_gain: f32::default_boxed_array::(), + per_tap_gain: f32::default_boxed_array::(), delay_tap_amp_envelope: f32::default_boxed_array::(), amp_envelopes, @@ -771,7 +775,7 @@ impl Plugin for Del2 { .gain .preview_modulated(normalized_offset); let (_, smoother) = - delay_tap.delay_tap_gain.get_or_insert_with(|| { + delay_tap.per_tap_gain.get_or_insert_with(|| { ( normalized_offset, self.params.gain.smoothed.clone(), @@ -813,16 +817,11 @@ impl Plugin for Del2 { { match poly_modulation_id { GAIN_POLY_MOD_ID => { - let (normalized_offset, smoother) = - match delay_tap.delay_tap_gain.as_mut() { - Some((o, s)) => (o, s), - // If the delay tap does not have existing - // polyphonic modulation, then there's nothing - // to do here. The global automation/monophonic - // modulation has already been taken care of by - // the framework. - None => continue, - }; + let Some((normalized_offset, smoother)) = + delay_tap.per_tap_gain.as_mut() + else { + continue; + }; let target_plain_value = self.params.gain.preview_plain( normalized_value + *normalized_offset, @@ -936,10 +935,10 @@ impl Plugin for Del2 { // Depending on whether the delay tap has polyphonic modulation applied to it, // either the global parameter values are used, or the delay tap's smoother is used // to generate unique modulated values for that delay tap - let gain = match &delay_tap.delay_tap_gain { + let gain = match &delay_tap.per_tap_gain { Some((_, smoother)) => { - smoother.next_block(&mut self.delay_tap_gain, block_len); - &self.delay_tap_gain + smoother.next_block(&mut self.per_tap_gain, block_len); + &self.per_tap_gain } None => &self.gain, }; @@ -1568,7 +1567,7 @@ impl Del2 { velocity: 1.0, releasing: false, amp_envelope: Smoother::none(), - delay_tap_gain: None, + per_tap_gain: None, is_muted: false, tap_index: NUM_TAPS, // Initial out-of-bounds safety index }; @@ -1588,7 +1587,7 @@ impl Del2 { let oldest_delay_tap = self .delay_taps .iter_mut() - .min_by_key(|t| t.as_ref().map(|tap| tap.internal_id).unwrap_or(u64::MAX)) + .min_by_key(|t| t.as_ref().map_or(u64::MAX, |tap| tap.internal_id)) .expect("At least one delay tap should exist"); *oldest_delay_tap = Some(new_delay_tap); @@ -2085,16 +2084,6 @@ impl LastPlayedNotes { .store(index, self.current_sequence.fetch_add(1, Ordering::SeqCst)); self.active_notes.store(index, true); // Mark as active break; - } else { - // Overwrite the oldest active note - let oldest_index = (0..8).min_by_key(|&i| self.sequence.load(i)).unwrap(); - self.notes.store(oldest_index, note); - self.sequence.store( - oldest_index, - self.current_sequence.fetch_add(1, Ordering::SeqCst), - ); - self.active_notes.store(oldest_index, true); // Mark as active - break; } } }