diff --git a/daemon/src/audio/audiobuffer.cpp b/daemon/src/audio/audiobuffer.cpp
index 13042d25f77a827245b9f654eadd19f3d464c5e2..9918a93438a525bb8af5f17c6de324187fb72d7a 100644
--- a/daemon/src/audio/audiobuffer.cpp
+++ b/daemon/src/audio/audiobuffer.cpp
@@ -160,18 +160,21 @@ void AudioBuffer::fromInterleaved(const SFLAudioSample* in, size_t sample_num, u
     }
 }
 
-size_t AudioBuffer::mix(const AudioBuffer& other)
+size_t AudioBuffer::mix(const AudioBuffer& other, bool up /* = true */)
 {
+    const bool upmix = up && (other.channels_ < channels_);
     const size_t samp_num = std::min(sampleNum_, other.sampleNum_);
-    const unsigned chan_num = std::min(channels_, other.channels_);
+    const unsigned chan_num = upmix ? channels_ : std::min(channels_, other.channels_);
+
     for(unsigned i=0; i<chan_num; i++) {
+        unsigned src_chan = upmix ? std::min(i, other.channels_-1) : i;
         for(unsigned j=0; j<samp_num; j++)
-            samples_[i][j] += other.samples_[i][j];
+            samples_[i][j] += other.samples_[src_chan][j];
     }
     return samp_num;
 }
 
