From fa0afb6c9209711d437eca5838e1fd138ce164ef Mon Sep 17 00:00:00 2001
From: f4exb <f4exb06@gmail.com>
Date: Mon, 2 Jan 2017 03:14:46 +0100
Subject: [PATCH] Tx support: implemented final interpolation stage in FileSink
 plugin

---
 CMakeLists.txt                                |   1 +
 devices/readme.md                             |  12 +
 plugins/samplesink/filesink/filesinkgui.cpp   |  13 +-
 plugins/samplesink/filesink/filesinkgui.h     |   1 +
 plugins/samplesink/filesink/filesinkgui.ui    |  49 ++
 .../samplesink/filesink/filesinkoutput.cpp    |  22 +-
 .../samplesink/filesink/filesinksettings.cpp  |   3 +
 .../samplesink/filesink/filesinksettings.h    |   1 +
 .../samplesink/filesink/filesinkthread.cpp    |  98 ++-
 plugins/samplesink/filesink/filesinkthread.h  |   7 +
 .../bladerfinput/bladerfinput.cpp             |  55 +-
 .../samplesource/bladerfinput/bladerfinput.h  |   2 +-
 sdrbase/dsp/interpolators.h                   | 617 ++++++++++++++++++
 sdrbase/sdrbase.pro                           |   1 +
 14 files changed, 841 insertions(+), 41 deletions(-)
 create mode 100644 devices/readme.md
 create mode 100644 sdrbase/dsp/interpolators.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c7907fcd5..17374ad4b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -199,6 +199,7 @@ set(sdrbase_HEADERS
     sdrbase/dsp/complex.h
     sdrbase/dsp/cwkeyer.h
     sdrbase/dsp/decimators.h
+    sdrbase/dsp/interpolators.h
     sdrbase/dsp/dspcommands.h
     sdrbase/dsp/dspengine.h
     sdrbase/dsp/dspdevicesourceengine.h
diff --git a/devices/readme.md b/devices/readme.md
new file mode 100644
index 000000000..0da09eaea
--- /dev/null
+++ b/devices/readme.md
@@ -0,0 +1,12 @@
+<h1>Devices common resources</h1>
+
+This folder contains classes and methods that can be used by different plugins that work with a common physical device. Thus this can be one of the following physical devices:
+
+  - BladeRF: one Rx and one Tx full duplex. Plugins are:
+    - bladerfinput
+    - bladerfoutput
+    
+  - HackRF: one Rx and one Tx half duplex. Plugins are:
+    - hackrfinput
+    - hackrfoutput
+  
\ No newline at end of file
diff --git a/plugins/samplesink/filesink/filesinkgui.cpp b/plugins/samplesink/filesink/filesinkgui.cpp
index 1381afa8c..166557b8a 100644
--- a/plugins/samplesink/filesink/filesinkgui.cpp
+++ b/plugins/samplesink/filesink/filesinkgui.cpp
@@ -189,7 +189,7 @@ void FileSinkGui::updateSampleRateAndFrequency()
 {
     m_deviceAPI->getSpectrum()->setSampleRate(m_sampleRate);
     m_deviceAPI->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency);
-    ui->deviceRateText->setText(tr("%1k").arg((float)m_sampleRate / 1000));
+    ui->deviceRateText->setText(tr("%1k").arg((float)(m_sampleRate*(1<<m_settings.m_log2Interp)) / 1000));
 }
 
 void FileSinkGui::displaySettings()
@@ -256,6 +256,17 @@ void FileSinkGui::on_sampleRate_currentIndexChanged(int index)
     sendSettings();
 }
 
+void FileSinkGui::on_interp_currentIndexChanged(int index)
+{
+    if (index < 0) {
+        return;
+    }
+
+    m_settings.m_log2Interp = index;
+    updateSampleRateAndFrequency();
+    sendSettings();
+}
+
 void FileSinkGui::on_startStop_toggled(bool checked)
 {
     if (checked)
diff --git a/plugins/samplesink/filesink/filesinkgui.h b/plugins/samplesink/filesink/filesinkgui.h
index a5c574a8f..ad7ea8ce1 100644
--- a/plugins/samplesink/filesink/filesinkgui.h
+++ b/plugins/samplesink/filesink/filesinkgui.h
@@ -81,6 +81,7 @@ private slots:
     void on_centerFrequency_changed(quint64 value);
 	void on_startStop_toggled(bool checked);
 	void on_showFileDialog_clicked(bool checked);
+	void on_interp_currentIndexChanged(int index);
     void on_sampleRate_currentIndexChanged(int index);
     void updateHardware();
     void updateStatus();
diff --git a/plugins/samplesink/filesink/filesinkgui.ui b/plugins/samplesink/filesink/filesinkgui.ui
index 72c06097d..30d97da9e 100644
--- a/plugins/samplesink/filesink/filesinkgui.ui
+++ b/plugins/samplesink/filesink/filesinkgui.ui
@@ -217,6 +217,55 @@
    </item>
    <item>
     <layout class="QHBoxLayout" name="rateControlLayout">
+     <item>
+      <widget class="QLabel" name="interpLabel">
+       <property name="text">
+        <string>Int</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QComboBox" name="interp">
+       <property name="toolTip">
+        <string>Interpolation</string>
+       </property>
+       <item>
+        <property name="text">
+         <string>1</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>2</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>4</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>8</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>16</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>32</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>64</string>
+        </property>
+       </item>
+      </widget>
+     </item>
      <item>
       <widget class="QLabel" name="sampleRateLabel">
        <property name="text">
diff --git a/plugins/samplesink/filesink/filesinkoutput.cpp b/plugins/samplesink/filesink/filesinkoutput.cpp
index c1366237e..d5dd9e143 100644
--- a/plugins/samplesink/filesink/filesinkoutput.cpp
+++ b/plugins/samplesink/filesink/filesinkoutput.cpp
@@ -60,7 +60,9 @@ void FileSinkOutput::openFileStream()
 
 	m_ofstream.open(m_fileName.toStdString().c_str(), std::ios::binary);
 
-	m_ofstream.write((const char *) &m_settings.m_sampleRate, sizeof(int));
+	int actualSampleRate = m_settings.m_sampleRate * (1<<m_settings.m_log2Interp);
+	m_ofstream.write((const char *) &actualSampleRate, sizeof(int));
+    //m_ofstream.write((const char *) &m_settings.m_sampleRate, sizeof(int));
 	m_ofstream.write((const char *) &m_settings.m_centerFrequency, sizeof(quint64));
     m_startingTimeStamp = time(0);
     m_ofstream.write((const char *) &m_startingTimeStamp, sizeof(std::time_t));
@@ -88,6 +90,7 @@ bool FileSinkOutput::start(int device)
 	}
 
 	m_fileSinkThread->setSamplerate(m_settings.m_sampleRate);
+	m_fileSinkThread->setLog2Interpolation(m_settings.m_log2Interp);
 	m_fileSinkThread->connectTimer(m_masterTimer);
 	m_fileSinkThread->startWork();
 
@@ -217,11 +220,24 @@ void FileSinkOutput::applySettings(const FileSinkSettings& settings, bool force)
         forwardChange = true;
     }
 
