-
-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
40 additions
and
118 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,36 @@ | ||
use crate::base::MovingAverageCalculator; | ||
|
||
use crate::domain::SampleOffset; | ||
use crate::domain::ControlEventTimestamp; | ||
use reaper_common_types::Bpm; | ||
use reaper_medium::Hz; | ||
use simple_moving_average::{SumTreeSMA, SMA}; | ||
use std::convert::TryInto; | ||
use tracing::warn; | ||
|
||
#[derive(Debug)] | ||
pub struct MidiClockCalculator { | ||
sample_rate: Hz, | ||
sample_counter: u64, | ||
previous_midi_clock_timestamp_in_samples: u64, | ||
bpm_calculator: MovingAverageCalculator, | ||
previous_timestamp: Option<ControlEventTimestamp>, | ||
previous_bpm: Option<f64>, | ||
moving_avg_calculator: SumTreeSMA<f64, f64, 10>, | ||
} | ||
|
||
impl Default for MidiClockCalculator { | ||
fn default() -> Self { | ||
Self { | ||
sample_rate: Hz::new_panic(1.0), | ||
sample_counter: 0, | ||
previous_midi_clock_timestamp_in_samples: 0, | ||
bpm_calculator: Default::default(), | ||
previous_timestamp: None, | ||
previous_bpm: None, | ||
moving_avg_calculator: SumTreeSMA::new(), | ||
} | ||
} | ||
} | ||
|
||
impl MidiClockCalculator { | ||
pub fn update_sample_rate(&mut self, sample_rate: Hz) { | ||
self.sample_rate = sample_rate; | ||
} | ||
|
||
pub fn increase_sample_counter_by(&mut self, sample_count: u64) { | ||
self.sample_counter += sample_count; | ||
} | ||
|
||
pub fn feed(&mut self, offset: SampleOffset) -> Option<Bpm> { | ||
let timestamp_in_samples = self.sample_counter + offset.get(); | ||
let prev_timestamp = self.previous_midi_clock_timestamp_in_samples; | ||
self.previous_midi_clock_timestamp_in_samples = timestamp_in_samples; | ||
|
||
if prev_timestamp == 0 || timestamp_in_samples <= prev_timestamp { | ||
return None; | ||
} | ||
let difference_in_samples = timestamp_in_samples - prev_timestamp; | ||
let difference_in_secs = difference_in_samples as f64 / self.sample_rate.get(); | ||
let num_ticks_per_sec = 1.0 / difference_in_secs; | ||
pub fn feed(&mut self, timestamp: ControlEventTimestamp) -> Option<Bpm> { | ||
let prev_timestamp = self.previous_timestamp.replace(timestamp)?; | ||
let duration_since_last = timestamp - prev_timestamp; | ||
let num_ticks_per_sec = 1.0 / duration_since_last.as_secs_f64(); | ||
let num_beats_per_sec = num_ticks_per_sec / 24.0; | ||
let num_beats_per_min = num_beats_per_sec * 60.0; | ||
if num_beats_per_min > 300.0 { | ||
return None; | ||
} | ||
self.bpm_calculator.feed(num_beats_per_min); | ||
let moving_avg = match self.bpm_calculator.moving_average() { | ||
None => return None, | ||
Some(a) => a, | ||
}; | ||
if self.bpm_calculator.value_count_so_far() % 24 == 0 { | ||
moving_avg.try_into().ok() | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
pub fn current_sample_count(&self) -> u64 { | ||
self.sample_counter | ||
let new_bpm = num_beats_per_sec * 60.0; | ||
self.moving_avg_calculator.add_sample(new_bpm); | ||
let avg_bpm = self.moving_avg_calculator.get_average(); | ||
let avg_bpm: Bpm = avg_bpm.try_into().ok()?; | ||
Some(avg_bpm) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters