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 | | mixer | Mixer to use | MIXER |
| Option | | initial-volume | Initial volume in %, once connected [0-100] | VOLUME |
| Flag | | progressive-volume | Increase volume slowly at low level | |
Taken from here:
https://github.com/ComlOnline/librespot/blob/master/src/main.rs#L88

View file

@ -122,5 +122,4 @@ pub struct ConnectConfig {
pub name: String,
pub device_type: DeviceType,
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("", "device", "Audio device to use. Use '?' to list options", "DEVICE")
.optopt("", "mixer", "Mixer to use", "MIXER")
.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");
.optopt("", "initial-volume", "Initial volume in %, once connected (must be from 0 to 100)", "VOLUME");
let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
@ -160,11 +159,8 @@ fn setup(args: &[String]) -> Setup {
// if argument not present use default values (50%)
else{
initial_volume = 0x8000 as i32;
}
let progressive_volume = matches.opt_present("progressive-volume");
info!("Volume:{}, progressive_volume: {}.", initial_volume, progressive_volume);
}
debug!("Volume \"{}\" !", initial_volume);
let name = matches.opt_str("name").unwrap();
let use_audio_cache = !matches.opt_present("disable-audio-cache");
@ -213,7 +209,6 @@ fn setup(args: &[String]) -> Setup {
name: name,
device_type: device_type,
volume: initial_volume,
progressive_volume,
}
};

View file

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