+    if (force || (m_settings.m_log2Interp != settings.m_log2Interp))
+    {
+        m_settings.m_log2Interp = settings.m_log2Interp;
+
+        if (m_fileSinkThread != 0)
+        {
+            m_fileSinkThread->setSamplerate(m_settings.m_sampleRate);
+        }
+
+        forwardChange = true;
+    }
+
     if (forwardChange)
     {
-        qDebug("FileSinkOutput::applySettings: forward: m_centerFrequency: %llu m_sampleRate: %d",
+        qDebug("FileSinkOutput::applySettings: forward: m_centerFrequency: %llu m_sampleRate: %d m_log2Interp: %d",
                 m_settings.m_centerFrequency,
-                m_settings.m_sampleRate);
+                m_settings.m_sampleRate,
+                m_settings.m_log2Interp);
         DSPSignalNotification *notif = new DSPSignalNotification(m_settings.m_sampleRate, m_settings.m_centerFrequency);
         m_deviceAPI->getDeviceInputMessageQueue()->push(notif);
     }
diff --git a/plugins/samplesink/filesink/filesinksettings.cpp b/plugins/samplesink/filesink/filesinksettings.cpp
index ad9aef1a3..bea9e7039 100644
--- a/plugins/samplesink/filesink/filesinksettings.cpp
+++ b/plugins/samplesink/filesink/filesinksettings.cpp
@@ -26,6 +26,7 @@ void FileSinkSettings::resetToDefaults()
 {
     m_centerFrequency = 435000*1000;
     m_sampleRate = 48000;
+    m_log2Interp = 0;
 }
 
 QByteArray FileSinkSettings::serialize() const
@@ -33,6 +34,7 @@ QByteArray FileSinkSettings::serialize() const
     SimpleSerializer s(1);
 
     s.writeS32(1, m_sampleRate);
+    s.writeU32(2, m_log2Interp);
 
     return s.final();
 }
@@ -51,6 +53,7 @@ bool FileSinkSettings::deserialize(const QByteArray& data)
     {
         int intval;
         d.readS32(1, &m_sampleRate, 48000);
+        d.readU32(2, &m_log2Interp, 0);
         return true;
     }
     else
diff --git a/plugins/samplesink/filesink/filesinksettings.h b/plugins/samplesink/filesink/filesinksettings.h
index 87c0dba22..694dae79b 100644
--- a/plugins/samplesink/filesink/filesinksettings.h
+++ b/plugins/samplesink/filesink/filesinksettings.h
@@ -22,6 +22,7 @@
 struct FileSinkSettings {
     quint64 m_centerFrequency;
     qint32 m_sampleRate;
+    quint32 m_log2Interp;
 
     FileSinkSettings();
     void resetToDefaults();
diff --git a/plugins/samplesink/filesink/filesinkthread.cpp b/plugins/samplesink/filesink/filesinkthread.cpp
index 910b0113d..2153a89b9 100644
--- a/plugins/samplesink/filesink/filesinkthread.cpp
+++ b/plugins/samplesink/filesink/filesinkthread.cpp
@@ -31,8 +31,10 @@ FileSinkThread::FileSinkThread(std::ofstream *samplesStream, SampleSourceFifo* s
 	m_sampleFifo(sampleFifo),
 	m_samplesCount(0),
     m_samplerate(0),
+    m_log2Interpolation(0),
     m_throttlems(FILESINK_THROTTLE_MS),
-    m_throttleToggle(false)
+    m_throttleToggle(false),
+    m_buf(0)
 {
     assert(m_ofstream != 0);
 }
@@ -42,6 +44,8 @@ FileSinkThread::~FileSinkThread()
 	if (m_running) {
 		stopWork();
 	}
+
+    if (m_buf) delete[] m_buf;
 }
 
 void FileSinkThread::startWork()
@@ -74,14 +78,18 @@ void FileSinkThread::stopWork()
 
 void FileSinkThread::setSamplerate(int samplerate)
 {
-	qDebug() << "FileSinkThread::setSamplerate:"
-			<< " new:" << samplerate
-			<< " old:" << m_samplerate;
-
 	if (samplerate != m_samplerate)
 	{
-		if (m_running) {
+	    qDebug() << "FileSinkThread::setSamplerate:"
+	            << " new:" << samplerate
+	            << " old:" << m_samplerate;
+
+	    bool wasRunning = false;
+
+		if (m_running)
+		{
 			stopWork();
+			wasRunning = true;
 		}
 
 		// resize sample FIFO
@@ -89,11 +97,52 @@ void FileSinkThread::setSamplerate(int samplerate)
 		    m_sampleFifo->resize(samplerate); // 1s buffer
 		}
 
-		m_samplerate = samplerate;
+        // resize output buffer
+        if (m_buf) delete[] m_buf;
+        m_buf = new int16_t[samplerate*(1<<m_log2Interpolation)*2];
+
+        m_samplerate = samplerate;
         m_samplesChunkSize = (m_samplerate * m_throttlems) / 1000;
+
+        if (wasRunning) {
+            startWork();
+        }
 	}
 }
 
+void FileSinkThread::setLog2Interpolation(int log2Interpolation)
+{
+    if ((log2Interpolation < 0) || (log2Interpolation > 6))
+    {
+        return;
+    }
+
+    if (log2Interpolation != m_log2Interpolation)
+    {
+        qDebug() << "FileSinkThread::setLog2Interpolation:"
+                << " new:" << log2Interpolation
+                << " old:" << m_log2Interpolation;
+
+        bool wasRunning = false;
+
+        if (m_running)
+        {
+            stopWork();
+            wasRunning = true;
+        }
+
+        // resize output buffer
+        if (m_buf) delete[] m_buf;
+        m_buf = new int16_t[m_samplerate*(1<<log2Interpolation)*2];
+
+        m_log2Interpolation = log2Interpolation;
+
+        if (wasRunning) {
+            startWork();
+        }
+    }
+}
+
 void FileSinkThread::run()
 {
 	int res;
@@ -138,7 +187,40 @@ void FileSinkThread::tick()
 
         m_sampleFifo->readAdvance(readUntil, m_samplesChunkSize);
         SampleVector::iterator beginRead = readUntil - m_samplesChunkSize;
-        m_ofstream->write(reinterpret_cast<char*>(&(*beginRead)), m_samplesChunkSize*sizeof(Sample));
         m_samplesCount += m_samplesChunkSize;
+
+        if (m_log2Interpolation == 0)
+        {
+            m_ofstream->write(reinterpret_cast<char*>(&(*beginRead)), m_samplesChunkSize*sizeof(Sample));
+        }
+        else
+        {
+            switch (m_log2Interpolation)
+            {
+            case 1:
+                m_interpolators.interpolate2_cen(&beginRead, m_buf, m_samplesChunkSize*(1<<m_log2Interpolation)*2);
+                break;
+            case 2:
+                m_interpolators.interpolate4_cen(&beginRead, m_buf, m_samplesChunkSize*(1<<m_log2Interpolation)*2);
+                break;
+            case 3:
+                m_interpolators.interpolate8_cen(&beginRead, m_buf, m_samplesChunkSize*(1<<m_log2Interpolation)*2);
+                break;
+            case 4:
+                m_interpolators.interpolate16_cen(&beginRead, m_buf, m_samplesChunkSize*(1<<m_log2Interpolation)*2);
+                break;
+            case 5:
+                m_interpolators.interpolate32_cen(&beginRead, m_buf, m_samplesChunkSize*(1<<m_log2Interpolation)*2);
+                break;
+            case 6:
+                m_interpolators.interpolate64_cen(&beginRead, m_buf, m_samplesChunkSize*(1<<m_log2Interpolation)*2);
+                break;
+            default:
+                break;
+            }
+
+            m_ofstream->write(reinterpret_cast<char*>(m_buf), m_samplesChunkSize*(1<<m_log2Interpolation)*2*sizeof(int16_t));
+        }
+
 	}
 }
