Skip to content

Commit

Permalink
warn on clipping
Browse files Browse the repository at this point in the history
add option to apply pre-gain
  • Loading branch information
herrernst committed Jan 25, 2018
1 parent 2eabb93 commit 38f18e3
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 4 deletions.
4 changes: 4 additions & 0 deletions core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ pub struct PlayerConfig {
pub onstart: Option<String>,
pub onstop: Option<String>,
pub normalization: bool,
pub normalization_pre_gain: f32,
}

impl Default for PlayerConfig {
Expand All @@ -115,6 +116,9 @@ impl Default for PlayerConfig {
onstart: None,
onstop: None,
normalization: false,
normalization_pre_gain: 0.0, //replaygain target is -14dbfs, may not be enough headroom
// macOS Spotify client adds 3.0
// https://community.spotify.com/t5/Social-Off-Topic/How-does-the-loudness-normalization-algorithm-work/td-p/1603671
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ fn setup(args: &[String]) -> Setup {
.optopt("", "backend", "Audio backend to use. Use '?' to list options", "BACKEND")
.optopt("", "device", "Audio device to use. Use '?' to list options", "DEVICE")
.optopt("", "mixer", "Mixer to use", "MIXER")
.optflag("", "enable-volume-normalization", "Play all tracks at the same volume");
.optflag("", "enable-volume-normalization", "Play all tracks at the same volume")
.optopt("", "normalization-pre-gain", "Pre-gain (dB) applied by volume normalization", "PREGAIN");

let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Expand Down Expand Up @@ -170,7 +171,10 @@ fn setup(args: &[String]) -> Setup {
bitrate: bitrate,
onstart: matches.opt_str("onstart"),
onstop: matches.opt_str("onstop"),
normalization: matches.opt_present("enable-volume-normalization")
normalization: matches.opt_present("enable-volume-normalization"),
normalization_pre_gain: matches.opt_str("normalization-pre-gain")
.map(|pre_gain| pre_gain.parse::<f32>().expect("Invalid pre-gain float value"))
.unwrap_or(PlayerConfig::default().normalization_pre_gain),
}
};

Expand Down
11 changes: 9 additions & 2 deletions src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ impl PlayerInternal {

if self.config.normalization {

let normalization_factor = f32::powf(10.0, track_gain_db / 20.0);
// see http://wiki.hydrogenaud.io/index.php?title=ReplayGain_specification#Loudness_normalization
let normalization_factor = f32::powf(10.0, (track_gain_db + self.config.normalization_pre_gain) / 20.0);

// info!("Use gain: {}, factor: {}", track_gain_db, normalization_factor);

Expand Down Expand Up @@ -413,9 +414,15 @@ impl PlayerInternal {
}
decrypted_file.seek(SeekFrom::Start(148)).unwrap(); // 4 bytes as LE float
decrypted_file.read(&mut track_gain_float_bytes).unwrap();
let normalization_factor = f32::powf(10.0, (track_gain_db + self.config.normalization_pre_gain) / 20.0);
let mut track_peak: f32 = 1.0;
unsafe {
// track peak, 1.0 represents dbfs
info!("Track peak: {}", mem::transmute::<[u8; 4], f32>(track_gain_float_bytes));
track_peak = mem::transmute::<[u8; 4], f32>(track_gain_float_bytes);
info!("Track peak: {}", track_peak);
if normalization_factor * track_peak > 1.0 {
warn!("Track will clip, please add negative pre-gain");
}
}
decrypted_file.seek(SeekFrom::Start(152)).unwrap(); // 4 bytes as LE float
decrypted_file.read(&mut track_gain_float_bytes).unwrap();
Expand Down

0 comments on commit 38f18e3

Please sign in to comment.