diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt
index 49a418d9f..aca193d6f 100644
--- a/sdrbase/CMakeLists.txt
+++ b/sdrbase/CMakeLists.txt
@@ -388,6 +388,7 @@ set(sdrbase_HEADERS
util/db.h
util/doublebuffer.h
util/doublebufferfifo.h
+ util/doublebuffermultiple.h
util/fixedtraits.h
util/fits.h
util/golay2312.h
diff --git a/sdrbase/util/doublebuffermultiple.h b/sdrbase/util/doublebuffermultiple.h
new file mode 100644
index 000000000..a24e25fca
--- /dev/null
+++ b/sdrbase/util/doublebuffermultiple.h
@@ -0,0 +1,268 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2016 Edouard Griffiths, F4EXB //
+// //
+// 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 //
+// (at your option) any later version. //
+// //
+// 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 . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef SDRBASE_UTIL_DOUBLEBUFFERMULTIPLE_H_
+#define SDRBASE_UTIL_DOUBLEBUFFERMULTIPLE_H_
+
+#include
+#include
+
+#include
+
+#include "simpleserializer.h"
+
+template
+class DoubleBufferMultiple
+{
+public:
+ DoubleBufferMultiple()
+ {
+ m_size = 0;
+ m_currentPosition = 0;
+ m_current = m_data.end();
+ }
+
+ ~DoubleBufferMultiple() {}
+
+ DoubleBufferMultiple(const DoubleBufferMultiple& other)
+ {
+ m_size = other.m_size;
+ m_data.resize(other.m_data.size());
+ m_current.resize(other.m_data.size());
+ m_currentPosition = 0;
+
+ for (unsigned int i = 0; i < other.m_data.size(); i++)
+ {
+ m_data[i] = other.m_data[i];
+ m_current[i] = m_data[i].begin();
+ }
+ }
+
+ DoubleBufferMultiple& operator=(const DoubleBufferMultiple& other)
+ {
+ if (&other == this) {
+ return *this;
+ }
+
+ m_size = other.m_size;
+ m_data.resize(other.m_data.size());
+ m_current.resize(other.m_data.size());
+ m_currentPosition = 0;
+
+ for (unsigned int i = 0; i < other.m_data.size(); i++)
+ {
+ m_data[i] = other.m_data[i];
+ m_current[i] = m_data[i].begin();
+ }
+
+ return *this;
+ }
+
+ void resize(int size)
+ {
+ m_size = size;
+ m_currentPosition = 0;
+
+ for (unsigned int i = 0; i < m_data.size(); i++)
+ {
+ m_data[i].resize(2*size);
+ m_current[i] = m_data[i].begin();
+ }
+ }
+
+ void addStream()
+ {
+ m_data.push_back(std::vector(2*m_size));
+ m_current.push_back(std::vector::iterator());
+ m_current.back() = m_data.back().begin();
+ }
+
+ void write(const std::vector::const_iterator>& vbegin, int length)
+ {
+ int insize = length > m_size ? m_size : length;
+
+ if ((m_currentPosition + insize) > m_size)
+ {
+ int sizeLeft = m_size - m_currentPosition;
+ m_currentPosition = insize - sizeLeft;
+ }
+ else
+ {
+ m_currentPosition += insize;
+ }
+
+ for (unsigned int i = 0; i < vbegin.size(); i++)
+ {
+ if (i >= m_data.size()) {
+ break;
+ }
+
+ std::copy(vbegin[i], vbegin[i] + insize, m_current[i]);
+
+ if (((m_current[i] - m_data[i].begin()) + insize) > m_size)
+ {
+ int sizeLeft = m_size - (m_current[i] - m_data[i].begin());
+ std::copy(vbegin[i], vbegin[i] + sizeLeft, m_current[i] + m_size);
+ std::copy(vbegin[i] + sizeLeft, vbegin[i] + insize, m_data[i].begin());
+ m_current[i] = m_data[i].begin() + (insize - sizeLeft);
+ }
+ else
+ {
+ std::copy(vbegin[i], vbegin[i] + insize, m_current[i] + m_size);
+ m_current[i] += insize;
+ }
+ }
+ }
+
+ // void write(const typename std::vector::const_iterator& begin, const typename std::vector::const_iterator& cend)
+ // {
+ // typename std::vector::const_iterator end = cend;
+
+ // if ((end - begin) > m_size) {
+ // end = begin + m_size;
+ // }
+
+ // int insize = end - begin;
+
+ // std::copy(begin, end, m_current);
+
+ // if (((m_current - m_data.begin()) + insize) > m_size)
+ // {
+ // int sizeLeft = m_size - (m_current - m_data.begin());
+ // std::copy(begin, begin + sizeLeft, m_current + m_size);
+ // std::copy(begin + sizeLeft, end, m_data.begin());
+ // m_current = m_data.begin() + (insize - sizeLeft);
+ // }
+ // else
+ // {
+ // std::copy(begin, end, m_current + m_size);
+ // m_current += insize;
+ // }
+ // }
+
+ typename std::vector::iterator getCurrent(unsigned int i) const { return m_current[i] + m_size; }
+ typename std::vector::const_iterator begin(unsigned int i) const { return m_data[i].begin(); }
+ typename std::vector::iterator begin(unsigned int i) { return m_data[i].begin(); }
+ unsigned int absoluteFill(unsigned int i) const { return m_current[i] - m_data[i].begin(); }
+ void reset(unsigned int i) { m_current[i] = m_data[i].begin(); }
+
+ void getCurrent(std::vector::iterator>& vcurrent) const
+ {
+ vcurrent.clear();
+
+ for (unsigned int i = 0; i < m_data.size(); i++) {
+ vcurrent.push_back(m_data[i].begin() + m_currentPosition + m_size);
+ }
+ }
+
+ int getCurrentPosition() const {
+ return m_currentPosition + m_size;
+ }
+
+ void begin(typename std::vector::const_iterator>& vbegin) const
+ {
+ vbegin.clear();
+
+ for (unsigned int i = 0; i < m_data.size(); i++) {
+ vbegin.push_back(m_data[i].begin());
+ }
+ }
+
+ void begin(typename std::vector::iterator>& vbegin)
+ {
+ vbegin.clear();
+
+ for (unsigned int i = 0; i < m_data.size(); i++) {
+ vbegin.push_back(m_data[i].begin());
+ }
+ }
+
+ unsigned int absoluteFill() const { return m_currentPosition; }
+
+ void reset()
+ {
+ m_currentPosition = 0;
+
+ for (unsigned int i = 0; i < m_current.size(); i++) {
+ m_current[i] = m_data[i].begin();
+ }
+ }
+
+ QByteArray serialize() const
+ {
+ SimpleSerializer s(1);
+
+ s.writeU32(1, std::min(m_data.size(), 10U));
+ s.writeS32(2, m_size);
+
+ for (unsigned int i = 0; i < std::min(m_data.size(), 10U); i++)
+ {
+ QByteArray buf(reinterpret_cast(m_data[i].data()), m_data[i].size()*sizeof(T));
+ s.writeU32(10*i + 11, m_current[i] - m_data[i].begin());
+ s.writeBlob(10*i + 12, buf);
+ }
+
+ return s.final();
+ }
+
+ bool deserialize(const QByteArray& data)
+ {
+ SimpleDeserializer d(data);
+
+ if(!d.isValid()) {
+ return false;
+ }
+
+ if (d.getVersion() == 1)
+ {
+ unsigned int tmpUInt;
+ unsigned int nbStreams;
+ QByteArray buf;
+
+ d.readU32(1, &nbStreams, 0);
+ nbStreams = nbStreams > 10 ? 10 : nbStreams;
+ m_data.resize(nbStreams);
+ m_current.resize(nbStreams);
+ d.readS32(2, &m_size, 0);
+
+ for (unsigned int i = 0; i < nbStreams; i++)
+ {
+ m_data.resize(2*m_size);
+ d.readU32(10*i + 11, &tmpUInt, 0);
+ d.readBlob(10*i + 12, &buf);
+ m_current[i] = m_data[i].begin() + tmpUInt;
+ memcpy(reinterpret_cast(m_data[i].data()), buf.data(), buf.size());
+ //qDebug("DoubleBufferMutiple::deserialize: i: %u m_data.size(): %u buf.size(): %d", i, m_data[i].size(), buf.size());
+ //std::copy(reinterpret_cast(m_data.data()), buf.data(), buf.data() + buf.size()); // bug
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+private:
+ int m_size;
+ std::vector> m_data;
+ std::vector::iterator> m_current;
+ int m_currentPosition;
+};
+
+#endif /* SDRBASE_UTIL_DOUBLEBUFFERMULTIPLE_H_ */