diff --git a/plugins/samplesink/filesink/filesinkthread.h b/plugins/samplesink/filesink/filesinkthread.h
index b401fe6fe..e408d0b39 100644
--- a/plugins/samplesink/filesink/filesinkthread.h
+++ b/plugins/samplesink/filesink/filesinkthread.h
@@ -25,8 +25,10 @@
 #include <iostream>
 #include <fstream>
 #include <cstdlib>
+#include <stdint.h>
 
 #include "dsp/inthalfbandfilter.h"
+#include "dsp/interpolators.h"
 
 #define FILESINK_THROTTLE_MS 50
 
@@ -42,6 +44,7 @@ public:
 	void startWork();
 	void stopWork();
 	void setSamplerate(int samplerate);
+	void setLog2Interpolation(int log2Interpolation);
     void setBuffer(std::size_t chunksize);
 	bool isRunning() const { return m_running; }
     std::size_t getSamplesCount() const { return m_samplesCount; }
@@ -61,11 +64,15 @@ private:
     std::size_t m_samplesCount;
 
 	int m_samplerate;
+	int m_log2Interpolation;
     int m_throttlems;
     int m_maxThrottlems;
     QElapsedTimer m_elapsedTimer;
     bool m_throttleToggle;
 
+    Interpolators<qint16, SDR_SAMP_SZ, 16> m_interpolators;
+    int16_t *m_buf;
+
 	void run();
 
 private slots:
diff --git a/plugins/samplesource/bladerfinput/bladerfinput.cpp b/plugins/samplesource/bladerfinput/bladerfinput.cpp
index 5d050749e..ac238b8aa 100644
--- a/plugins/samplesource/bladerfinput/bladerfinput.cpp
+++ b/plugins/samplesource/bladerfinput/bladerfinput.cpp
@@ -14,7 +14,7 @@
 // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 ///////////////////////////////////////////////////////////////////////////////////
 
-#include "../bladerfinput/bladerfinput.h"
+#include "bladerfinput.h"
 
 #include <string.h>
 #include <errno.h>
@@ -37,7 +37,7 @@ BladerfInput::BladerfInput(DeviceSourceAPI *deviceAPI) :
 	m_settings(),
 	m_dev(0),
 	m_bladerfThread(0),
-	m_deviceDescription("BladeRF")
+	m_deviceDescription("BladeRFInput")
 {
     m_deviceAPI->setBuddySharedPtr(&m_sharedParams);
 }
@@ -63,11 +63,10 @@ bool BladerfInput::start(int device)
 	}
 
 	int res;
-	int fpga_loaded;
 
 	if (!m_sampleFifo.setSize(96000 * 4))
 	{
-		qCritical("Could not allocate SampleFifo");
+		qCritical("BladerfInput::start: could not allocate SampleFifo");
 		return false;
 	}
 
@@ -135,18 +134,18 @@ bool BladerfInput::start(int device)
     // TODO: adjust USB transfer data according to sample rate
     if ((res = bladerf_sync_config(m_dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11, 64, 8192, 32, 10000)) < 0)
     {
-    	qCritical("bladerf_sync_config with return code %d", res);
+    	qCritical("BladerfInput::start: bladerf_sync_config with return code %d", res);
     	goto failed;
     }
 
     if ((res = bladerf_enable_module(m_dev, BLADERF_MODULE_RX, true)) < 0)
     {
-    	qCritical("bladerf_enable_module with return code %d", res);
+    	qCritical("BladerfInput::start: bladerf_enable_module with return code %d", res);
     	goto failed;
     }
 
 	if((m_bladerfThread = new BladerfInputThread(m_dev, &m_sampleFifo)) == NULL) {
-		qFatal("out of memory");
+		qFatal("BladerfInput::start: out of memory");
 		goto failed;
 	}
 
@@ -277,11 +276,11 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 		{
 			if(bladerf_set_lna_gain(m_dev, getLnaGain(m_settings.m_lnaGain)) != 0)
 			{
-				qDebug("bladerf_set_lna_gain() failed");
+				qDebug("BladerfInput::applySettings: bladerf_set_lna_gain() failed");
 			}
 			else
 			{
-				qDebug() << "BladerfInput: LNA gain set to " << getLnaGain(m_settings.m_lnaGain);
+				qDebug() << "BladerfInput::applySettings: LNA gain set to " << getLnaGain(m_settings.m_lnaGain);
 			}
 		}
 	}
@@ -294,11 +293,11 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 		{
 			if(bladerf_set_rxvga1(m_dev, m_settings.m_vga1) != 0)
 			{
-				qDebug("bladerf_set_rxvga1() failed");
+				qDebug("BladerfInput::applySettings: bladerf_set_rxvga1() failed");
 			}
 			else
 			{
-				qDebug() << "BladerfInput: VGA1 gain set to " << m_settings.m_vga1;
+				qDebug() << "BladerfInput::applySettings: VGA1 gain set to " << m_settings.m_vga1;
 			}
 		}
 	}
@@ -311,11 +310,11 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 		{
 			if(bladerf_set_rxvga2(m_dev, m_settings.m_vga2) != 0)
 			{
-				qDebug("bladerf_set_rxvga2() failed");
+				qDebug("BladerfInput::applySettings: bladerf_set_rxvga2() failed");
 			}
 			else
 			{
-				qDebug() << "BladerfInput: VGA2 gain set to " << m_settings.m_vga2;
+				qDebug() << "BladerfInput::applySettings: VGA2 gain set to " << m_settings.m_vga2;
 			}
 		}
 	}
@@ -353,22 +352,22 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 	            {
 	                if (bladerf_expansion_attach(m_dev, BLADERF_XB_200) != 0)
 	                {
-	                    qDebug("bladerf_expansion_attach(xb200) failed");
+	                    qDebug("BladerfInput::applySettings: bladerf_expansion_attach(xb200) failed");
 	                }
 	                else
 	                {
-	                    qDebug() << "BladerfInput: Attach XB200";
+	                    qDebug() << "BladerfInput::applySettings: Attach XB200";
 	                }
 	            }
 	            else
 	            {
 	                if (bladerf_expansion_attach(m_dev, BLADERF_XB_NONE) != 0)
 	                {
-	                    qDebug("bladerf_expansion_attach(none) failed");
+	                    qDebug("BladerfInput::applySettings: bladerf_expansion_attach(none) failed");
 	                }
 	                else
 	                {
-	                    qDebug() << "BladerfInput: Detach XB200";
+	                    qDebug() << "BladerfInput::applySettings: Detach XB200";
 	                }
 	            }
 
@@ -385,11 +384,11 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 		{
 			if(bladerf_xb200_set_path(m_dev, BLADERF_MODULE_RX, m_settings.m_xb200Path) != 0)
 			{
-				qDebug("bladerf_xb200_set_path(BLADERF_MODULE_RX) failed");
+				qDebug("BladerfInput::applySettings: bladerf_xb200_set_path(BLADERF_MODULE_RX) failed");
 			}
 			else
 			{
-				qDebug() << "BladerfInput: set xb200 path to " << m_settings.m_xb200Path;
+				qDebug() << "BladerfInput::applySettings: set xb200 path to " << m_settings.m_xb200Path;
 			}
 		}
 	}
@@ -402,11 +401,11 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 		{
 			if(bladerf_xb200_set_filterbank(m_dev, BLADERF_MODULE_RX, m_settings.m_xb200Filter) != 0)
 			{
-				qDebug("bladerf_xb200_set_filterbank(BLADERF_MODULE_RX) failed");
+				qDebug("BladerfInput::applySettings: bladerf_xb200_set_filterbank(BLADERF_MODULE_RX) failed");
 			}
 			else
 			{
-				qDebug() << "BladerfInput: set xb200 filter to " << m_settings.m_xb200Filter;
+				qDebug() << "BladerfInput::applySettings: set xb200 filter to " << m_settings.m_xb200Filter;
 			}
 		}
 	}