-size_t AudioBuffer::copy(AudioBuffer& in, int sample_num /* = -1 */, size_t pos_in /* = 0 */, size_t pos_out /* = 0 */)
+size_t AudioBuffer::copy(AudioBuffer& in, int sample_num /* = -1 */, size_t pos_in /* = 0 */, size_t pos_out /* = 0 */, bool up /* = true */)
 {
     if(sample_num == -1)
         sample_num = in.samples();
@@ -179,7 +182,8 @@ size_t AudioBuffer::copy(AudioBuffer& in, int sample_num /* = -1 */, size_t pos_
     int to_copy = std::min((int)in.samples()-(int)pos_in, sample_num);
     if(to_copy <= 0) return 0;
 
-    const size_t chan_num = std::min(in.channels_, channels_);
+    const bool upmix = up && (in.channels_ < channels_);
+    const size_t chan_num = upmix ? channels_ : std::min(in.channels_, channels_);
 
     if(pos_out+to_copy > sampleNum_)
         resize(pos_out+to_copy);
@@ -189,7 +193,8 @@ size_t AudioBuffer::copy(AudioBuffer& in, int sample_num /* = -1 */, size_t pos_
 
     unsigned i;
     for(i=0; i<chan_num; i++) {
-        std::copy(in.samples_[i].begin()+pos_in, in.samples_[i].begin()+pos_in+to_copy, samples_[i].begin()+pos_out);
+        unsigned src_chan = upmix ? std::min(i, in.channels_-1) : i;
+        std::copy(in.samples_[src_chan].begin()+pos_in, in.samples_[src_chan].begin()+pos_in+to_copy, samples_[i].begin()+pos_out);
     }
 
     return to_copy;
diff --git a/daemon/src/audio/audiobuffer.h b/daemon/src/audio/audiobuffer.h
index 36a1905518f502321f21e52357c44d3ba33872d3..a55dfb95acedc65a5d357d171c795ba95d6a69c2 100644
--- a/daemon/src/audio/audiobuffer.h
+++ b/daemon/src/audio/audiobuffer.h
@@ -35,7 +35,6 @@
 #include <cstddef> // for size_t
 
 #include "sfl_types.h"
-//#include "noncopyable.h"
 
 class AudioBuffer {
     public:
@@ -98,8 +97,8 @@ class AudioBuffer {
          * Return the total number of single samples in the buffer (same as samples()*channels()).
          */
         inline size_t capacity() const {
-			return samples()*channels();
-		}
+            return samples()*channels();
+        }
 
         /**
          * Resize the buffer to make it able to hold sample_num multichannel samples.
@@ -165,12 +164,20 @@ class AudioBuffer {
         void applyGain(double gain);
 
         /**
-         * Mix elements of the other buffer with this buffer (in-place simple addition).
+         * Mix elements of the other buffer within this buffer (in-place simple addition).
+         * If other.channels() is higher than this.channels(), only the first this.channels() channels are imported.
+         * If other.channels() is lower than this.channels(), behavior depends on upmix.
+         * Sample rate is not considered by this function.
+         *
          * TODO: some kind of check for overflow/saturation.
          *
+         * @param other: the other buffer to mix in this one.
+         * @param upmix: if true, upmixing occurs when other.channels() < this.channels().
+         *              If false, only the first other.channels() channels are edited in this buffer.
+         *
          * @returns Number of samples modified.
          */
-        size_t mix(const AudioBuffer& other);
+        size_t mix(const AudioBuffer& other, bool upmix=true);
 
         /**
          * Copy sample_num samples from in (from sample pos_in) to this buffer (at sample pos_out).
@@ -179,7 +186,7 @@ class AudioBuffer {
          * The number of channels is changed to match the in channel number.
          * Buffer sample number is also increased if required to hold the new requested samples.
          */
-        size_t copy(AudioBuffer& in, int sample_num=-1, size_t pos_in=0, size_t pos_out=0);
+        size_t copy(AudioBuffer& in, int sample_num=-1, size_t pos_in=0, size_t pos_out=0, bool upmix=true);
 
         /**
          * Copy sample_num samples from in to this buffer (at sample pos_out).
@@ -190,8 +197,6 @@ class AudioBuffer {
         size_t copy(SFLAudioSample* in, size_t sample_num, size_t pos_out=0);
 
     private:
-        //NON_COPYABLE(AudioBuffer);
-
         int sampleRate_;
         unsigned channels_; // should allways be the same as samples_.size()
         size_t sampleNum_;
diff --git a/daemon/src/audio/audioloop.cpp b/daemon/src/audio/audioloop.cpp
index 7a525a8efefcd1d15f0540e852ddf1bd7d207723..cfc8f936b364a034a8832ab92f5101a86f4801c4 100644
--- a/daemon/src/audio/audioloop.cpp
+++ b/daemon/src/audio/audioloop.cpp
@@ -49,7 +49,6 @@ AudioLoop::AudioLoop(unsigned int sampleRate) : buffer_(), pos_(0), isRecording_
 
 AudioLoop::~AudioLoop()
 {
-    //delete [] buffer_;
     delete buffer_;
 }
 
@@ -64,7 +63,6 @@ AudioLoop::seek(double relative_position)
 static unsigned int updatePlaybackScale = 0;
 
 void
-//AudioLoop::getNext(SFLAudioSample* output, size_t total_samples, short volume)
 AudioLoop::getNext(AudioBuffer& output, unsigned int volume)
 {
     if(!buffer_) {
@@ -88,23 +86,8 @@ AudioLoop::getNext(AudioBuffer& output, unsigned int volume)
     while (total_samples > 0) {
         size_t samples = std::min(total_samples, buf_samples - pos);
 
-       /* if (samples > (buf_samples - pos))
-            samples = buf_samples - pos;*/
-
-        // short->char conversion
-        //memcpy(output, buffer_ + pos, samples * sizeof(SFLAudioSample));
-        //buffer_.copy(output, pos, samples);
         output.copy(*buffer_, samples, pos, output_pos);
 
-        // Scaling needed
-        /*if (volume != 100) {
-            const double gain = volume * 0.01;
-
-            for (size_t i = 0; i < samples; ++i, ++output)
-                *output *= gain;
-        } else
-            output_pos += samples;*/
-            //output += samples; // this is the destination...
         output_pos += samples;
         pos = (pos + samples) % buf_samples;
 
diff --git a/daemon/src/audio/audioloop.h b/daemon/src/audio/audioloop.h
index e51dbe8f5d4e32f064becc6a809f866ceeaf8047..c6eed88eff695d4de51bdbacff364d3bb0a86727 100644
--- a/daemon/src/audio/audioloop.h
+++ b/daemon/src/audio/audioloop.h
@@ -56,7 +56,6 @@ class AudioLoop {
          * @param nb of int16 to send
          * @param volume  The volume
          */
-        //void getNext(SFLAudioSample* output, size_t samples, short volume=100);
         void getNext(AudioBuffer& output, unsigned int volume=100);
 
         void seek(double relative_position);
@@ -73,7 +72,7 @@ class AudioLoop {
          * @return unsigned int The size
          */
         size_t getSize() {
-            return buffer_->samples();//size_;
+            return buffer_->samples();
         }
 
         /**
@@ -87,17 +86,10 @@ class AudioLoop {
     protected:
         /** The data buffer */
         AudioBuffer * buffer_;
-        //SFLAudioSample* buffer_;
-
-        /** Number of samples inside the buffer */
-        //size_t size_;
 
         /** current position, set to 0, when initialize */
         size_t pos_;
 
-        /** Sample rate */
-        //unsigned int sampleRate_;
-
         /** Is a playback recording */
         bool isRecording_;
 
diff --git a/daemon/src/audio/pulseaudio/pulselayer.cpp b/daemon/src/audio/pulseaudio/pulselayer.cpp
index f061d914942a9bda94eaca9afbe2a8407fcd2ab9..e04d6fd656e93b8a0001a997c2cf58f1fd20a699 100644
--- a/daemon/src/audio/pulseaudio/pulselayer.cpp
+++ b/daemon/src/audio/pulseaudio/pulselayer.cpp
@@ -135,8 +135,6 @@ PulseLayer::~PulseLayer()
 
     if (mainloop_)
         pa_threaded_mainloop_free(mainloop_);
-
-    //delete [] mic_buffer_;
 }
 
 void PulseLayer::context_state_callback(pa_context* c, void *user_data)
@@ -365,6 +363,8 @@ void PulseLayer::writeToSpeaker()
     } else if (ret == 0)
         return;
 
+    DEBUG("writeToSpeaker with n_channels=%d", n_channels);
+
     size_t writableBytes = ret;
     size_t writableSamples = writableBytes/sample_size;
 
diff --git a/daemon/src/audio/pulseaudio/pulselayer.h b/daemon/src/audio/pulseaudio/pulselayer.h
index cba5d1d2ef3012e0e5d14a94ac4150a75df390c8..f9c1b3c1fe592a8f0d2df7999ca41908eca53867 100644
--- a/daemon/src/audio/pulseaudio/pulselayer.h
+++ b/daemon/src/audio/pulseaudio/pulselayer.h
@@ -55,15 +55,15 @@ typedef struct PaDeviceInfos {
     pa_channel_map channel_map;
 
     PaDeviceInfos(unsigned idx, const char* ep_name, pa_sample_spec samp_spec, pa_channel_map chan_map)
-        : index(idx), name(ep_name), sample_spec(samp_spec), channel_map(chan_map)
-    {}
+        : index(idx), name(ep_name), sample_spec(samp_spec), channel_map(chan_map) {}
+    virtual ~PaDeviceInfos() {}
 
     /**
      * Unary function to search for a device by name in a list using std functions.
      */
     struct nameComparator : public std::unary_function<const PaDeviceInfos, bool>
     {
-        explicit nameComparator(const std::string &baseline) : baseline(baseline) {}
+        explicit nameComparator(const std::string &ref) : baseline(ref) {}
         bool operator() (const PaDeviceInfos &arg) {
             return arg.name == baseline;
         }
diff --git a/daemon/src/audio/ringbuffer.cpp b/daemon/src/audio/ringbuffer.cpp
index deca77200859c28c1e77e8c646df4c3739363fc1..9c0bb544b333b8d62443ec7cb5a9a4414f1c3f99 100644
--- a/daemon/src/audio/ringbuffer.cpp
+++ b/daemon/src/audio/ringbuffer.cpp
@@ -3,6 +3,7 @@
  *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
+ *  Author: Adrien Beraud <adrien.beraud@gmail.com>
  *
  *  Portions (c) Dominic Mazzoni (Audacity)
  *
@@ -40,15 +41,14 @@
 #include "ringbuffer.h"
 
 namespace {
-    // corresponds to 106 ms (about 5 rtp packets)
+    // corresponds to 160 ms (about 5 rtp packets)
     const size_t MIN_BUFFER_SIZE = 1280;
 }
 
 // Create  a ring buffer with 'size' bytes
 RingBuffer::RingBuffer(size_t size, const std::string &call_id) :
       endPos_(0)
-    , bufferSize_(std::max(size, MIN_BUFFER_SIZE))
-    , buffer_(1, std::vector<SFLAudioSample>(bufferSize_))
+    , buffer_(std::max(size, MIN_BUFFER_SIZE), 1)
     , readpointers_()
     , buffer_id_(call_id)
 {
@@ -73,19 +73,21 @@ RingBuffer::flushAll()
 size_t
 RingBuffer::putLength() const
 {
+    const size_t buffer_size = buffer_.samples();
     const size_t startPos = (not readpointers_.empty()) ? getSmallestReadPointer() : 0;
-    return (endPos_ + bufferSize_ - startPos) % bufferSize_;
+    return (endPos_ + buffer_size - startPos) % buffer_size;
 }
 
 size_t RingBuffer::getLength(const std::string &call_id) const
 {
-    return (endPos_ + bufferSize_ - getReadPointer(call_id)) % bufferSize_;
+    const size_t buffer_size = buffer_.samples();
+    return (endPos_ + buffer_size - getReadPointer(call_id)) % buffer_size;
 }
 
 void
 RingBuffer::debug()
 {
-    DEBUG("Start=%d; End=%d; BufferSize=%d", getSmallestReadPointer(), endPos_, bufferSize_);
+    DEBUG("Start=%d; End=%d; BufferSize=%d", getSmallestReadPointer(), endPos_, buffer_.samples());
 }
 
 size_t RingBuffer::getReadPointer(const std::string &call_id) const
@@ -103,7 +105,7 @@ RingBuffer::getSmallestReadPointer() const
     if (hasNoReadPointers())
         return 0;
 
-    size_t smallest = bufferSize_;
+    size_t smallest = buffer_.samples();
 
     ReadPointer::const_iterator iter;
 
@@ -161,22 +163,20 @@ bool RingBuffer::hasNoReadPointers() const
 //
 
 // This one puts some data inside the ring buffer.
-//void RingBuffer::put(void* buffer, size_t toCopy)
 void RingBuffer::put(AudioBuffer& buf)
 {
     const size_t len = putLength();
-    const unsigned chans = buf.channels();
     const size_t sample_num = buf.samples();
+    const size_t buffer_size = buffer_.samples();
     size_t toCopy = sample_num;
 
     // Add more channels if the input buffer holds more channels than the ring.
-    if(buffer_.size() < chans)
-        buffer_.resize(chans, std::vector<SFLAudioSample>(bufferSize_, 0));
+    if(buffer_.channels() < buf.channels())
+        buffer_.setChannelNum(buf.channels());
 
-    if (toCopy > bufferSize_ - len)
-        toCopy = bufferSize_ - len;
+    if (toCopy > buffer_size - len)
+        toCopy = buffer_size - len;
 
-    //unsigned char *src = static_cast<SFLAudioSample *>(buffer);
     size_t in_pos = 0;
     size_t pos = endPos_;
 
@@ -184,14 +184,12 @@ void RingBuffer::put(AudioBuffer& buf)
         size_t block = toCopy;
         size_t i;
 
-        if (block > bufferSize_ - pos) // Wrap block around ring ?
-            block = bufferSize_ - pos; // Fill in to the end of the buffer
+        if (block > buffer_size - pos) // Wrap block around ring ?
+            block = buffer_size - pos; // Fill in to the end of the buffer
 
-        for(i=0; i<chans; i++) {
-            copy(buf.getChannel(i)->begin()+in_pos, buf.getChannel(i)->begin()+in_pos+block, buffer_[i].begin()+pos);
-        }
+        buffer_.copy(buf, block, in_pos, pos);
         in_pos += block;
-        pos = (pos + block) % bufferSize_;
+        pos = (pos + block) % buffer_size;
         toCopy -= block;
     }
     endPos_ = pos;
@@ -209,7 +207,6 @@ RingBuffer::availableForGet(const std::string &call_id) const
 }
 
 // Get will move 'toCopy' bytes from the internal FIFO to 'buffer'
-//size_t RingBuffer::get(void *buffer, size_t toCopy, const std::string &call_id)
 size_t RingBuffer::get(AudioBuffer& buf, const std::string &call_id)
 {
     if (hasNoReadPointers())
@@ -220,12 +217,9 @@ size_t RingBuffer::get(AudioBuffer& buf, const std::string &call_id)
 
     const size_t len = getLength(call_id);
     const size_t sample_num = buf.samples();
-    const size_t chans = std::min((unsigned)buffer_.size(), buf.channels());
+    const size_t buffer_size = buffer_.samples();
     size_t toCopy = std::min(sample_num, len);
 
-  /*  if (toCopy > len)
-        toCopy = len;*/
-
     const size_t copied = toCopy;
 
     size_t dest = 0;
@@ -235,17 +229,13 @@ size_t RingBuffer::get(AudioBuffer& buf, const std::string &call_id)
         size_t block = toCopy;
         unsigned i;
 
-        if (block > bufferSize_ - startPos)
-            block = bufferSize_ - startPos;
+        if (block > buffer_size - startPos)
+            block = buffer_size - startPos;
 
-        for(i=0; i<chans; i++) {
-            copy(buffer_[i].begin()+startPos, buffer_[i].begin()+startPos+block, buf.getChannel(i)->begin()+dest);
-           // memcpy(buf->getChannel(i), &(*buffer_[i].begin()) + startPos, block);
-        }
+        buf.copy(buffer_, block, startPos, dest);
 
-        //memcpy(dest, &(*buffer_.begin()) + startPos, block);
         dest += block;
-        startPos = (startPos + block) % bufferSize_;
+        startPos = (startPos + block) % buffer_size;
         toCopy -= block;
     }
 
@@ -261,7 +251,8 @@ RingBuffer::discard(size_t toDiscard, const std::string &call_id)
     if (toDiscard > len)
         toDiscard = len;
 
-    size_t startPos = (getReadPointer(call_id) + toDiscard) % bufferSize_;
+    size_t buffer_size = buffer_.samples();
+    size_t startPos = (getReadPointer(call_id) + toDiscard) % buffer_size;
 
     storeReadPointer(startPos, call_id);
 
diff --git a/daemon/src/audio/ringbuffer.h b/daemon/src/audio/ringbuffer.h
index 3f9f304041ef3e348464e260cae31f93715f569b..9977e8978508ff1ea0a0444aa34bcbf287b54d27 100644
--- a/daemon/src/audio/ringbuffer.h
+++ b/daemon/src/audio/ringbuffer.h
@@ -3,6 +3,7 @@
  *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
  *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
  *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
+ *  Author: Adrien Beraud <adrien.beraud@gmail.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -98,7 +99,6 @@ class RingBuffer {
          * @param toCopy Number of bytes to copy
          */
          void put(AudioBuffer& buf);
-        //void put(void* buffer, size_t toCopy);
 
         /**
          * To get how much samples are available in the buffer to read in
@@ -113,7 +113,6 @@ class RingBuffer {
          * @return size_t Number of bytes copied
          */
          size_t get(AudioBuffer& buf, const std::string &call_id);
-        //size_t get(void* buffer, size_t toCopy, const std::string &call_id);
 
         /**
          * Discard data from the buffer
@@ -141,10 +140,8 @@ class RingBuffer {
 
         /** Pointer on the last data */
         size_t endPos_;
-        /** Buffer size */
-        size_t bufferSize_;
         /** Data */
-        std::vector<std::vector<SFLAudioSample> > buffer_;
+        AudioBuffer buffer_;
 
         ReadPointer readpointers_;
         std::string buffer_id_;
diff --git a/daemon/src/audio/sound/dtmf.h b/daemon/src/audio/sound/dtmf.h
index 994dbcd6670c09707fbe2c7b0529550ec809e00e..f53c36671bf3dcbd68a140443dd20593e0047a7d 100644
--- a/daemon/src/audio/sound/dtmf.h
+++ b/daemon/src/audio/sound/dtmf.h
@@ -58,7 +58,7 @@ class DTMF {
 
         /**
          * Copy the sound inside the sampling* buffer
-         * @param buffer : a vector of SFLDataFormat
+         * @param buffer : a vector of SFLAudioSample
          */
         bool generateDTMF(std::vector<SFLAudioSample> &buffer);
 
diff --git a/daemon/test/mainbuffertest.cpp b/daemon/test/mainbuffertest.cpp
index a505427ded9950a3ff020bc62131e681933e8507..56f281e62934ad891bb171b6a23fee715a98f3f2 100644
--- a/daemon/test/mainbuffertest.cpp
+++ b/daemon/test/mainbuffertest.cpp
@@ -422,7 +422,7 @@ void MainBufferTest::testTwoPointer()
 
     input_buffer->put(test_input);
     CPPUNIT_ASSERT(output_buffer->get(test_output, MainBuffer::DEFAULT_ID) == 1);
-    CPPUNIT_ASSERT((*test_input.getChannel())[0] == (*test_output.getChannel())[0]);
+    CPPUNIT_ASSERT(test_sample == (*test_output.getChannel())[0]);
 
 }