diff --git a/src/editor.rs b/src/editor.rs index f8b5c63..59b9f64 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -13,7 +13,7 @@ use nih_plug_vizia::{ use crate::{ util, AtomicBoolArray, AtomicByteArray, Del2Params, DelayData, DelayDataOutput, - LastPlayedNotes, LEARNING, MUTE_IN, MUTE_OUT, NO_LEARNED_NOTE, RESET_PATTERN, + LastPlayedNotes, LEARNING, LOCK_PATTERN, MUTE_IN, MUTE_OUT, NO_LEARNED_NOTE, RESET_PATTERN, }; #[derive(Lens, Clone)] @@ -127,6 +127,42 @@ pub fn create(editor_data: Data, editor_state: Arc) -> Option, @@ -63,6 +67,8 @@ struct Del2 { // delay write buffer delay_buffer: [BMRingBuf; 2], + // fake mute the input mute by delayning the output mut + mute_in_delay_buffer: BMRingBuf, // delay read buffers // TODO: which vecs should be arrays? temp_l: Vec, @@ -413,6 +419,7 @@ impl Default for Del2 { BMRingBuf::::from_len(TOTAL_DELAY_SAMPLES), BMRingBuf::::from_len(TOTAL_DELAY_SAMPLES), ], + mute_in_delay_buffer: BMRingBuf::::from_len(TOTAL_DELAY_SAMPLES), temp_l: vec![0.0; MAX_BLOCK_LEN], temp_r: vec![0.0; MAX_BLOCK_LEN], @@ -582,7 +589,7 @@ impl Plugin for Del2 { self.update_peak_meter(buffer, &self.input_meter); self.process_audio_blocks(buffer); self.update_peak_meter(buffer, &self.output_meter); - ProcessStatus::Normal + ProcessStatus::KeepAlive } } @@ -621,7 +628,8 @@ impl Del2 { CountingState::TimeOut => { if is_delay_note && !is_learning { // If in TimeOut state, reset and start new counting phase - self.mute_out(true); + self.mute_all_outs(true); + self.enabled_actions.store(MUTE_IN, false); self.enabled_actions.store(MUTE_OUT, false); self.delay_data.current_tap = 0; self.timing_last_event = timing; @@ -699,12 +707,19 @@ impl Del2 { self.should_update_filter.store(true, Ordering::Release); } // Handle ActionTrigger events + if self.is_playing_action(MUTE_IN) { + if self.enabled_actions.load(MUTE_IN) { + self.enabled_actions.store(MUTE_IN, false); + } else { + self.enabled_actions.store(MUTE_IN, true); + } + } if self.is_playing_action(MUTE_OUT) { if self.enabled_actions.load(MUTE_OUT) { - self.mute_out(false); + self.mute_all_outs(false); self.enabled_actions.store(MUTE_OUT, false); } else { - self.mute_out(true); + self.mute_all_outs(true); self.enabled_actions.store(MUTE_OUT, true); } } @@ -719,7 +734,8 @@ impl Del2 { } } } - fn mute_out(&mut self, mute: bool) { + + fn mute_all_outs(&mut self, mute: bool) { let time_value = if mute { self.params.global.release_ms.value() } else { @@ -830,9 +846,13 @@ impl Del2 { let out_l = block_channels.next().expect("Left output channel missing"); let out_r = block_channels.next().expect("Right output channel missing"); - - self.delay_buffer[0].write_latest(out_l, self.delay_write_index as isize); - self.delay_buffer[1].write_latest(out_r, self.delay_write_index as isize); + let write_index = self.delay_write_index as isize; + self.delay_buffer[0].write_latest(out_l, write_index); + self.delay_buffer[1].write_latest(out_r, write_index); + self.mute_in_delay_buffer.write_latest( + &vec![self.enabled_actions.load(MUTE_IN); block_len], + write_index, + ); // TODO: no dry signal yet out_l.fill(0.0); out_r.fill(0.0); @@ -863,6 +883,18 @@ impl Del2 { } fn process_temp_with_envelope(&mut self, block_len: usize, tap: usize) { + // Use an inline buffer to read into and directly use its first value + self.mute_out(tap, { + let mut buffer = vec![false; 1]; // This vector acts as a temporary for reading + self.mute_in_delay_buffer.read_into( + &mut buffer, + self.delay_write_index as isize + - (self.delay_data.delay_times[tap] as isize - 1).max(0), + ); + buffer[0] // Return the single bool value after reading + | self.enabled_actions.load(MUTE_OUT) + }); + // Initialize an envelope block for the current processing segment self.amp_envelopes[tap].next_block(&mut self.envelope_block[..block_len], block_len); @@ -874,6 +906,19 @@ impl Del2 { } } + fn mute_out(&mut self, tap: usize, mute: bool) { + let time_value = if mute { + self.params.global.release_ms.value() + } else { + self.params.global.attack_ms.value() + }; + let target_value = if mute { 0.0 } else { 1.0 }; + + self.releasings[tap] = mute; + self.amp_envelopes[tap].style = SmoothingStyle::Exponential(time_value); + self.amp_envelopes[tap].set_target(self.sample_rate, target_value); + } + fn process_audio( &mut self, block_len: usize,