Browse Source

Changed volume control after discussion: https://github.com/librespot-org/librespot/pull/10
implement exponential volume control only

Robert 7 years ago
parent
commit
bec6b8c512
4 changed files with 28 additions and 41 deletions
  1. 0 1
      README.md
  2. 0 1
      core/src/config.rs
  3. 3 8
      src/main.rs
  4. 25 31
      src/spirc.rs

+ 0 - 1
README.md

@@ -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

+ 0 - 1
core/src/config.rs

@@ -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,
 }
 }

+ 3 - 8
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,
         }
         }
     };
     };
 
 

+ 25 - 31
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) {