mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 10:05:46 -05:00
Downsample filtering.
This commit is contained in:
parent
ff312a52a3
commit
dcc9f1917c
@ -223,9 +223,23 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void myDecimate(Sample* sample1, Sample* sample2)
|
||||||
|
{
|
||||||
|
static const qint16 mod33[38] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
|
||||||
|
20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2} ;
|
||||||
|
m_samples[m_ptr][0] = sample1->real();
|
||||||
|
m_samples[m_ptr][1] = sample1->imag();
|
||||||
|
m_ptr = mod33[m_ptr + 2 - 1];
|
||||||
|
|
||||||
|
m_samples[m_ptr][0] = sample2->real();
|
||||||
|
m_samples[m_ptr][1] = sample2->imag();
|
||||||
|
doFIR(sample2);
|
||||||
|
m_ptr = mod33[m_ptr + 2 - 1];
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
qint16 m_samples[HB_FILTERORDER + 1][2];
|
qint16 m_samples[HB_FILTERORDER + 1][2];
|
||||||
int m_ptr;
|
qint16 m_ptr;
|
||||||
int m_state;
|
int m_state;
|
||||||
|
|
||||||
void doFIR(Sample* sample)
|
void doFIR(Sample* sample)
|
||||||
@ -267,15 +281,17 @@ protected:
|
|||||||
0.317491986549921390015072120149852707982 * (1 << HB_SHIFT)
|
0.317491986549921390015072120149852707982 * (1 << HB_SHIFT)
|
||||||
};
|
};
|
||||||
#elif HB_FILTERORDER == 32
|
#elif HB_FILTERORDER == 32
|
||||||
|
static const qint16 mod33[38] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
|
||||||
|
20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2} ;
|
||||||
static const qint32 COEFF[8] = {
|
static const qint32 COEFF[8] = {
|
||||||
-0.015956912844043127236437484839370881673 * (1 << HB_SHIFT),
|
(qint32)(-0.015956912844043127236437484839370881673 * (1 << HB_SHIFT)),
|
||||||
0.013023031678944928940522274274371739011 * (1 << HB_SHIFT),
|
(qint32)( 0.013023031678944928940522274274371739011 * (1 << HB_SHIFT)),
|
||||||
-0.01866942273717486777684371190844103694 * (1 << HB_SHIFT),
|
(qint32)(-0.01866942273717486777684371190844103694 * (1 << HB_SHIFT)),
|
||||||
0.026550887571157304190005987720724078827 * (1 << HB_SHIFT),
|
(qint32)( 0.026550887571157304190005987720724078827 * (1 << HB_SHIFT)),
|
||||||
-0.038350314277854319344740474662103224546 * (1 << HB_SHIFT),
|
(qint32)(-0.038350314277854319344740474662103224546 * (1 << HB_SHIFT)),
|
||||||
0.058429248652825838128421764849917963147 * (1 << HB_SHIFT),
|
(qint32)( 0.058429248652825838128421764849917963147 * (1 << HB_SHIFT)),
|
||||||
-0.102889802028955756885153505209018476307 * (1 << HB_SHIFT),
|
(qint32)(-0.102889802028955756885153505209018476307 * (1 << HB_SHIFT)),
|
||||||
0.317237706405931241260276465254719369113 * (1 << HB_SHIFT)
|
(qint32)( 0.317237706405931241260276465254719369113 * (1 << HB_SHIFT))
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
#error unsupported filter order
|
#error unsupported filter order
|
||||||
@ -283,8 +299,8 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
// init read-pointer
|
// init read-pointer
|
||||||
int a = (m_ptr + 1) % (HB_FILTERORDER + 1);
|
int a = mod33[m_ptr + 2 + 1]; // 0 + 1
|
||||||
int b = (m_ptr + (HB_FILTERORDER - 1)) % (HB_FILTERORDER + 1);
|
int b = mod33[m_ptr + 2 - 2]; //-1 - 1
|
||||||
|
|
||||||
// go through samples in buffer
|
// go through samples in buffer
|
||||||
qint32 iAcc = 0;
|
qint32 iAcc = 0;
|
||||||
@ -297,17 +313,16 @@ protected:
|
|||||||
qAcc += qTmp * COEFF[i];
|
qAcc += qTmp * COEFF[i];
|
||||||
|
|
||||||
// update read-pointer
|
// update read-pointer
|
||||||
a = (a + 2) % (HB_FILTERORDER + 1);
|
a = mod33[a + 2 + 2];
|
||||||
b = (b + (HB_FILTERORDER - 1)) % (HB_FILTERORDER + 1);
|
b = mod33[b + 2 - 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
a = (a + HB_FILTERORDER) % (HB_FILTERORDER + 1);
|
a = mod33[a + 2 - 1];
|
||||||
iAcc += m_samples[a][0] * (qint32)(0.5 * (1 << HB_SHIFT));
|
iAcc += ((qint32)m_samples[a][0] + 1) << (HB_SHIFT - 1);
|
||||||
qAcc += m_samples[a][1] * (qint32)(0.5 * (1 << HB_SHIFT));
|
qAcc += ((qint32)m_samples[a][1] + 1) << (HB_SHIFT - 1);
|
||||||
|
|
||||||
// done, save result
|
sample->setReal(iAcc >> HB_SHIFT);
|
||||||
sample->setReal((iAcc + (qint32)(0.5 * (1 << HB_SHIFT))) >> HB_SHIFT);
|
sample->setImag(qAcc >> HB_SHIFT);
|
||||||
sample->setImag((qAcc + (qint32)(0.5 * (1 << HB_SHIFT))) >> HB_SHIFT);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ void RTLSDRThread::decimate4(SampleVector::iterator* it, const quint8* buf, qint
|
|||||||
for (int pos = 0; pos < len - 7; pos += 8) {
|
for (int pos = 0; pos < len - 7; pos += 8) {
|
||||||
xreal = buf[pos+0] - buf[pos+3] + buf[pos+7] - buf[pos+4];
|
xreal = buf[pos+0] - buf[pos+3] + buf[pos+7] - buf[pos+4];
|
||||||
yimag = buf[pos+1] - buf[pos+5] + buf[pos+2] - buf[pos+6];
|
yimag = buf[pos+1] - buf[pos+5] + buf[pos+2] - buf[pos+6];
|
||||||
Sample s( xreal << 4, yimag << 4 );
|
Sample s( xreal << 3, yimag << 3 );
|
||||||
**it = s;
|
**it = s;
|
||||||
(*it)++;
|
(*it)++;
|
||||||
}
|
}
|
||||||
@ -122,25 +122,29 @@ void RTLSDRThread::decimate16(SampleVector::iterator* it, const quint8* buf, qin
|
|||||||
{
|
{
|
||||||
// Offset tuning: 4x downsample and rotate, then
|
// Offset tuning: 4x downsample and rotate, then
|
||||||
// downsample 4x more. [ rotate: 0, 1, -3, 2, -4, -5, 7, -6]
|
// downsample 4x more. [ rotate: 0, 1, -3, 2, -4, -5, 7, -6]
|
||||||
qint16 xreal, yimag;
|
qint16 xreal[4], yimag[4];
|
||||||
for (int step = 0; step < len - 31; step +=32) {
|
bool b;
|
||||||
xreal = yimag = 0;
|
for (int pos = 0; pos < len - 31; ) {
|
||||||
for (int pos = step; pos < step + 32; pos += 8) {
|
for (int i = 0; i < 4; i++) {
|
||||||
xreal += buf[pos+0] - buf[pos+3] + buf[pos+7] - buf[pos+4];
|
xreal[i] = (buf[pos+0] - buf[pos+3] + buf[pos+7] - buf[pos+4]) << 4;
|
||||||
yimag += buf[pos+1] - buf[pos+5] + buf[pos+2] - buf[pos+6];
|
yimag[i] = (buf[pos+1] - buf[pos+5] + buf[pos+2] - buf[pos+6]) << 4;
|
||||||
|
pos += 8;
|
||||||
}
|
}
|
||||||
Sample s( xreal << 3, yimag << 3 );
|
Sample s1( xreal[0], yimag[0] );
|
||||||
**it = s;
|
Sample s2( xreal[1], yimag[1] );
|
||||||
|
Sample s3( xreal[2], yimag[2] );
|
||||||
|
Sample s4( xreal[3], yimag[3] );
|
||||||
|
m_decimator2.myDecimate(&s1, &s2);
|
||||||
|
m_decimator2.myDecimate(&s3, &s4);
|
||||||
|
m_decimator4.myDecimate(&s2, &s4);
|
||||||
|
**it = s4;
|
||||||
(*it)++;
|
(*it)++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Decimate everything by 16x, except 288kHz
|
|
||||||
TODO : no offset tuning for direct sampling
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
// Decimate everything by 16x, except 288kHz
|
||||||
void RTLSDRThread::callback(const quint8* buf, qint32 len)
|
void RTLSDRThread::callback(const quint8* buf, qint32 len)
|
||||||
{
|
{
|
||||||
qint16 xreal, yimag, phase;
|
qint16 xreal, yimag, phase;
|
||||||
@ -149,14 +153,12 @@ void RTLSDRThread::callback(const quint8* buf, qint32 len)
|
|||||||
int mode = 0;
|
int mode = 0;
|
||||||
if (m_samplerate < 800000)
|
if (m_samplerate < 800000)
|
||||||
mode = 2;
|
mode = 2;
|
||||||
// if (directsampling) mode++;
|
|
||||||
|
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case 0:
|
case 0:
|
||||||
decimate16(&it, buf, len);
|
decimate16(&it, buf, len);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
// no_rotate16(&it, buf, len);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
@ -164,7 +166,6 @@ void RTLSDRThread::callback(const quint8* buf, qint32 len)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
// norotate4(&it, buf, len);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -183,3 +184,4 @@ void RTLSDRThread::callbackHelper(unsigned char* buf, uint32_t len, void* ctx)
|
|||||||
RTLSDRThread* thread = (RTLSDRThread*)ctx;
|
RTLSDRThread* thread = (RTLSDRThread*)ctx;
|
||||||
thread->callback(buf, len);
|
thread->callback(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
#include <rtl-sdr.h>
|
#include <rtl-sdr.h>
|
||||||
#include "dsp/samplefifo.h"
|
#include "dsp/samplefifo.h"
|
||||||
|
#include "dsp/inthalfbandfilter.h"
|
||||||
|
|
||||||
class RTLSDRThread : public QThread {
|
class RTLSDRThread : public QThread {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -46,6 +47,9 @@ private:
|
|||||||
|
|
||||||
int m_samplerate;
|
int m_samplerate;
|
||||||
|
|
||||||
|
IntHalfbandFilter m_decimator2;
|
||||||
|
IntHalfbandFilter m_decimator4;
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
void decimate2(SampleVector::iterator* it, const quint8* buf, qint32 len);
|
void decimate2(SampleVector::iterator* it, const quint8* buf, qint32 len);
|
||||||
void decimate4(SampleVector::iterator* it, const quint8* buf, qint32 len);
|
void decimate4(SampleVector::iterator* it, const quint8* buf, qint32 len);
|
||||||
|
Loading…
Reference in New Issue
Block a user