Skip to content

Commit

Permalink
Playtime: Fix peak meters
Browse files Browse the repository at this point in the history
  • Loading branch information
helgoboss committed Nov 18, 2023
1 parent 3ef76dc commit 7e25662
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 30 deletions.
28 changes: 22 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ ascii.workspace = true
enigo = "0.0.14"
device_query = "1.1.1"
derive_more.workspace = true
slog.workspace = true
slog.workspace = true
either.workspace = true
2 changes: 2 additions & 0 deletions base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ mod trafficker;
pub use trafficker::*;

pub mod validation_util;

pub mod peak_util;
38 changes: 38 additions & 0 deletions base/src/peak_util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use either::Either;
use reaper_high::{Reaper, Track};
use reaper_medium::{MediaTrack, ReaperVolumeValue, SoloMode, TrackAttributeKey};
use std::iter;

/// Returns whether the peaks should better be hidden even they are available.
///
/// This is for the case if another track is soloed, reporting the peak would be misleading then.
pub fn peaks_should_be_hidden(track: &Track) -> bool {
let is_master = track.is_master_track();
(is_master && track.is_muted())
|| (!is_master && track.project().any_solo() && track.solo_mode() == SoloMode::Off)
}

/// Returns the track's peaks as iterator.
///
/// This takes VU mode / channel count intricacies into account. It returns peaks even if another
/// track is soloed! See [`peaks_should_be_hidden`].
pub fn get_track_peaks(
track: MediaTrack,
) -> impl Iterator<Item = ReaperVolumeValue> + ExactSizeIterator<Item = ReaperVolumeValue> {
let reaper = Reaper::get().medium_reaper();
let vu_mode =
unsafe { reaper.get_media_track_info_value(track, TrackAttributeKey::VuMode) as i32 };
let channel_count = if matches!(vu_mode, 2 | 8) {
// These VU modes have multi-channel support.
unsafe { reaper.get_media_track_info_value(track, TrackAttributeKey::Nchan) as i32 }
} else {
// Other VU modes always use stereo.
2
};
if channel_count <= 0 {
return Either::Left(iter::empty());
}
let iter =
(0..channel_count).map(move |ch| unsafe { reaper.track_get_peak_info(track, ch as u32) });
Either::Right(iter)
}
2 changes: 1 addition & 1 deletion helgoboss-license-processor
27 changes: 6 additions & 21 deletions main/src/domain/targets/track_peak_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::domain::{
FeedbackResolution, RealearnTarget, ReaperTarget, ReaperTargetType, TargetCharacter,
TargetTypeDef, TrackDescriptor, UnresolvedReaperTargetDef, DEFAULT_TARGET,
};
use base::peak_util;
use helgoboss_learn::{AbsoluteValue, ControlType, NumericValue, Target, UnitValue};
use reaper_high::{Project, Reaper, Track, Volume};
use reaper_medium::{ReaperVolumeValue, SoloMode, TrackAttributeKey};
Expand Down Expand Up @@ -60,31 +61,15 @@ impl<'a> Target<'a> for TrackPeakTarget {

impl TrackPeakTarget {
fn peak(&self) -> Option<Volume> {
let reaper = Reaper::get().medium_reaper();
if self.track.project().any_solo() && self.track.solo_mode() == SoloMode::Off {
// Another track is soloed. In this case, reporting the peak would be misleading.
if peak_util::peaks_should_be_hidden(&self.track) {
return Some(Volume::MIN);
}
let vu_mode = unsafe {
reaper.get_media_track_info_value(self.track.raw(), TrackAttributeKey::VuMode) as i32
};
let channel_count = if matches!(vu_mode, 2 | 8) {
// These VU modes have multi-channel support.
unsafe {
reaper.get_media_track_info_value(self.track.raw(), TrackAttributeKey::Nchan) as i32
}
} else {
// Other VU modes always use stereo.
2
};
if channel_count <= 0 {
let peaks = peak_util::get_track_peaks(self.track.raw());
let channel_count = peaks.len();
if channel_count == 0 {
return None;
}
let mut sum = 0.0;
for ch in 0..channel_count {
let volume = unsafe { reaper.track_get_peak_info(self.track.raw(), ch as u32) };
sum += volume.get();
}
let sum: f64 = peaks.map(|v| v.get()).sum();
let avg = sum / channel_count as f64;
let vol = ReaperVolumeValue::new(avg);
Some(Volume::from_reaper_value(vol))
Expand Down
2 changes: 1 addition & 1 deletion playtime-clip-engine

0 comments on commit 7e25662

Please sign in to comment.