Skip to content

Commit

Permalink
map delay_taps index to tap_meter index
Browse files Browse the repository at this point in the history
  • Loading branch information
magnetophon committed Nov 20, 2024
1 parent edc1ff5 commit ca8ddc0
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 14 deletions.
9 changes: 7 additions & 2 deletions src/delay_tap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub struct DelayTap {
/// Is set to true when the tap is created and false is created
/// and false when the amplitude envelope hits 0 while the note is releasing.
pub is_alive: bool,
/// Only used for indexing into tap_meters
pub tap_index: usize,
}

impl DelayTap {
Expand All @@ -56,8 +58,9 @@ impl DelayTap {
note: NO_LEARNED_NOTE,
velocity: 0.0,
releasing: false,
is_muted: false,
is_muted: true,
is_alive: false,
tap_index: 0,
}
}

Expand All @@ -68,14 +71,16 @@ impl DelayTap {
delay_time: u32,
note: u8,
velocity: f32,
index: usize,
) {
self.amp_envelope = amp_envelope;
self.internal_id = internal_id;
self.delay_time = delay_time;
self.note = note;
self.velocity = velocity;
self.releasing = false;
self.is_muted = false;
self.is_muted = true;
self.is_alive = true;
self.tap_index = index;
}
}
22 changes: 15 additions & 7 deletions src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ use nih_plug_vizia::{
};

use crate::{
format_time, util, AtomicBoolArray, AtomicByteArray, AtomicF32, AtomicF32Array, Del2Params,
LastPlayedNotes, CLEAR_TAPS, LEARNING, LOCK_TAPS, MUTE_IN, MUTE_OUT, NO_LEARNED_NOTE, NUM_TAPS,
format_time, util, AtomicBoolArray, AtomicByteArray, AtomicF32, AtomicF32Array,
AtomicUsizeArray, Del2Params, LastPlayedNotes, CLEAR_TAPS, LEARNING, LOCK_TAPS, MUTE_IN,
MUTE_OUT, NO_LEARNED_NOTE, NUM_TAPS,
};

const GUI_SMOOTHING_DECAY_MS: f64 = 240.0;
Expand All @@ -34,6 +35,7 @@ pub struct Data {
pub input_meter: Arc<AtomicF32>,
pub output_meter: Arc<AtomicF32>,
pub tap_meters: Arc<AtomicF32Array>,
pub meter_indexes: Arc<AtomicUsizeArray>,
pub is_learning: Arc<AtomicBool>,
pub learning_index: Arc<AtomicUsize>,
pub learned_notes: Arc<AtomicByteArray>,
Expand Down Expand Up @@ -284,7 +286,7 @@ pub fn create(editor_data: Data, editor_state: Arc<ViziaState>) -> Option<Box<dy
.class("parameters");
VStack::new(cx, |cx| {
ZStack::new(cx, |cx| {
DelayGraph::new(cx, Data::params, Data::tap_meters, Data::input_meter, Data::output_meter)
DelayGraph::new(cx, Data::params, Data::tap_meters, Data::input_meter, Data::output_meter, Data::meter_indexes)
// .overflow(Overflow::Hidden)
;
Label::new(cx, "DEL2").class("plugin-name");
Expand All @@ -304,6 +306,7 @@ pub struct DelayGraph {
tap_meters: Arc<AtomicF32Array>,
input_meter: Arc<AtomicF32>,
output_meter: Arc<AtomicF32>,
meter_indexes: Arc<AtomicUsizeArray>,
}

// TODO: add grid to show bars & beats
Expand All @@ -314,8 +317,6 @@ impl View for DelayGraph {
}

fn draw(&self, draw_context: &mut DrawContext, canvas: &mut Canvas) {
// let params = self.params.clone();

let params = self.params.clone();
let bounds = draw_context.bounds();

Expand Down Expand Up @@ -343,6 +344,7 @@ impl View for DelayGraph {
);

let first_note = params.first_note.load(Ordering::SeqCst);
let meter_indexes = self.meter_indexes.clone();

// Draw components
Self::draw_background(canvas, bounds, background_color);
Expand All @@ -360,6 +362,7 @@ impl View for DelayGraph {
canvas,
&params,
&tap_meters,
&meter_indexes,
&input_meter,
&output_meter,
bounds,
Expand Down Expand Up @@ -397,24 +400,27 @@ impl View for DelayGraph {
}

impl DelayGraph {
fn new<ParamsL, TapMetersL, InputMeterL, OutputMeterL>(
fn new<ParamsL, TapMetersL, InputMeterL, OutputMeterL, MeterIndexL>(
cx: &mut Context,
params: ParamsL,
tap_meters: TapMetersL,
input_meter: InputMeterL,
output_meter: OutputMeterL,
meter_indexes: MeterIndexL,
) -> Handle<Self>
where
ParamsL: Lens<Target = Arc<Del2Params>>,
TapMetersL: Lens<Target = Arc<AtomicF32Array>>,
InputMeterL: Lens<Target = Arc<AtomicF32>>,
OutputMeterL: Lens<Target = Arc<AtomicF32>>,
MeterIndexL: Lens<Target = Arc<AtomicUsizeArray>>,
{
Self {
params: params.get(cx),
tap_meters: tap_meters.get(cx),
input_meter: input_meter.get(cx),
output_meter: output_meter.get(cx),
meter_indexes: meter_indexes.get(cx),
}
.build(cx, |cx| {
Label::new(
Expand Down Expand Up @@ -659,6 +665,7 @@ impl DelayGraph {
canvas: &mut Canvas,
params: &Arc<Del2Params>,
tap_meters: &Arc<AtomicF32Array>,
meter_indexes: &Arc<AtomicUsizeArray>,
input_meter: &Arc<AtomicF32>,
output_meter: &Arc<AtomicF32>,
bounds: BoundingBox,
Expand All @@ -677,7 +684,8 @@ impl DelayGraph {
let velocity_value = params.velocities[i].load(Ordering::SeqCst);
let velocity_height = velocity_value.mul_add(bounds.h, -border_width);

let meter_db = util::gain_to_db(tap_meters[i].load(Ordering::Relaxed));
let meter_index = meter_indexes[i].load(Ordering::Relaxed);
let meter_db = util::gain_to_db(tap_meters[meter_index].load(Ordering::Relaxed));
let meter_height = {
let tick_fraction = (meter_db - MIN_TICK) / (MAX_TICK - MIN_TICK);
(tick_fraction * bounds.h).max(0.0)
Expand Down
21 changes: 16 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ struct Del2 {
input_meter: Arc<AtomicF32>,
output_meter: Arc<AtomicF32>,
tap_meters: Arc<AtomicF32Array>,
meter_indexes: Arc<AtomicUsizeArray>,
delay_write_index: isize,
is_learning: Arc<AtomicBool>,
// for which control are we learning?
Expand Down Expand Up @@ -474,6 +475,7 @@ impl Default for Del2 {
Arc::new(AtomicF32::new(util::MINUS_INFINITY_DB))
}))
.into(),
meter_indexes: AtomicUsizeArray(array_init(|_| Arc::new(AtomicUsize::new(0)))).into(),
delay_write_index: 0,
is_learning: Arc::new(AtomicBool::new(false)),
learning_index: Arc::new(AtomicUsize::new(0)),
Expand Down Expand Up @@ -578,6 +580,7 @@ impl Plugin for Del2 {
input_meter: self.input_meter.clone(),
output_meter: self.output_meter.clone(),
tap_meters: self.tap_meters.clone(),
meter_indexes: self.meter_indexes.clone(),
is_learning: self.is_learning.clone(),
learning_index: self.learning_index.clone(),
learned_notes: self.learned_notes.clone(),
Expand All @@ -589,6 +592,8 @@ impl Plugin for Del2 {
)
}

// After this function [`reset()`][Self::reset()] will always be called. If you need to clear
// state, such as filters or envelopes, then you should do so in that function instead.
fn initialize(
&mut self,
_audio_io_layout: &AudioIOLayout,
Expand Down Expand Up @@ -620,7 +625,7 @@ impl Plugin for Del2 {
delay_tap.ladders.s = [f32x4::splat(0.); 4];
}

for i in 0..self.params.tap_counter.load(Ordering::SeqCst) {
for i in 0..NUM_TAPS {
self.load_and_configure_tap(i);
}

Expand Down Expand Up @@ -753,7 +758,7 @@ impl Plugin for Del2 {
self.delay_taps
.iter_mut()
.enumerate()
.for_each(|(tap_index, delay_tap)| {
.for_each(|(meter_index, delay_tap)| {
if delay_tap.is_alive {
let pan = ((f32::from(delay_tap.note) - panning_center) * panning_amount)
.clamp(-1.0, 1.0);
Expand Down Expand Up @@ -820,16 +825,19 @@ impl Plugin for Del2 {

if self.params.editor_state.is_open() {
let weight = self.peak_meter_decay_weight * 0.91;
let gui_index = delay_tap.tap_index;

self.meter_indexes[gui_index].store(meter_index, Ordering::Relaxed);
amplitude = (amplitude / block_len as f32).min(1.0);
let current_peak_meter =
self.tap_meters[tap_index].load(Ordering::Relaxed);
self.tap_meters[meter_index].load(Ordering::Relaxed);
let new_peak_meter = if amplitude > current_peak_meter {
amplitude
} else {
current_peak_meter.mul_add(weight, amplitude * (1.0 - weight))
};

self.tap_meters[tap_index].store(new_peak_meter, Ordering::Relaxed);
self.tap_meters[meter_index].store(new_peak_meter, Ordering::Relaxed);
}
}
});
Expand Down Expand Up @@ -1332,7 +1340,6 @@ impl Del2 {
self.enabled_actions.store(MUTE_OUT, false);
}

// Create and setup amplitude envelope, outside the loop for potential reuse.
let amp_envelope = Smoother::new(SmoothingStyle::Linear(global_params.attack_ms.value()));
if global_params.mute_is_toggle.value() {
amp_envelope.set_target(sample_rate, 1.0);
Expand Down Expand Up @@ -1371,6 +1378,7 @@ impl Del2 {
delay_time,
note,
velocity,
new_index,
);
self.next_internal_id = self.next_internal_id.wrapping_add(1);
} else if let Some(oldest_delay_tap) = found_oldest {
Expand All @@ -1381,6 +1389,7 @@ impl Del2 {
delay_time,
note,
velocity,
new_index,
);
self.next_internal_id = self.next_internal_id.wrapping_add(1);
}
Expand Down Expand Up @@ -1692,6 +1701,7 @@ impl PersistentField<'_, u8> for ArcAtomicBoolArray {
}
}
struct AtomicU8Array([Arc<AtomicU8>; NUM_TAPS]);
pub struct AtomicUsizeArray([Arc<AtomicUsize>; NUM_TAPS]);
struct AtomicU32Array([Arc<AtomicU32>; NUM_TAPS]);
pub struct AtomicF32Array([Arc<AtomicF32>; NUM_TAPS]);

Expand Down Expand Up @@ -1777,6 +1787,7 @@ macro_rules! impl_index_for_atomic_array {

// Apply the macro to different types
impl_index_for_atomic_array!(AtomicU8Array, AtomicU8);
impl_index_for_atomic_array!(AtomicUsizeArray, AtomicUsize);
impl_index_for_atomic_array!(AtomicU32Array, AtomicU32);
impl_index_for_atomic_array!(AtomicF32Array, AtomicF32);

Expand Down

0 comments on commit ca8ddc0

Please sign in to comment.