@@ -422,11 +421,11 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 
 			if (bladerf_set_sample_rate(m_dev, BLADERF_MODULE_RX, m_settings.m_devSampleRate, &actualSamplerate) < 0)
 			{
-				qCritical("could not set sample rate: %d", m_settings.m_devSampleRate);
+				qCritical("BladerfInput::applySettings: could not set sample rate: %d", m_settings.m_devSampleRate);
 			}
 			else
 			{
-				qDebug() << "bladerf_set_sample_rate(BLADERF_MODULE_RX) actual sample rate is " << actualSamplerate;
+				qDebug() << "BladerfInput::applySettings: bladerf_set_sample_rate(BLADERF_MODULE_RX) actual sample rate is " << actualSamplerate;
 			}
 		}
 	}
@@ -441,11 +440,11 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 
 			if( bladerf_set_bandwidth(m_dev, BLADERF_MODULE_RX, m_settings.m_bandwidth, &actualBandwidth) < 0)
 			{
-				qCritical("could not set bandwidth: %d", m_settings.m_bandwidth);
+				qCritical("BladerfInput::applySettings: could not set bandwidth: %d", m_settings.m_bandwidth);
 			}
 			else
 			{
-				qDebug() << "bladerf_set_bandwidth(BLADERF_MODULE_RX) actual bandwidth is " << actualBandwidth;
+				qDebug() << "BladerfInput::applySettings: bladerf_set_bandwidth(BLADERF_MODULE_RX) actual bandwidth is " << actualBandwidth;
 			}
 		}
 	}
@@ -458,7 +457,7 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 		if(m_dev != 0)
 		{
 			m_bladerfThread->setLog2Decimation(m_settings.m_log2Decim);
-			qDebug() << "BladerfInput: set decimation to " << (1<<m_settings.m_log2Decim);
+			qDebug() << "BladerfInput::applySettings: set decimation to " << (1<<m_settings.m_log2Decim);
 		}
 	}
 
@@ -469,7 +468,7 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 		if(m_dev != 0)
 		{
 			m_bladerfThread->setFcPos((int) m_settings.m_fcPos);
-			qDebug() << "BladerfInput: set fc pos (enum) to " << (int) m_settings.m_fcPos;
+			qDebug() << "BladerfInput::applySettings: set fc pos (enum) to " << (int) m_settings.m_fcPos;
 		}
 	}
 
