mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Merge pull request #573 from librespot-org/album-normalisation
Add option to choose between track or album normalisation gain
This commit is contained in:
commit
24486c8c83
3 changed files with 50 additions and 8 deletions
|
@ -25,10 +25,34 @@ impl Default for Bitrate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum NormalisationType {
|
||||||
|
Album,
|
||||||
|
Track,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for NormalisationType {
|
||||||
|
type Err = ();
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"album" => Ok(NormalisationType::Album),
|
||||||
|
"track" => Ok(NormalisationType::Track),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for NormalisationType {
|
||||||
|
fn default() -> NormalisationType {
|
||||||
|
NormalisationType::Album
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PlayerConfig {
|
pub struct PlayerConfig {
|
||||||
pub bitrate: Bitrate,
|
pub bitrate: Bitrate,
|
||||||
pub normalisation: bool,
|
pub normalisation: bool,
|
||||||
|
pub normalisation_type: NormalisationType,
|
||||||
pub normalisation_pregain: f32,
|
pub normalisation_pregain: f32,
|
||||||
pub gapless: bool,
|
pub gapless: bool,
|
||||||
}
|
}
|
||||||
|
@ -38,6 +62,7 @@ impl Default for PlayerConfig {
|
||||||
PlayerConfig {
|
PlayerConfig {
|
||||||
bitrate: Bitrate::default(),
|
bitrate: Bitrate::default(),
|
||||||
normalisation: false,
|
normalisation: false,
|
||||||
|
normalisation_type: NormalisationType::default(),
|
||||||
normalisation_pregain: 0.0,
|
normalisation_pregain: 0.0,
|
||||||
gapless: true,
|
gapless: true,
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::mem;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use crate::config::{Bitrate, PlayerConfig};
|
use crate::config::{Bitrate, NormalisationType, PlayerConfig};
|
||||||
use librespot_core::session::Session;
|
use librespot_core::session::Session;
|
||||||
use librespot_core::spotify_id::SpotifyId;
|
use librespot_core::spotify_id::SpotifyId;
|
||||||
|
|
||||||
|
@ -214,17 +214,20 @@ impl NormalisationData {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_factor(config: &PlayerConfig, data: NormalisationData) -> f32 {
|
fn get_factor(config: &PlayerConfig, data: NormalisationData) -> f32 {
|
||||||
let mut normalisation_factor = f32::powf(
|
let [gain_db, gain_peak] = match config.normalisation_type {
|
||||||
10.0,
|
NormalisationType::Album => [data.album_gain_db, data.album_peak],
|
||||||
(data.track_gain_db + config.normalisation_pregain) / 20.0,
|
NormalisationType::Track => [data.track_gain_db, data.track_peak],
|
||||||
);
|
};
|
||||||
|
let mut normalisation_factor =
|
||||||
|
f32::powf(10.0, (gain_db + config.normalisation_pregain) / 20.0);
|
||||||
|
|
||||||
if normalisation_factor * data.track_peak > 1.0 {
|
if normalisation_factor * gain_peak > 1.0 {
|
||||||
warn!("Reducing normalisation factor to prevent clipping. Please add negative pregain to avoid.");
|
warn!("Reducing normalisation factor to prevent clipping. Please add negative pregain to avoid.");
|
||||||
normalisation_factor = 1.0 / data.track_peak;
|
normalisation_factor = 1.0 / gain_peak;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Normalisation Data: {:?}", data);
|
debug!("Normalisation Data: {:?}", data);
|
||||||
|
debug!("Normalisation Type: {:?}", config.normalisation_type);
|
||||||
debug!("Applied normalisation factor: {}", normalisation_factor);
|
debug!("Applied normalisation factor: {}", normalisation_factor);
|
||||||
|
|
||||||
normalisation_factor
|
normalisation_factor
|
||||||
|
|
16
src/main.rs
16
src/main.rs
|
@ -22,7 +22,7 @@ use librespot::core::version;
|
||||||
use librespot::connect::discovery::{discovery, DiscoveryStream};
|
use librespot::connect::discovery::{discovery, DiscoveryStream};
|
||||||
use librespot::connect::spirc::{Spirc, SpircTask};
|
use librespot::connect::spirc::{Spirc, SpircTask};
|
||||||
use librespot::playback::audio_backend::{self, Sink, BACKENDS};
|
use librespot::playback::audio_backend::{self, Sink, BACKENDS};
|
||||||
use librespot::playback::config::{Bitrate, PlayerConfig};
|
use librespot::playback::config::{Bitrate, NormalisationType, PlayerConfig};
|
||||||
use librespot::playback::mixer::{self, Mixer, MixerConfig};
|
use librespot::playback::mixer::{self, Mixer, MixerConfig};
|
||||||
use librespot::playback::player::{Player, PlayerEvent};
|
use librespot::playback::player::{Player, PlayerEvent};
|
||||||
|
|
||||||
|
@ -177,6 +177,12 @@ fn setup(args: &[String]) -> Setup {
|
||||||
"enable-volume-normalisation",
|
"enable-volume-normalisation",
|
||||||
"Play all tracks at the same volume",
|
"Play all tracks at the same volume",
|
||||||
)
|
)
|
||||||
|
.optopt(
|
||||||
|
"",
|
||||||
|
"normalisation-gain-type",
|
||||||
|
"Specify the normalisation gain type to use - [track, album]. Default is album.",
|
||||||
|
"GAIN_TYPE",
|
||||||
|
)
|
||||||
.optopt(
|
.optopt(
|
||||||
"",
|
"",
|
||||||
"normalisation-pregain",
|
"normalisation-pregain",
|
||||||
|
@ -354,10 +360,18 @@ fn setup(args: &[String]) -> Setup {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|bitrate| Bitrate::from_str(bitrate).expect("Invalid bitrate"))
|
.map(|bitrate| Bitrate::from_str(bitrate).expect("Invalid bitrate"))
|
||||||
.unwrap_or(Bitrate::default());
|
.unwrap_or(Bitrate::default());
|
||||||
|
let gain_type = matches
|
||||||
|
.opt_str("normalisation-gain-type")
|
||||||
|
.as_ref()
|
||||||
|
.map(|gain_type| {
|
||||||
|
NormalisationType::from_str(gain_type).expect("Invalid normalisation type")
|
||||||
|
})
|
||||||
|
.unwrap_or(NormalisationType::default());
|
||||||
PlayerConfig {
|
PlayerConfig {
|
||||||
bitrate: bitrate,
|
bitrate: bitrate,
|
||||||
gapless: !matches.opt_present("disable-gapless"),
|
gapless: !matches.opt_present("disable-gapless"),
|
||||||
normalisation: matches.opt_present("enable-volume-normalisation"),
|
normalisation: matches.opt_present("enable-volume-normalisation"),
|
||||||
|
normalisation_type: gain_type,
|
||||||
normalisation_pregain: matches
|
normalisation_pregain: matches
|
||||||
.opt_str("normalisation-pregain")
|
.opt_str("normalisation-pregain")
|
||||||
.map(|pregain| pregain.parse::<f32>().expect("Invalid pregain float value"))
|
.map(|pregain| pregain.parse::<f32>().expect("Invalid pregain float value"))
|
||||||
|
|
Loading…
Reference in a new issue