///|
/// Auditable thresholds and counts used for integrated-loudness gating.
pub struct IntegratedGateReport {
priv absolute_threshold_lufs : Double
priv relative_threshold_lufs : Double
priv applied_threshold_lufs : Double
priv candidate_block_count : Int32
priv gated_block_count : Int32
priv integrated_lufs : Double
}
///|
pub fn IntegratedGateReport::absolute_threshold_lufs(
self : IntegratedGateReport,
) -> Double {
self.absolute_threshold_lufs
}
///|
pub fn IntegratedGateReport::relative_threshold_lufs(
self : IntegratedGateReport,
) -> Double {
self.relative_threshold_lufs
}
///|
pub fn IntegratedGateReport::applied_threshold_lufs(
self : IntegratedGateReport,
) -> Double {
self.applied_threshold_lufs
}
///|
pub fn IntegratedGateReport::candidate_block_count(
self : IntegratedGateReport,
) -> Int32 {
self.candidate_block_count
}
///|
pub fn IntegratedGateReport::gated_block_count(
self : IntegratedGateReport,
) -> Int32 {
self.gated_block_count
}
///|
pub fn IntegratedGateReport::integrated_lufs(
self : IntegratedGateReport,
) -> Double {
self.integrated_lufs
}
///|
/// Auditable thresholds, accepted block counts, and percentiles for LRA.
pub struct LraGateReport {
priv absolute_threshold_lufs : Double
priv relative_threshold_lufs : Double
priv applied_threshold_lufs : Double
priv candidate_block_count : Int32
priv gated_block_count : Int32
priv percentile_10_lufs : Double
priv percentile_95_lufs : Double
priv loudness_range_lu : Double
}
///|
pub fn LraGateReport::absolute_threshold_lufs(self : LraGateReport) -> Double {
self.absolute_threshold_lufs
}
///|
pub fn LraGateReport::relative_threshold_lufs(self : LraGateReport) -> Double {
self.relative_threshold_lufs
}
///|
pub fn LraGateReport::applied_threshold_lufs(self : LraGateReport) -> Double {
self.applied_threshold_lufs
}
///|
pub fn LraGateReport::candidate_block_count(self : LraGateReport) -> Int32 {
self.candidate_block_count
}
///|
pub fn LraGateReport::gated_block_count(self : LraGateReport) -> Int32 {
self.gated_block_count
}
///|
pub fn LraGateReport::percentile_10_lufs(self : LraGateReport) -> Double {
self.percentile_10_lufs
}
///|
pub fn LraGateReport::percentile_95_lufs(self : LraGateReport) -> Double {
self.percentile_95_lufs
}
///|
pub fn LraGateReport::loudness_range_lu(self : LraGateReport) -> Double {
self.loudness_range_lu
}
///|
/// Returns the integrated-gate trace when at least one block passes the absolute gate.
pub fn MeasurementReport::integrated_gate(
self : MeasurementReport,
) -> IntegratedGateReport? {
self.integrated_gate
}
///|
pub fn MeasurementReport::lra_gate(self : MeasurementReport) -> LraGateReport? {
self.lra_gate
}
///|
/// Calculates the two EBU-style integrated gates over bounded block statistics.
fn integrated_gate_from_histogram(
histogram : LoudnessHistogram,
) -> IntegratedGateReport? {
if histogram.above_range_count > 0 {
return None
}
match histogram.mean_energy_at_or_above(-70.0) {
None => None
Some(absolute_mean) => {
let absolute_loudness = energy_to_lufs(absolute_mean)
let relative_threshold = absolute_loudness - 10.0
let applied_threshold = if relative_threshold > -70.0 {
relative_threshold
} else {
-70.0
}
match histogram.mean_energy_at_or_above(applied_threshold) {
None => None
Some(gated_mean) =>
Some({
absolute_threshold_lufs: -70.0,
relative_threshold_lufs: relative_threshold,
applied_threshold_lufs: applied_threshold,
candidate_block_count: histogram.count_at_or_above(-70.0).to_int(),
gated_block_count: histogram
.count_at_or_above(applied_threshold)
.to_int(),
integrated_lufs: energy_to_lufs(gated_mean),
})
}
}
}
}
///|
/// Calculates EBU-style absolute and relative LRA gates and 10th/95th percentiles.
fn lra_gate_from_histogram(histogram : LoudnessHistogram) -> LraGateReport? {
if histogram.above_range_count > 0 {
return None
}
match histogram.mean_energy_at_or_above(-70.0) {
None => None
Some(absolute_mean) => {
let absolute_loudness = energy_to_lufs(absolute_mean)
let relative_threshold = absolute_loudness - 20.0
let applied_threshold = if relative_threshold > -70.0 {
relative_threshold
} else {
-70.0
}
match
(
histogram.percentile_at_or_above(applied_threshold, 10),
histogram.percentile_at_or_above(applied_threshold, 95),
) {
(Some(p10), Some(p95)) =>
Some({
absolute_threshold_lufs: -70.0,
relative_threshold_lufs: relative_threshold,
applied_threshold_lufs: applied_threshold,
candidate_block_count: histogram.count_at_or_above(-70.0).to_int(),
gated_block_count: histogram
.count_at_or_above(applied_threshold)
.to_int(),
percentile_10_lufs: p10,
percentile_95_lufs: p95,
loudness_range_lu: p95 - p10,
})
_ => None
}
}
}
}
///|
fn Analyzer::calculate_integrated_gate(
self : Analyzer,
) -> IntegratedGateReport? {
integrated_gate_from_histogram(self.integrated_distribution)
}
///|
fn Analyzer::calculate_lra_gate(self : Analyzer) -> LraGateReport? {
lra_gate_from_histogram(self.short_distribution)
}