Browse Source

Merge pull request #188 from thekr1s/linear-volume-control

Add optional linear volume contol
Sasha Hilton 7 years ago
parent
commit
085f76162f
3 changed files with 30 additions and 6 deletions
  1. 23 6
      connect/src/spirc.rs
  2. 1 0
      core/src/config.rs
  3. 6 0
      src/main.rs

+ 23 - 6
connect/src/spirc.rs

@@ -24,6 +24,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
 pub struct SpircTask {
     player: Player,
     mixer: Box<Mixer>,
+    linear_volume: bool,
 
     sequence: SeqGenerator<u32>,
 
@@ -170,7 +171,7 @@ fn initial_device_state(config: ConnectConfig, volume: u16) -> DeviceState {
     }
 }
 
-fn volume_to_mixer(volume: u16) -> u16 {
+fn calc_logarithmic_volume(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.
@@ -192,6 +193,15 @@ fn volume_to_mixer(volume: u16) -> u16 {
     val
 }
 
+fn volume_to_mixer(volume: u16, linear_volume: bool) -> u16 {
+    if linear_volume {
+        debug!("linear volume: {}", volume);
+        volume
+    } else {
+        calc_logarithmic_volume(volume)
+    }
+}
+
 impl Spirc {
     pub fn new(
         config: ConnectConfig,
@@ -224,12 +234,15 @@ impl Spirc {
         let (cmd_tx, cmd_rx) = mpsc::unbounded();
 
         let volume = config.volume as u16;
+        let linear_volume = config.linear_volume;
+
         let device = initial_device_state(config, volume);
-        mixer.set_volume(volume_to_mixer(volume as u16));
+        mixer.set_volume(volume_to_mixer(volume as u16, linear_volume));
 
         let mut task = SpircTask {
             player: player,
             mixer: mixer,
+            linear_volume: linear_volume,
 
             sequence: SeqGenerator::new(1),
 
@@ -517,8 +530,10 @@ impl SpircTask {
 
             MessageType::kMessageTypeVolume => {
                 self.device.set_volume(frame.get_volume());
-                self.mixer
-                    .set_volume(volume_to_mixer(frame.get_volume() as u16));
+                self.mixer.set_volume(volume_to_mixer(
+                    frame.get_volume() as u16,
+                    self.linear_volume,
+                ));
                 self.notify(None);
             }
 
@@ -642,7 +657,8 @@ impl SpircTask {
             volume = 0xFFFF;
         }
         self.device.set_volume(volume);
-        self.mixer.set_volume(volume_to_mixer(volume as u16));
+        self.mixer
+            .set_volume(volume_to_mixer(volume as u16, self.linear_volume));
     }
 
     fn handle_volume_down(&mut self) {
@@ -651,7 +667,8 @@ impl SpircTask {
             volume = 0;
         }
         self.device.set_volume(volume as u32);
-        self.mixer.set_volume(volume_to_mixer(volume as u16));
+        self.mixer
+            .set_volume(volume_to_mixer(volume as u16, self.linear_volume));
     }
 
     fn handle_end_of_track(&mut self) {

+ 1 - 0
core/src/config.rs

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

+ 6 - 0
src/main.rs

@@ -166,6 +166,11 @@ fn setup(args: &[String]) -> Setup {
             "normalisation-pregain",
             "Pregain (dB) applied by volume normalisation",
             "PREGAIN",
+        )
+        .optflag(
+            "",
+            "linear-volume",
+            "increase volume linear instead of logarithmic.",
         );
 
     let matches = match opts.parse(&args[1..]) {
@@ -282,6 +287,7 @@ fn setup(args: &[String]) -> Setup {
             name: name,
             device_type: device_type,
             volume: initial_volume,
+            linear_volume: matches.opt_present("linear-volume"),
         }
     };