From 077a083336b6d30389349a2d5f6382b89486aff9 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 27 Oct 2019 22:25:05 +0100 Subject: [PATCH] ChannelAnalyzer: set trace length to FFT length when auto-correlation by IFFT is used --- plugins/channelrx/chanalyzer/chanalyzer.cpp | 3 +- plugins/channelrx/chanalyzer/chanalyzer.h | 5 +- .../channelrx/chanalyzer/chanalyzergui.cpp | 8 ++ .../channelrx/chanalyzer/chanalyzerplugin.cpp | 2 +- sdrbase/CMakeLists.txt | 2 - sdrbase/dsp/fftcorr.cpp | 50 +++++--- sdrbase/dsp/fftcorr.h | 26 ++-- sdrbase/dsp/fftcorr2.cpp | 120 ------------------ sdrbase/dsp/fftcorr2.h | 58 --------- 9 files changed, 56 insertions(+), 218 deletions(-) delete mode 100644 sdrbase/dsp/fftcorr2.cpp delete mode 100644 sdrbase/dsp/fftcorr2.h diff --git a/plugins/channelrx/chanalyzer/chanalyzer.cpp b/plugins/channelrx/chanalyzer/chanalyzer.cpp index e5c223ed0..cac11cf05 100644 --- a/plugins/channelrx/chanalyzer/chanalyzer.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzer.cpp @@ -31,6 +31,7 @@ MESSAGE_CLASS_DEFINITION(ChannelAnalyzer::MsgReportChannelSampleRateChanged, Mes const QString ChannelAnalyzer::m_channelIdURI = "sdrangel.channel.chanalyzer"; const QString ChannelAnalyzer::m_channelId = "ChannelAnalyzer"; +const unsigned int ChannelAnalyzer::m_corrFFTLen = 4*ssbFftLen; ChannelAnalyzer::ChannelAnalyzer(DeviceAPI *deviceAPI) : ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink), @@ -52,7 +53,7 @@ ChannelAnalyzer::ChannelAnalyzer(DeviceAPI *deviceAPI) : SSBFilter = new fftfilt(m_settings.m_lowCutoff / m_inputSampleRate, m_settings.m_bandwidth / m_inputSampleRate, ssbFftLen); DSBFilter = new fftfilt(m_settings.m_bandwidth / m_inputSampleRate, 2*ssbFftLen); RRCFilter = new fftfilt(m_settings.m_bandwidth / m_inputSampleRate, 2*ssbFftLen); - m_corr = new fftcorr2(8*ssbFftLen); // 8k for 4k effective samples + m_corr = new fftcorr(2*m_corrFFTLen); // 8k for 4k effective samples m_pll.computeCoefficients(0.002f, 0.5f, 10.0f); // bandwidth, damping factor, loop gain applyChannelSettings(m_inputSampleRate, m_inputFrequencyOffset, true); diff --git a/plugins/channelrx/chanalyzer/chanalyzer.h b/plugins/channelrx/chanalyzer/chanalyzer.h index d7325d8e1..5e12a95ec 100644 --- a/plugins/channelrx/chanalyzer/chanalyzer.h +++ b/plugins/channelrx/chanalyzer/chanalyzer.h @@ -25,7 +25,7 @@ #include "channel/channelapi.h" #include "dsp/interpolator.h" #include "dsp/ncof.h" -#include "dsp/fftcorr2.h" +#include "dsp/fftcorr.h" #include "dsp/fftfilt.h" #include "dsp/phaselockcomplex.h" #include "dsp/freqlockcomplex.h" @@ -156,6 +156,7 @@ public: static const QString m_channelIdURI; static const QString m_channelId; + static const unsigned int m_corrFFTLen; private: DeviceAPI *m_deviceAPI; @@ -181,7 +182,7 @@ private: fftfilt* SSBFilter; fftfilt* DSBFilter; fftfilt* RRCFilter; - fftcorr2* m_corr; + fftcorr* m_corr; BasebandSampleSink* m_sampleSink; SampleVector m_sampleBuffer; diff --git a/plugins/channelrx/chanalyzer/chanalyzergui.cpp b/plugins/channelrx/chanalyzer/chanalyzergui.cpp index b078fafe1..588cb9d03 100644 --- a/plugins/channelrx/chanalyzer/chanalyzergui.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzergui.cpp @@ -292,6 +292,14 @@ int ChannelAnalyzerGUI::getRequestedChannelSampleRate() void ChannelAnalyzerGUI::on_signalSelect_currentIndexChanged(int index) { m_settings.m_inputType = (ChannelAnalyzerSettings::InputType) index; + + if (m_settings.m_inputType == ChannelAnalyzerSettings::InputAutoCorr) { + m_scopeVis->setTraceChunkSize(ChannelAnalyzer::m_corrFFTLen); + } else { + m_scopeVis->setTraceChunkSize(ScopeVis::m_traceChunkDefaultSize); + } + + ui->scopeGUI->traceLengthChange(); applySettings(); } diff --git a/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp b/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp index 942540f7f..29c9e26c5 100644 --- a/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp +++ b/plugins/channelrx/chanalyzer/chanalyzerplugin.cpp @@ -25,7 +25,7 @@ const PluginDescriptor ChannelAnalyzerPlugin::m_pluginDescriptor = { QString("Channel Analyzer"), - QString("4.11.6"), + QString("4.11.12"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index 177827d6b..6a926dd88 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -79,7 +79,6 @@ set(sdrbase_SOURCES dsp/dspdevicesinkengine.cpp dsp/dspdevicemimoengine.cpp dsp/fftcorr.cpp - dsp/fftcorr2.cpp dsp/fftengine.cpp dsp/fftfilt.cpp dsp/fftwindow.cpp @@ -201,7 +200,6 @@ set(sdrbase_HEADERS dsp/dspdevicemimoengine.h dsp/dsptypes.h dsp/fftcorr.h - dsp/fftcorr2.h dsp/fftengine.h dsp/fftfilt.h dsp/fftwengine.h diff --git a/sdrbase/dsp/fftcorr.cpp b/sdrbase/dsp/fftcorr.cpp index 101db05f4..1846dac23 100644 --- a/sdrbase/dsp/fftcorr.cpp +++ b/sdrbase/dsp/fftcorr.cpp @@ -1,13 +1,8 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2018 F4EXB // +// Copyright (C) 2019 F4EXB // // written by Edouard Griffiths // // // -// FFT based cross correlation // -// // -// See: http://liquidsdr.org/blog/pll-howto/ // -// Fixed filter registers saturation // -// Added order for PSK locking. This brilliant idea actually comes from this // -// post: https://www.dsprelated.com/showthread/comp.dsp/36356-1.php // +// FFT based cross correlation. Uses FFTW/Kiss engine. // // // // 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 // @@ -24,17 +19,21 @@ /////////////////////////////////////////////////////////////////////////////////// #include + +#include "dsp/fftengine.h" #include "fftcorr.h" void fftcorr::init_fft() { - fftA = new g_fft(flen); - fftB = new g_fft(flen); + fftA->configure(flen, false); + fftB->configure(flen, false); + fftInvA->configure(flen, true); + m_window.create(FFTWindow::Hanning, flen); - dataA = new cmplx[flen]; - dataB = new cmplx[flen]; - dataBj = new cmplx[flen]; - dataP = new cmplx[flen]; + dataA = new cmplx[flen]; + dataB = new cmplx[flen]; + dataBj = new cmplx[flen]; + dataP = new cmplx[flen]; std::fill(dataA, dataA+flen, 0); std::fill(dataB, dataB+flen, 0); @@ -44,7 +43,12 @@ void fftcorr::init_fft() outptr = 0; } -fftcorr::fftcorr(int len) : flen(len), flen2(len>>1) +fftcorr::fftcorr(int len) : + flen(len), + flen2(len>>1), + fftA(FFTEngine::create()), + fftB(FFTEngine::create()), + fftInvA(FFTEngine::create()) { init_fft(); } @@ -71,21 +75,25 @@ int fftcorr::run(const cmplx& inA, const cmplx* inB, cmplx **out) return 0; } - fftA->ComplexFFT(dataA); + m_window.apply(dataA, fftA->in()); + fftA->transform(); - if (inB) { - fftB->ComplexFFT(dataB); + if (inB) + { + m_window.apply(dataB, fftB->in()); + fftB->transform(); } if (inB) { - std::transform(dataB, dataB+flen, dataBj, [](const cmplx& c) -> cmplx { return std::conj(c); }); + std::transform(fftB->out(), fftB->out()+flen, dataBj, [](const cmplx& c) -> cmplx { return std::conj(c); }); } else { - std::transform(dataA, dataA+flen, dataBj, [](const cmplx& c) -> cmplx { return std::conj(c); }); + std::transform(fftA->out(), fftA->out()+flen, dataBj, [](const cmplx& c) -> cmplx { return std::conj(c); }); } - std::transform(dataA, dataA+flen, dataBj, dataP, [](const cmplx& a, const cmplx& b) -> cmplx { return a*b; }); + std::transform(fftA->out(), fftA->out()+flen, dataBj, fftInvA->in(), [](const cmplx& a, const cmplx& b) -> cmplx { return a*b; }); - fftA->InverseComplexFFT(dataP); + fftInvA->transform(); + std::copy(fftInvA->out(), fftInvA->out()+flen, dataP); std::fill(dataA, dataA+flen, 0); inptrA = 0; diff --git a/sdrbase/dsp/fftcorr.h b/sdrbase/dsp/fftcorr.h index e7df0c4ce..528927ead 100644 --- a/sdrbase/dsp/fftcorr.h +++ b/sdrbase/dsp/fftcorr.h @@ -1,13 +1,8 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2018 F4EXB // +// Copyright (C) 2019 F4EXB // // written by Edouard Griffiths // // // -// FFT based cross correlation // -// // -// See: http://liquidsdr.org/blog/pll-howto/ // -// Fixed filter registers saturation // -// Added order for PSK locking. This brilliant idea actually comes from this // -// post: https://www.dsprelated.com/showthread/comp.dsp/36356-1.php // +// FFT based cross correlation. Uses FFTW/Kiss engine. // // // // 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 // @@ -23,13 +18,16 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef SDRBASE_DSP_FFTCORR_H_ -#define SDRBASE_DSP_FFTCORR_H_ +#ifndef SDRBASE_DSP_FFTCORR2_H_ +#define SDRBASE_DSP_FFTCORR2_H_ #include -#include "gfft.h" + +#include "dsp/fftwindow.h" #include "export.h" +class FFTEngine; + class SDRBASE_API fftcorr { public: typedef std::complex cmplx; @@ -43,8 +41,10 @@ private: void init_fft(); int flen; //!< FFT length int flen2; //!< half FFT length - g_fft *fftA; - g_fft *fftB; + FFTEngine *fftA; + FFTEngine *fftB; + FFTEngine *fftInvA; + FFTWindow m_window; cmplx *dataA; // from A input cmplx *dataB; // from B input cmplx *dataBj; // conjugate of B @@ -55,4 +55,4 @@ private: }; -#endif /* SDRBASE_DSP_FFTCORR_H_ */ +#endif /* SDRBASE_DSP_FFTCORR2_H_ */ diff --git a/sdrbase/dsp/fftcorr2.cpp b/sdrbase/dsp/fftcorr2.cpp deleted file mode 100644 index e0847d3d1..000000000 --- a/sdrbase/dsp/fftcorr2.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2019 F4EXB // -// written by Edouard Griffiths // -// // -// FFT based cross correlation. Uses FFTW/Kiss engine. // -// // -// 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 . // -/////////////////////////////////////////////////////////////////////////////////// - -#include - -#include "dsp/fftengine.h" -#include "fftcorr2.h" - -void fftcorr2::init_fft() -{ - fftA->configure(flen, false); - fftB->configure(flen, false); - fftInvA->configure(flen, true); - m_window.create(FFTWindow::Hamming, flen); - - dataA = new cmplx[flen]; - dataB = new cmplx[flen]; - dataBj = new cmplx[flen]; - dataP = new cmplx[flen]; - - std::fill(dataA, dataA+flen, 0); - std::fill(dataB, dataB+flen, 0); - - inptrA = 0; - inptrB = 0; - outptr = 0; -} - -fftcorr2::fftcorr2(int len) : - flen(len), - flen2(len>>1), - fftA(FFTEngine::create()), - fftB(FFTEngine::create()), - fftInvA(FFTEngine::create()) -{ - init_fft(); -} - -fftcorr2::~fftcorr2() -{ - delete fftA; - delete fftB; - delete[] dataA; - delete[] dataB; - delete[] dataBj; - delete[] dataP; -} - -int fftcorr2::run(const cmplx& inA, const cmplx* inB, cmplx **out) -{ - dataA[inptrA++] = inA; - - if (inB) { - dataB[inptrB++] = *inB; - } - - if (inptrA < flen2) { - return 0; - } - - m_window.apply(dataA, fftA->in()); - fftA->transform(); - - if (inB) - { - m_window.apply(dataB, fftB->in()); - fftB->transform(); - } - - if (inB) { - std::transform(fftB->out(), fftB->out()+flen, dataBj, [](const cmplx& c) -> cmplx { return std::conj(c); }); - } else { - std::transform(fftA->out(), fftA->out()+flen, dataBj, [](const cmplx& c) -> cmplx { return std::conj(c); }); - } - - std::transform(fftA->out(), fftA->out()+flen, dataBj, fftInvA->in(), [](const cmplx& a, const cmplx& b) -> cmplx { return a*b; }); - - fftInvA->transform(); - std::copy(fftInvA->out(), fftInvA->out()+flen, dataP); - - std::fill(dataA, dataA+flen, 0); - inptrA = 0; - - if (inB) - { - std::fill(dataB, dataB+flen, 0); - inptrB = 0; - } - - *out = dataP; - return flen2; -} - -const fftcorr2::cmplx& fftcorr2::run(const cmplx& inA, const cmplx* inB) -{ - cmplx *dummy; - - if (run(inA, inB, &dummy)) { - outptr = 0; - } - - return dataP[outptr++]; -} diff --git a/sdrbase/dsp/fftcorr2.h b/sdrbase/dsp/fftcorr2.h deleted file mode 100644 index 9042de2ba..000000000 --- a/sdrbase/dsp/fftcorr2.h +++ /dev/null @@ -1,58 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2019 F4EXB // -// written by Edouard Griffiths // -// // -// FFT based cross correlation. Uses FFTW/Kiss engine. // -// // -// 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_DSP_FFTCORR2_H_ -#define SDRBASE_DSP_FFTCORR2_H_ - -#include - -#include "dsp/fftwindow.h" -#include "export.h" - -class FFTEngine; - -class SDRBASE_API fftcorr2 { -public: - typedef std::complex cmplx; - fftcorr2(int len); - ~fftcorr2(); - - int run(const cmplx& inA, const cmplx* inB, cmplx **out); //!< if inB = 0 then run auto-correlation - const cmplx& run(const cmplx& inA, const cmplx* inB); - -private: - void init_fft(); - int flen; //!< FFT length - int flen2; //!< half FFT length - FFTEngine *fftA; - FFTEngine *fftB; - FFTEngine *fftInvA; - FFTWindow m_window; - cmplx *dataA; // from A input - cmplx *dataB; // from B input - cmplx *dataBj; // conjugate of B - cmplx *dataP; // product of A with conjugate of B - int inptrA; - int inptrB; - int outptr; -}; - - -#endif /* SDRBASE_DSP_FFTCORR2_H_ */