mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Changed volume control after discussion: https://github.com/librespot-org/librespot/pull/10
implement exponential volume control only
This commit is contained in:
parent
de7d341faa
commit
bec6b8c512
4 changed files with 28 additions and 41 deletions
1
README.md
Executable file → Normal file
1
README.md
Executable file → Normal 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
|
||||||
|
|
|
@ -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,
|
|
||||||
}
|
}
|
||||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -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,
|
||||||
|
@ -160,11 +159,8 @@ fn setup(args: &[String]) -> Setup {
|
||||||
// if argument not present use default values (50%)
|
// if argument not present use default values (50%)
|
||||||
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,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
56
src/spirc.rs
56
src/spirc.rs
|
@ -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
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 (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) {
|
||||||
|
|
Loading…
Reference in a new issue