diff --git a/daemon/src/audio/audiobuffer.cpp b/daemon/src/audio/audiobuffer.cpp
index bd2525cedccbc4a45c188388b8352eba1c619353..5f3c97916c17763253c6dc17cd3795b075b999d9 100644
--- a/daemon/src/audio/audiobuffer.cpp
+++ b/daemon/src/audio/audiobuffer.cpp
@@ -28,8 +28,8 @@
  *  as that of the covered work.
  */
 
-#include <iostream>
 #include "audiobuffer.h"
+#include "logger.h"
 
 AudioBuffer::AudioBuffer(size_t sample_num, unsigned channel_num /* = 1 */, int sample_rate /* = 8000 */)
     :  sampleRate_(sample_rate),
@@ -102,19 +102,17 @@ std::vector<SFLAudioSample> * AudioBuffer::getChannel(unsigned chan /* = 0 */)
     return NULL;
 }
 
-void AudioBuffer::applyGain(unsigned int gain)
-{
-    if (gain != 100)
-        applyGain(gain * 0.01);
-}
-
 void AudioBuffer::applyGain(double gain)
 {
     if (gain == 1.0) return;
 
-    for (unsigned i = 0; i < samples_.size(); i++)
-        for (unsigned j = 0; j < samples_[0].size(); j++)
-            samples_[i][j] *= gain;
+    const double g = std::max(std::min(1.0, gain), -1.0);
+    if (g != gain)
+        WARN("Normalizing %f to [-1.0, 1.0]", gain);
+
+    for (auto &channel : samples_)
+        for (auto &sample : channel)
+            sample *= g;
 }
 
 size_t AudioBuffer::interleave(SFLAudioSample* out) const