@@ -510,7 +509,7 @@ bool BladerfInput::applySettings(const BladeRFInputSettings& settings, bool forc
 	{
 		if (bladerf_set_frequency( m_dev, BLADERF_MODULE_RX, deviceCenterFrequency ) != 0)
 		{
-			qDebug("bladerf_set_frequency(%lld) failed", m_settings.m_centerFrequency);
+			qDebug("BladerfInput::applySettings: bladerf_set_frequency(%lld) failed", m_settings.m_centerFrequency);
 		}
 	}
 
diff --git a/plugins/samplesource/bladerfinput/bladerfinput.h b/plugins/samplesource/bladerfinput/bladerfinput.h
index fd484491f..446977c36 100644
--- a/plugins/samplesource/bladerfinput/bladerfinput.h
+++ b/plugins/samplesource/bladerfinput/bladerfinput.h
@@ -24,7 +24,7 @@
 #include <libbladeRF.h>
 #include <QString>
 
-#include "../bladerfinput/bladerfinputsettings.h"
+#include "bladerfinputsettings.h"
 
 class DeviceSourceAPI;
 class BladerfInputThread;
diff --git a/sdrbase/dsp/interpolators.h b/sdrbase/dsp/interpolators.h
new file mode 100644
index 000000000..a4faae1a3
--- /dev/null
+++ b/sdrbase/dsp/interpolators.h
@@ -0,0 +1,617 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2016-2017 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                  //
+//                                                                               //
+// 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 <http://www.gnu.org/licenses/>.          //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDE_GPL_DSP_INTERPOLATORS_H_
+#define INCLUDE_GPL_DSP_INTERPOLATORS_H_
+
+#include "dsp/dsptypes.h"
+#ifdef USE_SSE4_1
+#include "dsp/inthalfbandfiltereo1.h"
+#else
+#include "dsp/inthalfbandfilterdb.h"
+#endif
+
+#define INTERPOLATORS_HB_FILTER_ORDER 64
+
+template<uint SdrBits, uint OutputBits>
+struct interpolation_shifts
+{
+    static const uint post1  = 0;
+    static const uint pre2   = 0;
+    static const uint post2  = 0;
+    static const uint pre4   = 0;
+    static const uint post4  = 0;
+    static const uint pre8   = 0;
+    static const uint post8  = 0;
+    static const uint pre16  = 0;
+    static const uint post16 = 0;
+    static const uint pre32  = 0;
+    static const uint post32 = 0;
+    static const uint pre64  = 0;
+    static const uint post64 = 0;
+};
+
+template<>
+struct interpolation_shifts<16, 16>
+{
+    static const uint post1  = 0;
+    static const uint pre2   = 1;
+    static const uint post2  = 1;
+    static const uint pre4   = 2;
+    static const uint post4  = 2;
+    static const uint pre8   = 3;
+    static const uint post8  = 3;
+    static const uint pre16  = 3;
+    static const uint post16 = 3;
+    static const uint pre32  = 3;
+    static const uint post32 = 3;
+    static const uint pre64  = 3;
+    static const uint post64 = 3;
+};
+
+template<>
+struct interpolation_shifts<16, 12>
+{
+    static const uint post1  = 4;
+    static const uint pre2   = 1;
+    static const uint post2  = 5;
+    static const uint pre4   = 2;
+    static const uint post4  = 6;
+    static const uint pre8   = 3;
+    static const uint post8  = 7;
+    static const uint pre16  = 3;
+    static const uint post16 = 7;
+    static const uint pre32  = 3;
+    static const uint post32 = 7;
+    static const uint pre64  = 3;
+    static const uint post64 = 7;
+};
+
+template<>
+struct interpolation_shifts<16, 8>
+{
+    static const uint post1  = 8;
+    static const uint pre2   = 1;
+    static const uint post2  = 9;
+    static const uint pre4   = 2;
+    static const uint post4  = 10;
+    static const uint pre8   = 3;
+    static const uint post8  = 11;
+    static const uint pre16  = 3;
+    static const uint post16 = 11;
+    static const uint pre32  = 3;
+    static const uint post32 = 11;
+    static const uint pre64  = 3;
+    static const uint post64 = 11;
+};
+
+template<typename T, uint SdrBits, uint OutputBits>
+class Interpolators
+{
+public:
+    // interleaved I/Q input buffer
+	void interpolate1(SampleVector::iterator* it, T* buf, qint32 len);
+	void interpolate2_cen(SampleVector::iterator* it, T* buf, qint32 len);
+	void interpolate4_cen(SampleVector::iterator* it, T* buf, qint32 len);
+	void interpolate8_cen(SampleVector::iterator* it, T* buf, qint32 len);
+	void interpolate16_cen(SampleVector::iterator* it, T* buf, qint32 len);
+	void interpolate32_cen(SampleVector::iterator* it, T* buf, qint32 len);
+	void interpolate64_cen(SampleVector::iterator* it, T* buf, qint32 len);
+
+private:
+#ifdef USE_SSE4_1
+    IntHalfbandFilterEO1<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator2;  // 1st stages
+    IntHalfbandFilterEO1<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator4;  // 2nd stages
+    IntHalfbandFilterEO1<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator8;  // 3rd stages
+    IntHalfbandFilterEO1<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator16; // 4th stages
+    IntHalfbandFilterEO1<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator32; // 5th stages
+    IntHalfbandFilterEO1<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator64; // 6th stages
+#else
+	IntHalfbandFilterDB<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator2;  // 1st stages
+	IntHalfbandFilterDB<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator4;  // 2nd stages
+	IntHalfbandFilterDB<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator8;  // 3rd stages
+	IntHalfbandFilterDB<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator16; // 4th stages
+	IntHalfbandFilterDB<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator32; // 5th stages
+	IntHalfbandFilterDB<INTERPOLATORS_HB_FILTER_ORDER> m_interpolator64; // 6th stages
+#endif
+};
+
+template<typename T, uint SdrBits, uint OutputBits>
+void Interpolators<T, SdrBits, OutputBits>::interpolate1(SampleVector::iterator* it, T* buf, qint32 len)
+{
+	qint32 xreal, yimag;
+
+	for (int pos = 0; pos < len - 1; pos += 2)
+	{
+	    buf[pos+0] = (**it).m_real >> interpolation_shifts<SdrBits, OutputBits>::post1;
+	    buf[pos+1] = (**it).m_imag >> interpolation_shifts<SdrBits, OutputBits>::post1;
+		++(*it);
+	}
+}
+
+template<typename T, uint SdrBits, uint OutputBits>
+void Interpolators<T, SdrBits, OutputBits>::interpolate2_cen(SampleVector::iterator* it, T* buf, qint32 len)
+{
+	qint32 intbuf[4];
+
+    for (int pos = 0; pos < len - 3; pos += 4)
+    {
+        intbuf[0] = (**it).m_real << interpolation_shifts<SdrBits, OutputBits>::pre2;
+        intbuf[1] = (**it).m_imag << interpolation_shifts<SdrBits, OutputBits>::pre2;
+//        intbuf[2] = 0;
+//        intbuf[3] = 0;
+
+        m_interpolator2.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[2], &intbuf[3]);
+
+        buf[pos+0] = intbuf[0] >> interpolation_shifts<SdrBits, OutputBits>::post2;
+        buf[pos+1] = intbuf[1] >> interpolation_shifts<SdrBits, OutputBits>::post2;
+        buf[pos+2] = intbuf[2] >> interpolation_shifts<SdrBits, OutputBits>::post2;
+        buf[pos+3] = intbuf[3] >> interpolation_shifts<SdrBits, OutputBits>::post2;
+
+        ++(*it);
+    }
+}
+
+template<typename T, uint SdrBits, uint OutputBits>
+void Interpolators<T, SdrBits, OutputBits>::interpolate4_cen(SampleVector::iterator* it, T* buf, qint32 len)
+{
+	qint32 intbuf[8];
+
+	for (int pos = 0; pos < len - 7; pos += 8)
+	{
+        memset(intbuf, 0, 8*sizeof(qint32));
+		intbuf[0]  = (**it).m_real << interpolation_shifts<SdrBits, OutputBits>::pre4;
+		intbuf[1]  = (**it).m_imag << interpolation_shifts<SdrBits, OutputBits>::pre4;
+
+        m_interpolator2.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[4], &intbuf[5]);
+
+        m_interpolator4.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[2], &intbuf[3]);
+        m_interpolator4.myInterpolate(&intbuf[4], &intbuf[5], &intbuf[6], &intbuf[7]);
+
+        buf[pos+0] = intbuf[0] >> interpolation_shifts<SdrBits, OutputBits>::post4;
+        buf[pos+1] = intbuf[1] >> interpolation_shifts<SdrBits, OutputBits>::post4;
+        buf[pos+2] = intbuf[2] >> interpolation_shifts<SdrBits, OutputBits>::post4;
+        buf[pos+3] = intbuf[3] >> interpolation_shifts<SdrBits, OutputBits>::post4;
+        buf[pos+4] = intbuf[4] >> interpolation_shifts<SdrBits, OutputBits>::post4;
+        buf[pos+5] = intbuf[5] >> interpolation_shifts<SdrBits, OutputBits>::post4;
+        buf[pos+6] = intbuf[6] >> interpolation_shifts<SdrBits, OutputBits>::post4;
+        buf[pos+7] = intbuf[7] >> interpolation_shifts<SdrBits, OutputBits>::post4;
+
+		++(*it);
+	}
+}
+
+template<typename T, uint SdrBits, uint OutputBits>
+void Interpolators<T, SdrBits, OutputBits>::interpolate8_cen(SampleVector::iterator* it, T* buf, qint32 len)
+{
+	qint32 intbuf[16];
+
+	for (int pos = 0; pos < len - 15; pos += 16)
+	{
+        memset(intbuf, 0, 16*sizeof(qint32));
+        intbuf[0]  = (**it).m_real << interpolation_shifts<SdrBits, OutputBits>::pre8;
+        intbuf[1]  = (**it).m_imag << interpolation_shifts<SdrBits, OutputBits>::pre8;
+
+        m_interpolator2.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[8], &intbuf[9]);
+
+        m_interpolator4.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[4], &intbuf[5]);
+        m_interpolator4.myInterpolate(&intbuf[8], &intbuf[9], &intbuf[12], &intbuf[13]);
+
+        m_interpolator8.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[2], &intbuf[3]);
+        m_interpolator8.myInterpolate(&intbuf[4], &intbuf[5], &intbuf[6], &intbuf[7]);
+        m_interpolator8.myInterpolate(&intbuf[8], &intbuf[9], &intbuf[10], &intbuf[11]);
+        m_interpolator8.myInterpolate(&intbuf[12], &intbuf[13], &intbuf[14], &intbuf[15]);
+
+        buf[pos+0]  = intbuf[0]  >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+1]  = intbuf[1]  >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+2]  = intbuf[2]  >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+3]  = intbuf[3]  >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+4]  = intbuf[4]  >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+5]  = intbuf[5]  >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+6]  = intbuf[6]  >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+7]  = intbuf[7]  >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+8]  = intbuf[8]  >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+9]  = intbuf[9]  >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+10] = intbuf[10] >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+11] = intbuf[11] >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+12] = intbuf[12] >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+13] = intbuf[13] >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+14] = intbuf[14] >> interpolation_shifts<SdrBits, OutputBits>::post8;
+        buf[pos+15] = intbuf[15] >> interpolation_shifts<SdrBits, OutputBits>::post8;
+
+        ++(*it);
+	}
+}
+
+template<typename T, uint SdrBits, uint OutputBits>
+void Interpolators<T, SdrBits, OutputBits>::interpolate16_cen(SampleVector::iterator* it, T* buf, qint32 len)
+{
+	qint32 intbuf[32];
+
+	for (int pos = 0; pos < len - 31; pos += 32)
+	{
+        memset(intbuf, 0, 32*sizeof(qint32));
+        intbuf[0]  = (**it).m_real << interpolation_shifts<SdrBits, OutputBits>::pre16;
+        intbuf[1]  = (**it).m_imag << interpolation_shifts<SdrBits, OutputBits>::pre16;
+
+        m_interpolator2.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[16], &intbuf[17]);
+
+        m_interpolator4.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[8], &intbuf[9]);
+        m_interpolator4.myInterpolate(&intbuf[16], &intbuf[17], &intbuf[24], &intbuf[25]);
+
+        m_interpolator8.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[4], &intbuf[5]);
+        m_interpolator8.myInterpolate(&intbuf[8], &intbuf[9], &intbuf[12], &intbuf[13]);
+        m_interpolator8.myInterpolate(&intbuf[16], &intbuf[17], &intbuf[20], &intbuf[21]);
+        m_interpolator8.myInterpolate(&intbuf[24], &intbuf[25], &intbuf[28], &intbuf[29]);
+
+        m_interpolator16.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[2], &intbuf[3]);
+        m_interpolator16.myInterpolate(&intbuf[4], &intbuf[5], &intbuf[6], &intbuf[7]);
+        m_interpolator16.myInterpolate(&intbuf[8], &intbuf[9], &intbuf[10], &intbuf[11]);
+        m_interpolator16.myInterpolate(&intbuf[12], &intbuf[13], &intbuf[14], &intbuf[15]);
+        m_interpolator16.myInterpolate(&intbuf[16], &intbuf[17], &intbuf[18], &intbuf[19]);
+        m_interpolator16.myInterpolate(&intbuf[20], &intbuf[21], &intbuf[22], &intbuf[23]);
+        m_interpolator16.myInterpolate(&intbuf[24], &intbuf[25], &intbuf[26], &intbuf[27]);
+        m_interpolator16.myInterpolate(&intbuf[28], &intbuf[29], &intbuf[30], &intbuf[31]);
+
+        buf[pos+0]  = intbuf[0]  >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+1]  = intbuf[1]  >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+2]  = intbuf[2]  >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+3]  = intbuf[3]  >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+4]  = intbuf[4]  >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+5]  = intbuf[5]  >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+6]  = intbuf[6]  >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+7]  = intbuf[7]  >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+8]  = intbuf[8]  >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+9]  = intbuf[9]  >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+10] = intbuf[10] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+11] = intbuf[11] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+12] = intbuf[12] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+13] = intbuf[13] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+14] = intbuf[14] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+15] = intbuf[15] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+16] = intbuf[16] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+17] = intbuf[17] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+18] = intbuf[18] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+19] = intbuf[19] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+20] = intbuf[20] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+21] = intbuf[21] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+22] = intbuf[22] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+23] = intbuf[23] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+24] = intbuf[24] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+25] = intbuf[25] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+26] = intbuf[26] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+27] = intbuf[27] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+28] = intbuf[28] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+29] = intbuf[29] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+30] = intbuf[30] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+        buf[pos+31] = intbuf[31] >> interpolation_shifts<SdrBits, OutputBits>::post16;
+
+		++(*it);
+	}
+}
+
+template<typename T, uint SdrBits, uint OutputBits>
+void Interpolators<T, SdrBits, OutputBits>::interpolate32_cen(SampleVector::iterator* it, T* buf, qint32 len)
+{
+	qint32 intbuf[64];
+
+	for (int pos = 0; pos < len - 63; pos += 64)
+	{
+	    memset(intbuf, 0, 64*sizeof(qint32));
+        intbuf[0]  = (**it).m_real << interpolation_shifts<SdrBits, OutputBits>::pre32;
+        intbuf[1]  = (**it).m_imag << interpolation_shifts<SdrBits, OutputBits>::pre32;
+        m_interpolator2.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[32], &intbuf[33]);
+
+
+        m_interpolator4.myInterpolate(&intbuf[0],  &intbuf[1],  &intbuf[16], &intbuf[17]);
+        m_interpolator4.myInterpolate(&intbuf[32], &intbuf[33], &intbuf[48], &intbuf[49]);
+
+
+        m_interpolator8.myInterpolate(&intbuf[0],  &intbuf[1],  &intbuf[8],  &intbuf[9]);
+        m_interpolator8.myInterpolate(&intbuf[16], &intbuf[17], &intbuf[24], &intbuf[25]);
+        m_interpolator8.myInterpolate(&intbuf[32], &intbuf[33], &intbuf[40], &intbuf[41]);
+        m_interpolator8.myInterpolate(&intbuf[48], &intbuf[49], &intbuf[56], &intbuf[57]);
+
+        m_interpolator16.myInterpolate(&intbuf[0],  &intbuf[1],  &intbuf[4],  &intbuf[5]);
+        m_interpolator16.myInterpolate(&intbuf[8],  &intbuf[9],  &intbuf[12], &intbuf[13]);
+        m_interpolator16.myInterpolate(&intbuf[16], &intbuf[17], &intbuf[20], &intbuf[21]);
+        m_interpolator16.myInterpolate(&intbuf[24], &intbuf[25], &intbuf[28], &intbuf[29]);
+        m_interpolator16.myInterpolate(&intbuf[32], &intbuf[33], &intbuf[36], &intbuf[37]);
+        m_interpolator16.myInterpolate(&intbuf[40], &intbuf[41], &intbuf[44], &intbuf[45]);
+        m_interpolator16.myInterpolate(&intbuf[48], &intbuf[49], &intbuf[52], &intbuf[53]);
+        m_interpolator16.myInterpolate(&intbuf[56], &intbuf[57], &intbuf[60], &intbuf[61]);
+
+        m_interpolator32.myInterpolate(&intbuf[0],  &intbuf[1],  &intbuf[2],  &intbuf[3]);
+        m_interpolator32.myInterpolate(&intbuf[4],  &intbuf[5],  &intbuf[6],  &intbuf[7]);
+        m_interpolator32.myInterpolate(&intbuf[8],  &intbuf[9],  &intbuf[10], &intbuf[11]);
+        m_interpolator32.myInterpolate(&intbuf[12], &intbuf[13], &intbuf[14], &intbuf[15]);
+        m_interpolator32.myInterpolate(&intbuf[16], &intbuf[17], &intbuf[18], &intbuf[19]);
+        m_interpolator32.myInterpolate(&intbuf[20], &intbuf[21], &intbuf[22], &intbuf[23]);
+        m_interpolator32.myInterpolate(&intbuf[24], &intbuf[25], &intbuf[26], &intbuf[27]);
+        m_interpolator32.myInterpolate(&intbuf[28], &intbuf[29], &intbuf[30], &intbuf[31]);
+        m_interpolator32.myInterpolate(&intbuf[32], &intbuf[33], &intbuf[34], &intbuf[35]);
+        m_interpolator32.myInterpolate(&intbuf[36], &intbuf[37], &intbuf[38], &intbuf[39]);
+        m_interpolator32.myInterpolate(&intbuf[40], &intbuf[41], &intbuf[42], &intbuf[43]);
+        m_interpolator32.myInterpolate(&intbuf[44], &intbuf[45], &intbuf[46], &intbuf[47]);
+        m_interpolator32.myInterpolate(&intbuf[48], &intbuf[49], &intbuf[50], &intbuf[51]);
+        m_interpolator32.myInterpolate(&intbuf[52], &intbuf[53], &intbuf[54], &intbuf[55]);
+        m_interpolator32.myInterpolate(&intbuf[56], &intbuf[57], &intbuf[58], &intbuf[59]);
+        m_interpolator32.myInterpolate(&intbuf[60], &intbuf[61], &intbuf[62], &intbuf[63]);
+
+        buf[pos+0]  = intbuf[0]  >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+1]  = intbuf[1]  >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+2]  = intbuf[2]  >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+3]  = intbuf[3]  >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+4]  = intbuf[4]  >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+5]  = intbuf[5]  >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+6]  = intbuf[6]  >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+7]  = intbuf[7]  >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+8]  = intbuf[8]  >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+9]  = intbuf[9]  >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+10] = intbuf[10] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+11] = intbuf[11] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+12] = intbuf[12] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+13] = intbuf[13] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+14] = intbuf[14] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+15] = intbuf[15] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+16] = intbuf[16] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+17] = intbuf[17] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+18] = intbuf[18] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+19] = intbuf[19] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+20] = intbuf[20] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+21] = intbuf[21] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+22] = intbuf[22] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+23] = intbuf[23] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+24] = intbuf[24] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+25] = intbuf[25] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+26] = intbuf[26] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+27] = intbuf[27] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+28] = intbuf[28] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+29] = intbuf[29] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+30] = intbuf[30] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+31] = intbuf[31] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+32] = intbuf[32] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+33] = intbuf[33] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+34] = intbuf[34] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+35] = intbuf[35] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+36] = intbuf[36] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+37] = intbuf[37] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+38] = intbuf[38] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+39] = intbuf[39] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+40] = intbuf[40] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+41] = intbuf[41] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+42] = intbuf[42] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+43] = intbuf[43] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+44] = intbuf[44] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+45] = intbuf[45] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+46] = intbuf[46] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+47] = intbuf[47] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+48] = intbuf[48] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+49] = intbuf[49] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+50] = intbuf[50] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+51] = intbuf[51] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+52] = intbuf[52] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+53] = intbuf[53] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+54] = intbuf[54] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+55] = intbuf[55] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+56] = intbuf[56] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+57] = intbuf[57] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+58] = intbuf[58] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+59] = intbuf[59] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+60] = intbuf[60] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+61] = intbuf[61] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+62] = intbuf[62] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+        buf[pos+63] = intbuf[63] >> interpolation_shifts<SdrBits, OutputBits>::post32;
+
+        ++(*it);
+	}
+}
+
+template<typename T, uint SdrBits, uint OutputBits>
+void Interpolators<T, SdrBits, OutputBits>::interpolate64_cen(SampleVector::iterator* it, T* buf, qint32 len)
+{
+	qint32 intbuf[128];
+
+	for (int pos = 0; pos < len - 127; pos += 128)
+	{
+        memset(intbuf, 0, 128*sizeof(qint32));
+        intbuf[0]  = (**it).m_real << interpolation_shifts<SdrBits, OutputBits>::pre64;
+        intbuf[1]  = (**it).m_imag << interpolation_shifts<SdrBits, OutputBits>::pre64;
+        m_interpolator2.myInterpolate(&intbuf[0], &intbuf[1], &intbuf[64], &intbuf[65]);
+
+        m_interpolator4.myInterpolate(&intbuf[0],  &intbuf[1],  &intbuf[32], &intbuf[33]);
+        m_interpolator4.myInterpolate(&intbuf[64], &intbuf[65], &intbuf[96], &intbuf[97]);
+
+        m_interpolator8.myInterpolate(&intbuf[0],   &intbuf[1],   &intbuf[16],  &intbuf[17]);
+        m_interpolator8.myInterpolate(&intbuf[32],  &intbuf[33],  &intbuf[48],  &intbuf[49]);
+        m_interpolator8.myInterpolate(&intbuf[64],  &intbuf[65],  &intbuf[80],  &intbuf[81]);
+        m_interpolator8.myInterpolate(&intbuf[96],  &intbuf[97],  &intbuf[112], &intbuf[113]);
+
+        m_interpolator16.myInterpolate(&intbuf[0],   &intbuf[1],    &intbuf[8],   &intbuf[9]);
+        m_interpolator16.myInterpolate(&intbuf[16],  &intbuf[17],   &intbuf[24],  &intbuf[25]);
+        m_interpolator16.myInterpolate(&intbuf[32],  &intbuf[33],   &intbuf[40],  &intbuf[41]);
+        m_interpolator16.myInterpolate(&intbuf[48],  &intbuf[49],   &intbuf[56],  &intbuf[57]);
+        m_interpolator16.myInterpolate(&intbuf[64],  &intbuf[65],   &intbuf[72],  &intbuf[73]);
+        m_interpolator16.myInterpolate(&intbuf[80],  &intbuf[81],   &intbuf[88],  &intbuf[89]);
+        m_interpolator16.myInterpolate(&intbuf[96],  &intbuf[97],   &intbuf[104], &intbuf[105]);
+        m_interpolator16.myInterpolate(&intbuf[112], &intbuf[113],  &intbuf[120], &intbuf[121]);
+
+        m_interpolator32.myInterpolate(&intbuf[0],   &intbuf[1],    &intbuf[4],   &intbuf[5]);
+        m_interpolator32.myInterpolate(&intbuf[8],   &intbuf[9],    &intbuf[12],  &intbuf[13]);
+        m_interpolator32.myInterpolate(&intbuf[16],  &intbuf[17],   &intbuf[20],  &intbuf[21]);
+        m_interpolator32.myInterpolate(&intbuf[24],  &intbuf[25],   &intbuf[28],  &intbuf[29]);
+        m_interpolator32.myInterpolate(&intbuf[32],  &intbuf[33],   &intbuf[36],  &intbuf[37]);
+        m_interpolator32.myInterpolate(&intbuf[40],  &intbuf[41],   &intbuf[44],  &intbuf[45]);
+        m_interpolator32.myInterpolate(&intbuf[48],  &intbuf[49],   &intbuf[52],  &intbuf[53]);
+        m_interpolator32.myInterpolate(&intbuf[56],  &intbuf[57],   &intbuf[60],  &intbuf[61]);
+        m_interpolator32.myInterpolate(&intbuf[64],  &intbuf[65],   &intbuf[68],  &intbuf[69]);
+        m_interpolator32.myInterpolate(&intbuf[72],  &intbuf[73],   &intbuf[76],  &intbuf[77]);
+        m_interpolator32.myInterpolate(&intbuf[80],  &intbuf[81],   &intbuf[84],  &intbuf[85]);
+        m_interpolator32.myInterpolate(&intbuf[88],  &intbuf[89],   &intbuf[92],  &intbuf[93]);
+        m_interpolator32.myInterpolate(&intbuf[96],  &intbuf[97],   &intbuf[100], &intbuf[101]);
+        m_interpolator32.myInterpolate(&intbuf[104], &intbuf[105],  &intbuf[108], &intbuf[109]);
+        m_interpolator32.myInterpolate(&intbuf[112], &intbuf[113],  &intbuf[116], &intbuf[117]);
+        m_interpolator32.myInterpolate(&intbuf[120], &intbuf[121],  &intbuf[124], &intbuf[125]);
+
+        m_interpolator64.myInterpolate(&intbuf[0],   &intbuf[1],    &intbuf[2],   &intbuf[3]);
+        m_interpolator64.myInterpolate(&intbuf[4],   &intbuf[5],    &intbuf[6],   &intbuf[7]);
+        m_interpolator64.myInterpolate(&intbuf[8],   &intbuf[9],    &intbuf[10],  &intbuf[11]);
+        m_interpolator64.myInterpolate(&intbuf[12],  &intbuf[13],   &intbuf[14],  &intbuf[15]);
+        m_interpolator64.myInterpolate(&intbuf[16],  &intbuf[17],   &intbuf[18],  &intbuf[19]);
+        m_interpolator64.myInterpolate(&intbuf[20],  &intbuf[21],   &intbuf[22],  &intbuf[23]);
+        m_interpolator64.myInterpolate(&intbuf[24],  &intbuf[25],   &intbuf[26],  &intbuf[27]);
+        m_interpolator64.myInterpolate(&intbuf[28],  &intbuf[29],   &intbuf[30],  &intbuf[31]);
+        m_interpolator64.myInterpolate(&intbuf[32],  &intbuf[33],   &intbuf[34],  &intbuf[35]);
+        m_interpolator64.myInterpolate(&intbuf[36],  &intbuf[37],   &intbuf[38],  &intbuf[39]);
+        m_interpolator64.myInterpolate(&intbuf[40],  &intbuf[41],   &intbuf[42],  &intbuf[43]);
+        m_interpolator64.myInterpolate(&intbuf[44],  &intbuf[45],   &intbuf[46],  &intbuf[47]);
+        m_interpolator64.myInterpolate(&intbuf[48],  &intbuf[49],   &intbuf[50],  &intbuf[51]);
+        m_interpolator64.myInterpolate(&intbuf[52],  &intbuf[53],   &intbuf[54],  &intbuf[55]);
+        m_interpolator64.myInterpolate(&intbuf[56],  &intbuf[57],   &intbuf[58],  &intbuf[59]);
+        m_interpolator64.myInterpolate(&intbuf[60],  &intbuf[61],   &intbuf[62],  &intbuf[63]);
+        m_interpolator64.myInterpolate(&intbuf[64],  &intbuf[65],   &intbuf[66],  &intbuf[67]);
+        m_interpolator64.myInterpolate(&intbuf[68],  &intbuf[69],   &intbuf[70],  &intbuf[71]);
+        m_interpolator64.myInterpolate(&intbuf[72],  &intbuf[73],   &intbuf[74],  &intbuf[75]);
+        m_interpolator64.myInterpolate(&intbuf[76],  &intbuf[77],   &intbuf[78],  &intbuf[79]);
+        m_interpolator64.myInterpolate(&intbuf[80],  &intbuf[81],   &intbuf[82],  &intbuf[83]);
+        m_interpolator64.myInterpolate(&intbuf[84],  &intbuf[85],   &intbuf[86],  &intbuf[87]);
+        m_interpolator64.myInterpolate(&intbuf[88],  &intbuf[89],   &intbuf[90],  &intbuf[91]);
+        m_interpolator64.myInterpolate(&intbuf[92],  &intbuf[93],   &intbuf[94],  &intbuf[95]);
+        m_interpolator64.myInterpolate(&intbuf[96],  &intbuf[97],   &intbuf[98],  &intbuf[99]);
+        m_interpolator64.myInterpolate(&intbuf[100], &intbuf[101],  &intbuf[102], &intbuf[103]);
+        m_interpolator64.myInterpolate(&intbuf[104], &intbuf[105],  &intbuf[106], &intbuf[107]);
+        m_interpolator64.myInterpolate(&intbuf[108], &intbuf[109],  &intbuf[110], &intbuf[111]);
+        m_interpolator64.myInterpolate(&intbuf[112], &intbuf[113],  &intbuf[114], &intbuf[115]);
+        m_interpolator64.myInterpolate(&intbuf[116], &intbuf[117],  &intbuf[118], &intbuf[119]);
+        m_interpolator64.myInterpolate(&intbuf[120], &intbuf[121],  &intbuf[122], &intbuf[123]);
+        m_interpolator64.myInterpolate(&intbuf[124], &intbuf[125],  &intbuf[126], &intbuf[127]);
+
+        buf[pos+0]   = intbuf[0]   >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+1]   = intbuf[1]   >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+2]   = intbuf[2]   >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+3]   = intbuf[3]   >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+4]   = intbuf[4]   >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+5]   = intbuf[5]   >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+6]   = intbuf[6]   >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+7]   = intbuf[7]   >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+8]   = intbuf[8]   >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+9]   = intbuf[9]   >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+10]  = intbuf[10]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+11]  = intbuf[11]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+12]  = intbuf[12]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+13]  = intbuf[13]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+14]  = intbuf[14]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+15]  = intbuf[15]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+16]  = intbuf[16]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+17]  = intbuf[17]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+18]  = intbuf[18]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+19]  = intbuf[19]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+20]  = intbuf[20]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+21]  = intbuf[21]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+22]  = intbuf[22]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+23]  = intbuf[23]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+24]  = intbuf[24]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+25]  = intbuf[25]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+26]  = intbuf[26]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+27]  = intbuf[27]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+28]  = intbuf[28]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+29]  = intbuf[29]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+30]  = intbuf[30]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+31]  = intbuf[31]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+32]  = intbuf[32]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+33]  = intbuf[33]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+34]  = intbuf[34]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+35]  = intbuf[35]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+36]  = intbuf[36]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+37]  = intbuf[37]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+38]  = intbuf[38]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+39]  = intbuf[39]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+40]  = intbuf[40]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+41]  = intbuf[41]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+42]  = intbuf[42]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+43]  = intbuf[43]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+44]  = intbuf[44]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+45]  = intbuf[45]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+46]  = intbuf[46]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+47]  = intbuf[47]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+48]  = intbuf[48]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+49]  = intbuf[49]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+50]  = intbuf[50]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+51]  = intbuf[51]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+52]  = intbuf[52]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+53]  = intbuf[53]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+54]  = intbuf[54]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+55]  = intbuf[55]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+56]  = intbuf[56]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+57]  = intbuf[57]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+58]  = intbuf[58]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+59]  = intbuf[59]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+60]  = intbuf[60]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+61]  = intbuf[61]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+62]  = intbuf[62]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+63]  = intbuf[63]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+64]  = intbuf[64]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+65]  = intbuf[65]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+66]  = intbuf[66]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+67]  = intbuf[67]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+68]  = intbuf[68]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+69]  = intbuf[69]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+70]  = intbuf[70]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+71]  = intbuf[71]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+72]  = intbuf[72]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+73]  = intbuf[73]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+74]  = intbuf[74]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+75]  = intbuf[75]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+76]  = intbuf[76]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+77]  = intbuf[77]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+78]  = intbuf[78]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+79]  = intbuf[79]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+80]  = intbuf[80]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+81]  = intbuf[81]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+82]  = intbuf[82]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+83]  = intbuf[83]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+84]  = intbuf[84]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+85]  = intbuf[85]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+86]  = intbuf[86]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+87]  = intbuf[87]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+88]  = intbuf[88]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+89]  = intbuf[89]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+90]  = intbuf[90]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+91]  = intbuf[91]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+92]  = intbuf[92]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+93]  = intbuf[93]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+94]  = intbuf[94]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+95]  = intbuf[95]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+96]  = intbuf[96]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+97]  = intbuf[97]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+98]  = intbuf[98]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+99]  = intbuf[99]  >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+100] = intbuf[100] >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+101] = intbuf[101] >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+102] = intbuf[102] >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+103] = intbuf[103] >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+104] = intbuf[104] >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+105] = intbuf[105] >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+106] = intbuf[106] >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+107] = intbuf[107] >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+108] = intbuf[108] >> interpolation_shifts<SdrBits, OutputBits>::post64;
+        buf[pos+109] = intbuf[109] >> interpolation_shifts<SdrBits, OutputBits>::post64;
+
+        ++(*it);
+	}
+}
+
+#endif /* INCLUDE_GPL_DSP_INTERPOLATORS_H_ */
diff --git a/sdrbase/sdrbase.pro b/sdrbase/sdrbase.pro
index 3423cf11c..f039fdf0f 100644
--- a/sdrbase/sdrbase.pro
+++ b/sdrbase/sdrbase.pro
@@ -131,6 +131,7 @@ HEADERS  += mainwindow.h\
         dsp/cwkeyer.h\
         dsp/complex.h\
         dsp/decimators.h\
+        dsp/interpolators.h\
         dsp/dspcommands.h\
         dsp/dspengine.h\
         dsp/dspdevicesourceengine.h\