implement exponential volume control only
This commit is contained in:
Robert 2018-01-29 23:37:30 +01:00
parent de7d341faa
commit bec6b8c512
4 changed files with 28 additions and 41 deletions

1
README.md Executable file → Normal file
View file

@ -73,7 +73,6 @@ target/release/librespot --username USERNAME --cache CACHEDIR --name DEVICENAME
| Option | | device | Audio device to use. Use '?' to list options | DEVICE | | Option | | device | Audio device to use. Use '?' to list options | DEVICE |
| Option | | mixer | Mixer to use | MIXER | | Option | | mixer | Mixer to use | MIXER |
| Option | | initial-volume | Initial volume in %, once connected [0-100] | VOLUME | | Option | | initial-volume | Initial volume in %, once connected [0-100] | VOLUME |
| Flag | | progressive-volume | Increase volume slowly at low level | |
Taken from here: Taken from here:
https://github.com/ComlOnline/librespot/blob/master/src/main.rs#L88 https://github.com/ComlOnline/librespot/blob/master/src/main.rs#L88

View file

@ -122,5 +122,4 @@ pub struct ConnectConfig {
pub name: String, pub name: String,
pub device_type: DeviceType, pub device_type: DeviceType,
pub volume: i32, pub volume: i32,
pub progressive_volume: bool,
} }

View file

@ -101,8 +101,7 @@ fn setup(args: &[String]) -> Setup {
.optopt("", "backend", "Audio backend to use. Use '?' to list options", "BACKEND") .optopt("", "backend", "Audio backend to use. Use '?' to list options", "BACKEND")
.optopt("", "device", "Audio device to use. Use '?' to list options", "DEVICE") .optopt("", "device", "Audio device to use. Use '?' to list options", "DEVICE")
.optopt("", "mixer", "Mixer to use", "MIXER") .optopt("", "mixer", "Mixer to use", "MIXER")
.optopt("", "initial-volume", "Initial volume in %, once connected (must be from 0 to 100)", "VOLUME") .optopt("", "initial-volume", "Initial volume in %, once connected (must be from 0 to 100)", "VOLUME");
.optflag("", "progressive-volume", "Increase volume slowly at low level, faster at high level");
let matches = match opts.parse(&args[1..]) { let matches = match opts.parse(&args[1..]) {
Ok(m) => m, Ok(m) => m,
@ -161,10 +160,7 @@ fn setup(args: &[String]) -> Setup {
else{ else{
initial_volume = 0x8000 as i32; initial_volume = 0x8000 as i32;
} }
debug!("Volume \"{}\" !", initial_volume);
let progressive_volume = matches.opt_present("progressive-volume");
info!("Volume:{}, progressive_volume: {}.", initial_volume, progressive_volume);
let name = matches.opt_str("name").unwrap(); let name = matches.opt_str("name").unwrap();
let use_audio_cache = !matches.opt_present("disable-audio-cache"); let use_audio_cache = !matches.opt_present("disable-audio-cache");
@ -213,7 +209,6 @@ fn setup(args: &[String]) -> Setup {
name: name, name: name,
device_type: device_type, device_type: device_type,
volume: initial_volume, volume: initial_volume,
progressive_volume,
} }
}; };

View file

@ -24,7 +24,6 @@ use rand::Rng;
pub struct SpircTask { pub struct SpircTask {
player: Player, player: Player,
mixer: Box<Mixer>, mixer: Box<Mixer>,
progressive_volume:bool,
sequence: SeqGenerator<u32>, sequence: SeqGenerator<u32>,
@ -124,30 +123,26 @@ fn initial_device_state(config: ConnectConfig, volume: u16) -> DeviceState {
}) })
} }
fn volume_to_mixer(volume: u16, progressive: bool) -> u16 { fn volume_to_mixer(volume: u16) -> u16 {
if progressive { // Volume conversion taken from https://www.dr-lex.be/info-stuff/volumecontrols.html#ideal2
// Some by trail determined volume calculation algorithm. Start increasing slowly, // Convert the given volume [0..0xffff] to a dB gain
// then after 50% increase in bigger steps. // We assume a dB range of 60dB.
let d = volume / (std::u16::MAX / 100); // Use the equatation: a * exp(b * x)
let mut v:u32 = 0; // in which a = IDEAL_FACTOR, b = 1/1000
let mut incr:u32 = 0; const IDEAL_FACTOR: f64 = 6.908;
for i in 0..d { let normalized_volume = volume as f64 / std::u16::MAX as f64; // To get a value between 0 and 1
v += incr;
incr +=3; let mut val = std::u16::MAX;
if i > 50 { // Prevent val > std::u16::MAX due to rounding errors
// Increase faster to reach max volume if normalized_volume < 0.999 {
incr += 42; let new_volume = (normalized_volume * IDEAL_FACTOR).exp() / 1000.0;
} val = (new_volume * std::u16::MAX as f64) as u16;
} }
// Clip the vulume to the max debug!("input volume:{} to mixer: {}", volume, val);
if v > std::u16::MAX as u32 {v = std::u16::MAX as u32;}
debug!("volume_to_mixer {} {}", volume, v); // return the scale factor (0..0xffff) (equivalent to a voltage multiplier).
return v as u16; val
} else {
debug!("volume_to_mixer {}", volume);
return volume;
}
} }
@ -173,15 +168,15 @@ impl Spirc {
})); }));
let (cmd_tx, cmd_rx) = mpsc::unbounded(); let (cmd_tx, cmd_rx) = mpsc::unbounded();
let progressive_volume = config.progressive_volume;
let volume = config.volume as u16; let volume = config.volume as u16;
let device = initial_device_state(config, volume); let device = initial_device_state(config, volume);
mixer.set_volume(volume_to_mixer(volume as u16, progressive_volume)); mixer.set_volume(volume_to_mixer(volume as u16));
let mut task = SpircTask { let mut task = SpircTask {
player: player, player: player,
mixer: mixer, mixer: mixer,
progressive_volume,
sequence: SeqGenerator::new(1), sequence: SeqGenerator::new(1),
ident: ident, ident: ident,
@ -469,8 +464,7 @@ impl SpircTask {
MessageType::kMessageTypeVolume => { MessageType::kMessageTypeVolume => {
self.device.set_volume(frame.get_volume()); self.device.set_volume(frame.get_volume());
self.mixer.set_volume( self.mixer.set_volume(volume_to_mixer(frame.get_volume() as u16));
volume_to_mixer(frame.get_volume() as u16, self.progressive_volume));
self.notify(None); self.notify(None);
} }
@ -570,7 +564,7 @@ impl SpircTask {
volume = 0xFFFF; volume = 0xFFFF;
} }
self.device.set_volume(volume); self.device.set_volume(volume);
self.mixer.set_volume(volume_to_mixer(volume as u16, self.progressive_volume)); self.mixer.set_volume(volume_to_mixer(volume as u16));
} }
fn handle_volume_down(&mut self) { fn handle_volume_down(&mut self) {
@ -579,7 +573,7 @@ impl SpircTask {
volume = 0; volume = 0;
} }
self.device.set_volume(volume as u32); self.device.set_volume(volume as u32);
self.mixer.set_volume(volume_to_mixer(volume as u16, self.progressive_volume)); self.mixer.set_volume(volume_to_mixer(volume as u16));
} }
fn handle_end_of_track(&mut self) { fn handle_end_of_track(&mut self) {