kopia lustrzana https://github.com/f4exb/sdrangel
ChannelAnalyzer: set trace length to FFT length when auto-correlation by IFFT is used
rodzic
47e80ad8d1
commit
077a083336
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <algorithm>
|
||||
|
||||
#include "dsp/fftengine.h"
|
||||
#include "fftcorr.h"
|
||||
|
||||
void fftcorr::init_fft()
|
||||
{
|
||||
fftA = new g_fft<float>(flen);
|
||||
fftB = new g_fft<float>(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;
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SDRBASE_DSP_FFTCORR_H_
|
||||
#define SDRBASE_DSP_FFTCORR_H_
|
||||
#ifndef SDRBASE_DSP_FFTCORR2_H_
|
||||
#define SDRBASE_DSP_FFTCORR2_H_
|
||||
|
||||
#include <complex>
|
||||
#include "gfft.h"
|
||||
|
||||
#include "dsp/fftwindow.h"
|
||||
#include "export.h"
|
||||
|
||||
class FFTEngine;
|
||||
|
||||
class SDRBASE_API fftcorr {
|
||||
public:
|
||||
typedef std::complex<float> cmplx;
|
||||
|
@ -43,8 +41,10 @@ private:
|
|||
void init_fft();
|
||||
int flen; //!< FFT length
|
||||
int flen2; //!< half FFT length
|
||||
g_fft<float> *fftA;
|
||||
g_fft<float> *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_ */
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#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++];
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SDRBASE_DSP_FFTCORR2_H_
|
||||
#define SDRBASE_DSP_FFTCORR2_H_
|
||||
|
||||
#include <complex>
|
||||
|
||||
#include "dsp/fftwindow.h"
|
||||
#include "export.h"
|
||||
|
||||
class FFTEngine;
|
||||
|
||||
class SDRBASE_API fftcorr2 {
|
||||
public:
|
||||
typedef std::complex<float> 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_ */
|
Ładowanie…
Reference in New Issue