diff --git a/daemon/src/audio/audiobuffer.h b/daemon/src/audio/audiobuffer.h
index 95d84007f2aa68cf475f803b9a6237e65879ce19..a3a4ea7dc371327b393216d422f493cdb17e3cc8 100644
--- a/daemon/src/audio/audiobuffer.h
+++ b/daemon/src/audio/audiobuffer.h
@@ -153,13 +153,6 @@ class AudioBuffer {
          */
         void deinterleave(const SFLAudioSample* in, size_t sample_num, unsigned channel_num = 1);
 
-        /**
-         * In-place gain transformation with integer parameter.
-         *
-         * @param gain: 0 -> 100 scale
-         */
-        void applyGain(unsigned int gain);
-
         /**
          * In-place gain transformation.
          *
diff --git a/daemon/src/audio/audiolayer.cpp b/daemon/src/audio/audiolayer.cpp
index 1837f557fe3df707ac5047a59455897cf8cfd088..309d49dee27e7ef2d84f7dc99805ea8476a8cf64 100644
--- a/daemon/src/audio/audiolayer.cpp
+++ b/daemon/src/audio/audiolayer.cpp
@@ -36,8 +36,8 @@
 #include "scoped_lock.h"
 
 AudioLayer::AudioLayer()
-    : captureGain_(100)
-    , playbackGain_(100)
+    : captureGain_(1.0)
+    , playbackGain_(1.0)
     , isStarted_(false)
     , playbackMode_(NONE)
     , urgentRingBuffer_(SIZEBUF, MainBuffer::DEFAULT_ID)
@@ -96,7 +96,7 @@ void AudioLayer::notifyIncomingCall()
     Tone tone("440/160", getSampleRate());
     unsigned int nbSample = tone.getSize();
     AudioBuffer buf(nbSample);
-    tone.getNext(buf);
+    tone.getNext(buf, 1.0);
 
     /* Put the data in the urgent ring buffer */
     flushUrgent();
diff --git a/daemon/src/audio/audiolayer.h b/daemon/src/audio/audiolayer.h
index a79b5b6155a998976fc4f95423c678411bdde2ab..eaec079d170b80410a72834fb870e38c6bdadc27 100644
--- a/daemon/src/audio/audiolayer.h
+++ b/daemon/src/audio/audiolayer.h
@@ -137,45 +137,33 @@ class AudioLayer {
          */
         void flushUrgent();
 
-        /**
-         * Convert audio amplitude value from linear value to dB
-         */
-        static double amplitudeLinearToDB(double value) {
-            return 20.0 * log10(value);
-        }
-
-        /**
-         * Convert audio amplitude from dB to Linear value
-         */
-        static double ampluitudeDBToLinear(double value) {
-            return pow(10.0, value / 20.0);
-        }
-
         /**
          * Set capture stream gain (microphone)
+         * Range should be [-1.0, 1.0]
          */
-        void setCaptureGain(unsigned int gain) {
+        void setCaptureGain(double gain) {
             captureGain_ = gain;
         }
 
         /**
          * Set capture stream gain (microphone)
          */
-        unsigned int getCaptureGain() const {
+        double getCaptureGain() const {
             return captureGain_;
         }
 
         /**
          * Set playback stream gain (speaker)
+         * Range should be [-1.0, 1.0]
          */
-        void setPlaybackGain(unsigned int gain) {
+        void setPlaybackGain(double gain) {
             playbackGain_ = gain;
         }
 
         /**
          * Get playback stream gain (speaker)
          */
-        unsigned int getPlaybackGain() const {
+        double getPlaybackGain() const {
             return playbackGain_;
         }
 
@@ -200,12 +188,12 @@ class AudioLayer {
         /**
          * Gain applied to mic signal
          */
-        unsigned int captureGain_;
+        double captureGain_;
 
         /**
          * Gain applied to playback signal
          */
-        unsigned int playbackGain_;
+        double playbackGain_;
 
         /**
          * Whether or not the audio layer stream is started
diff --git a/daemon/src/audio/audioloop.cpp b/daemon/src/audio/audioloop.cpp
index f1f645ab5899fcfdeef8e5b3c607a75c6a895a75..017725ad427c3620a6f1803e8cdd77031e7fe1e0 100644
--- a/daemon/src/audio/audioloop.cpp
+++ b/daemon/src/audio/audioloop.cpp
@@ -62,7 +62,7 @@ AudioLoop::seek(double relative_position)
 }
 
 void
-AudioLoop::getNext(AudioBuffer& output, unsigned int volume)
+AudioLoop::getNext(AudioBuffer& output, double gain)
 {
     if (!buffer_) {
         ERROR("buffer is NULL");
@@ -93,7 +93,7 @@ AudioLoop::getNext(AudioBuffer& output, unsigned int volume)
         total_samples -= samples;
     }
 
-    output.applyGain(volume); // apply volume
+    output.applyGain(gain);
 
     pos_ = pos;
 
diff --git a/daemon/src/audio/audioloop.h b/daemon/src/audio/audioloop.h
index d2ddef0fabd793b1306a73d9505107a5a8170928..9d58060dc3d8c99429686607ca1c545f4849e051 100644
--- a/daemon/src/audio/audioloop.h
+++ b/daemon/src/audio/audioloop.h
@@ -54,9 +54,9 @@ class AudioLoop {
          * the function change the intern position, and will loop
          * @param output  The data buffer
          * @param nb of int16 to send
-         * @param volume  The volume
+         * @param gain The gain [-1.0, 1.0]
          */
-        void getNext(AudioBuffer& output, unsigned int volume=100);
+        void getNext(AudioBuffer& output, double gain);
 
         void seek(double relative_position);
 
diff --git a/daemon/src/client/dbus/callmanager.cpp b/daemon/src/client/dbus/callmanager.cpp
index 265120d0d9d461ba5b7f13db04966ef10bbfe6ac..a1a6803e627ae2b6d371f6bce1ee91ce6f604c66 100644
--- a/daemon/src/client/dbus/callmanager.cpp
+++ b/daemon/src/client/dbus/callmanager.cpp
@@ -123,9 +123,9 @@ void CallManager::setVolume(const std::string& device, const double& value)
     DEBUG("DBUS set volume for %s: %f", device.c_str(), value);
 
     if (device == "speaker") {
-        audiolayer->setPlaybackGain((int)(value * 100.0));
+        audiolayer->setPlaybackGain(value);
     } else if (device == "mic") {
-        audiolayer->setCaptureGain((int)(value * 100.0));
+        audiolayer->setCaptureGain(value);
     }
 
     volumeChanged(device, value);
@@ -142,9 +142,9 @@ CallManager::getVolume(const std::string& device)
     }
 
     if (device == "speaker")
-        return audiolayer->getPlaybackGain() / 100.0;
+        return audiolayer->getPlaybackGain();
     else if (device == "mic")
-        return audiolayer->getCaptureGain() / 100.0;
+        return audiolayer->getCaptureGain();
 
     return 0;
 }
diff --git a/daemon/src/preferences.h b/daemon/src/preferences.h
index 0edbefd803813f1877ceb8cb4c1a3c47d09f1cc0..27ad5470622919643abb2b1b54edf81389a54b5e 100644
--- a/daemon/src/preferences.h
+++ b/daemon/src/preferences.h
@@ -308,17 +308,17 @@ class AudioPreference : public Serializable {
             alwaysRecording_ = rec;
         }
 
-        int getVolumemic() const {
+        double getVolumemic() const {
             return volumemic_;
         }
-        void setVolumemic(int m) {
+        void setVolumemic(double m) {
             volumemic_ = m;
         }
 
-        int getVolumespkr() const {
+        double getVolumespkr() const {
             return volumespkr_;
         }
-        void setVolumespkr(int s) {
+        void setVolumespkr(double s) {
             volumespkr_ = s;
         }