diff --git a/sdrdaemon/CMakeLists.txt b/sdrdaemon/CMakeLists.txt
index aa834977d..fa97be443 100644
--- a/sdrdaemon/CMakeLists.txt
+++ b/sdrdaemon/CMakeLists.txt
@@ -12,6 +12,7 @@ set(sdrdaemon_SOURCES
channel/sdrdaemonchannelsinksettings.cpp
channel/sdrdaemonchannelsourcesettings.cpp
channel/sdrdaemonchannelsourcethread.cpp
+ channel/sdrdaemonchannelsourcebuffer.cpp
webapi/webapiadapterdaemon.cpp
webapi/webapirequestmapper.cpp
webapi/webapiserver.cpp
@@ -30,6 +31,7 @@ set(sdrdaemon_HEADERS
channel/sdrdaemonchannelsinksettings.h
channel/sdrdaemonchannelsourcesettings.h
channel/sdrdaemonchannelsourcethread.h
+ channel/sdrdaemonchannelsourcebuffer.h
webapi/webapiadapterdaemon.h
webapi/webapirequestmapper.h
webapi/webapiserver.h
diff --git a/sdrdaemon/channel/sdrdaemonchannelsourcebuffer.cpp b/sdrdaemon/channel/sdrdaemonchannelsourcebuffer.cpp
new file mode 100644
index 000000000..8cc2112e9
--- /dev/null
+++ b/sdrdaemon/channel/sdrdaemonchannelsourcebuffer.cpp
@@ -0,0 +1,85 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
+// //
+// SDRdaemon source channel (Tx). Samples buffer //
+// //
+// SDRdaemon is a detached SDR front end that handles the interface with a //
+// physical device and sends or receives the I/Q samples stream to or from a //
+// SDRangel instance via UDP. It is controlled via a Web REST API. //
+// //
+// 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 //
+// the Free Software Foundation as version 3 of the License, or //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include "channel/sdrdaemonchannelsourcebuffer.h"
+
+SDRDaemonChannelSourceBuffer::SDRDaemonChannelSourceBuffer(uint32_t nbSamples)
+{
+ m_buffer = new Sample[nbSamples];
+ m_wp = nbSamples/2;
+ m_rp = 0;
+ m_size = nbSamples;
+}
+
+SDRDaemonChannelSourceBuffer::~SDRDaemonChannelSourceBuffer()
+{
+ delete[] m_buffer;
+}
+
+void SDRDaemonChannelSourceBuffer::resize(uint32_t nbSamples)
+{
+ if (nbSamples > m_size)
+ {
+ delete[] m_buffer;
+ m_buffer = new Sample[nbSamples];
+ }
+
+ m_wp = nbSamples/2;
+ m_rp = 0;
+ m_size = nbSamples;
+}
+
+void SDRDaemonChannelSourceBuffer::write(Sample *begin, uint32_t nbSamples)
+{
+ if (m_wp + nbSamples < m_size)
+ {
+ std::copy(begin, begin+nbSamples, &m_buffer[m_wp]);
+ m_wp += nbSamples;
+ }
+ else // wrap
+ {
+ int first = m_size - m_wp;
+ std::copy(begin, begin+first, &m_buffer[m_wp]);
+ int second = nbSamples - first;
+ std::copy(begin+first, begin+nbSamples, m_buffer);
+ m_wp = second;
+ }
+}
+
+void SDRDaemonChannelSourceBuffer::readOne(Sample& sample)
+{
+ sample = m_buffer[m_rp];
+ m_rp++;
+
+ if (m_rp == m_size) { // wrap
+ m_rp = 0;
+ }
+}
+
+int SDRDaemonChannelSourceBuffer::getRWBalancePercent()
+{
+ if (m_wp > m_rp) {
+ return (((m_wp - m_rp) - (m_size/2))*100)/m_size;
+ } else {
+ return (((m_size/2) - (m_rp - m_wp))*100)/m_size;
+ }
+}
\ No newline at end of file
diff --git a/sdrdaemon/channel/sdrdaemonchannelsourcebuffer.h b/sdrdaemon/channel/sdrdaemonchannelsourcebuffer.h
new file mode 100644
index 000000000..7ec10bde7
--- /dev/null
+++ b/sdrdaemon/channel/sdrdaemonchannelsourcebuffer.h
@@ -0,0 +1,42 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
+// //
+// SDRdaemon source channel (Tx). Samples buffer //
+// //
+// SDRdaemon is a detached SDR front end that handles the interface with a //
+// physical device and sends or receives the I/Q samples stream to or from a //
+// SDRangel instance via UDP. It is controlled via a Web REST API. //
+// //
+// 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 //
+// the Free Software Foundation as version 3 of the License, or //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include
+
+#include "dsp/dsptypes.h"
+
+class SDRDaemonChannelSourceBuffer
+{
+public:
+ SDRDaemonChannelSourceBuffer(uint32_t nbSamples);
+ ~SDRDaemonChannelSourceBuffer();
+ void resize(uint32_t nbSamples);
+ void write(Sample *begin, uint32_t nbSamples);
+ void readOne(Sample& sample);
+ int getRWBalancePercent(); //!< positive write leads, negative read leads, balance = 0, percentage of buffer size
+
+private:
+ Sample *m_buffer;
+ uint32_t m_size;
+ uint32_t m_rp;
+ uint32_t m_wp;
+};