Skip to content

Commit

Permalink
delay times change with tempo, but not with SR
Browse files Browse the repository at this point in the history
  • Loading branch information
magnetophon committed Nov 29, 2024
1 parent db04ca1 commit b722a93
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 15 deletions.
4 changes: 2 additions & 2 deletions src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ impl DelayGraph {
const TOTAL_DIGITS: usize = 3;
let tap_counter = params.tap_counter.load(Ordering::SeqCst);
let current_time = params.current_time.load(Ordering::SeqCst);
let tempo = params.tempo.load(Ordering::SeqCst);
let tempo = params.current_tempo.load(Ordering::SeqCst);
let time_sig_numerator = params.time_sig_numerator.load(Ordering::SeqCst);
// Determine the max delay time
let seconds = if current_time > 0 {
Expand All @@ -477,7 +477,7 @@ impl DelayGraph {
if current_time == 0 && tap_counter == 0 {
// String::from("tap a rhythm!")
String::new()
} else if tempo >= 0.0 && time_sig_numerator > 0 {
} else if tempo > 0.0 && time_sig_numerator > 0 {
let seconds_per_beat = 60.0 / tempo;
let seconds_per_measure = seconds_per_beat * time_sig_numerator as f32;
let full_bars = (seconds / seconds_per_measure).floor() as i32;
Expand Down
74 changes: 61 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ pub struct Del2Params {
#[persist = "preset-sample-rate"]
preset_sample_rate: AtomicF32,
// TODO: persist and use for conversions
tempo: AtomicF32,
current_tempo: AtomicF32,
#[persist = "preset-tempo"]
preset_tempo: AtomicF32,
time_sig_numerator: AtomicI32,
learning_start_time: AtomicU64,
}
Expand Down Expand Up @@ -536,7 +538,8 @@ impl Del2Params {
last_frame_time: AtomicU64::new(0),
sample_rate: 1.0.into(),
preset_sample_rate: 1.0.into(),
tempo: (-1.0).into(),
preset_tempo: (-1.0).into(),
current_tempo: (-1.0).into(),
time_sig_numerator: (-1).into(),
learning_start_time: AtomicU64::new(0),
}
Expand Down Expand Up @@ -634,16 +637,23 @@ impl Plugin for Del2 {

fn reset(&mut self) {
let tap_counter = self.params.tap_counter.load(Ordering::SeqCst);

let sample_rate = self.params.sample_rate.load(Ordering::SeqCst);
let preset_sample_rate = self.params.sample_rate.load(Ordering::SeqCst);
let needs_conversion = sample_rate != preset_sample_rate;
if needs_conversion {
let preset_sample_rate = self.params.preset_sample_rate.load(Ordering::SeqCst);

if sample_rate != preset_sample_rate {
// if preset_sample_rate is not the initial value
// convert the delay times for the new SR
if preset_sample_rate > 1.0 {
let sr_conversion_factor = sample_rate / preset_sample_rate;
// we do this in reset() and not in process(),
// because if the user is changing the at runtime,
// we want the delay time to change along with the audio speed.
if preset_sample_rate > 0.0 {
self.params
.previous_time_scaling_factor
.store(NO_GUI_SMOOTHING, Ordering::SeqCst);
let conversion_factor = sample_rate / preset_sample_rate;
for tap_index in 0..NUM_TAPS {
let new_delay_time = (sr_conversion_factor
let new_delay_time = (conversion_factor
* self.params.delay_times[tap_index].load(Ordering::SeqCst) as f32)
as u32;
self.params.delay_times[tap_index].store(new_delay_time, Ordering::SeqCst);
Expand All @@ -654,7 +664,6 @@ impl Plugin for Del2 {
.preset_sample_rate
.store(sample_rate, Ordering::SeqCst);
}

// first make room in the array
self.delay_taps.iter_mut().for_each(|delay_tap| {
delay_tap.is_alive = false;
Expand Down Expand Up @@ -703,15 +712,54 @@ impl Plugin for Del2 {
self.update_min_max_tap_samples();

let num_samples = buffer.samples();

let sample_rate = context.transport().sample_rate;

let current_tempo = context.transport().tempo.unwrap_or(-1.0) as f32;
let preset_tempo = self.params.preset_tempo.load(Ordering::SeqCst);

if current_tempo > 0.0 && current_tempo != preset_tempo {
if preset_tempo > 0.0 {
// if preset_tempo is not the initial value
// convert the delay times for the new tempo
// we do this in process() and not in reset(),
// because if the user changes the tempo in the song,
// we want the delay time to change with it.

// the graph should remain stationary after the recalculation
self.params
.previous_time_scaling_factor
.store(NO_GUI_SMOOTHING, Ordering::SeqCst);

let conversion_factor = preset_tempo / current_tempo;
let tap_counter = self.params.tap_counter.load(Ordering::SeqCst);

// first start fading out the current delay taps
self.start_release_for_all_delay_taps();
for tap_index in 0..NUM_TAPS {
let new_delay_time = (conversion_factor
* self.params.delay_times[tap_index].load(Ordering::SeqCst) as f32)
as u32;
self.params.delay_times[tap_index].store(new_delay_time, Ordering::SeqCst);

if tap_index < tap_counter {
// find a free delay_tap to run the new delay time
self.start_tap(tap_index, true);
}
}
}
// store the actual tempo, in case the user makes a new preset
self.params
.preset_tempo
.store(current_tempo, Ordering::SeqCst);
}

self.params
.sample_rate
.store(context.transport().sample_rate, Ordering::SeqCst);
self.params.tempo.store(
context.transport().tempo.unwrap_or(-1.0) as f32,
Ordering::SeqCst,
);
self.params
.current_tempo
.store(current_tempo, Ordering::SeqCst);
self.params.time_sig_numerator.store(
context.transport().time_sig_numerator.unwrap_or(-1),
Ordering::SeqCst,
Expand Down

0 comments on commit b722a93

Please sign in to comment.