mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
parent
55ced49c2d
commit
03e71f6e0a
2 changed files with 46 additions and 13 deletions
|
@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- [main] Don't panic when parsing options. Instead list valid values and exit.
|
- [main] Don't panic when parsing options. Instead list valid values and exit.
|
||||||
- [main] `--alsa-mixer-device` and `--alsa-mixer-index` now fallback to the card and index specified in `--device`.
|
- [main] `--alsa-mixer-device` and `--alsa-mixer-index` now fallback to the card and index specified in `--device`.
|
||||||
- [core] Removed unsafe code (breaking)
|
- [core] Removed unsafe code (breaking)
|
||||||
|
- [playback] Adhere to ReplayGain spec when calculating gain normalisation factor.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- [playback] `alsamixer`: previously deprecated option `mixer-card` has been removed.
|
- [playback] `alsamixer`: previously deprecated option `mixer-card` has been removed.
|
||||||
|
|
|
@ -31,6 +31,7 @@ use crate::{MS_PER_PAGE, NUM_CHANNELS, PAGES_PER_MS, SAMPLES_PER_SECOND};
|
||||||
|
|
||||||
const PRELOAD_NEXT_TRACK_BEFORE_END_DURATION_MS: u32 = 30000;
|
const PRELOAD_NEXT_TRACK_BEFORE_END_DURATION_MS: u32 = 30000;
|
||||||
pub const DB_VOLTAGE_RATIO: f64 = 20.0;
|
pub const DB_VOLTAGE_RATIO: f64 = 20.0;
|
||||||
|
pub const PCM_AT_0DBFS: f64 = 1.0;
|
||||||
|
|
||||||
pub struct Player {
|
pub struct Player {
|
||||||
commands: Option<mpsc::UnboundedSender<PlayerCommand>>,
|
commands: Option<mpsc::UnboundedSender<PlayerCommand>>,
|
||||||
|
@ -251,26 +252,57 @@ impl NormalisationData {
|
||||||
(data.track_gain_db, data.track_peak)
|
(data.track_gain_db, data.track_peak)
|
||||||
};
|
};
|
||||||
|
|
||||||
let normalisation_power = gain_db + config.normalisation_pregain_db;
|
// As per the ReplayGain 1.0 & 2.0 (proposed) spec:
|
||||||
let mut normalisation_factor = db_to_ratio(normalisation_power);
|
// https://wiki.hydrogenaud.io/index.php?title=ReplayGain_1.0_specification#Clipping_prevention
|
||||||
|
// https://wiki.hydrogenaud.io/index.php?title=ReplayGain_2.0_specification#Clipping_prevention
|
||||||
|
let normalisation_factor = if config.normalisation_method == NormalisationMethod::Basic {
|
||||||
|
// For Basic Normalisation, factor = min(ratio of (ReplayGain + PreGain), 1.0 / peak level).
|
||||||
|
// https://wiki.hydrogenaud.io/index.php?title=ReplayGain_1.0_specification#Peak_amplitude
|
||||||
|
// https://wiki.hydrogenaud.io/index.php?title=ReplayGain_2.0_specification#Peak_amplitude
|
||||||
|
// We then limit that to 1.0 as not to exceed dBFS (0.0 dB).
|
||||||
|
let factor = f64::min(
|
||||||
|
db_to_ratio(gain_db + config.normalisation_pregain_db),
|
||||||
|
PCM_AT_0DBFS / gain_peak,
|
||||||
|
);
|
||||||
|
|
||||||
if normalisation_power + ratio_to_db(gain_peak) > config.normalisation_threshold_dbfs {
|
if factor > PCM_AT_0DBFS {
|
||||||
let limited_normalisation_factor =
|
info!(
|
||||||
db_to_ratio(config.normalisation_threshold_dbfs) / gain_peak;
|
"Lowering gain by {:.2} dB for the duration of this track to avoid potentially exceeding dBFS.",
|
||||||
let limited_normalisation_power = ratio_to_db(limited_normalisation_factor);
|
ratio_to_db(factor)
|
||||||
|
);
|
||||||
|
|
||||||
if config.normalisation_method == NormalisationMethod::Basic {
|
PCM_AT_0DBFS
|
||||||
warn!("Limiting gain to {:.2} dB for the duration of this track to stay under normalisation threshold.", limited_normalisation_power);
|
|
||||||
normalisation_factor = limited_normalisation_factor;
|
|
||||||
} else {
|
} else {
|
||||||
|
factor
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For Dynamic Normalisation it's up to the player to decide,
|
||||||
|
// factor = ratio of (ReplayGain + PreGain).
|
||||||
|
// We then let the dynamic limiter handle gain reduction.
|
||||||
|
let factor = db_to_ratio(gain_db + config.normalisation_pregain_db);
|
||||||
|
let threshold_ratio = db_to_ratio(config.normalisation_threshold_dbfs);
|
||||||
|
|
||||||
|
if factor > PCM_AT_0DBFS {
|
||||||
|
let factor_db = gain_db + config.normalisation_pregain_db;
|
||||||
|
let limiting_db = factor_db + config.normalisation_threshold_dbfs.abs();
|
||||||
|
|
||||||
warn!(
|
warn!(
|
||||||
"This track will at its peak be subject to {:.2} dB of dynamic limiting.",
|
"This track may exceed dBFS by {:.2} dB and be subject to {:.2} dB of dynamic limiting at it's peak.",
|
||||||
normalisation_power - limited_normalisation_power
|
factor_db, limiting_db
|
||||||
|
);
|
||||||
|
} else if factor > threshold_ratio {
|
||||||
|
let limiting_db = gain_db
|
||||||
|
+ config.normalisation_pregain_db
|
||||||
|
+ config.normalisation_threshold_dbfs.abs();
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"This track may be subject to {:.2} dB of dynamic limiting at it's peak.",
|
||||||
|
limiting_db
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
warn!("Please lower pregain to avoid.");
|
factor
|
||||||
}
|
};
|
||||||
|
|
||||||
debug!("Normalisation Data: {:?}", data);
|
debug!("Normalisation Data: {:?}", data);
|
||||||
debug!(
|
debug!(
|
||||||
|
|
Loading…
Reference in a new issue