diff --git a/plugins/channelmimo/interferometer/interferometercorr.cpp b/plugins/channelmimo/interferometer/interferometercorr.cpp index b68b00453..219b0a84c 100644 --- a/plugins/channelmimo/interferometer/interferometercorr.cpp +++ b/plugins/channelmimo/interferometer/interferometercorr.cpp @@ -126,6 +126,8 @@ InterferometerCorrelator::InterferometerCorrelator(int fftSize) : m_tcorr.resize(fftSize); m_scorrSize = fftSize; m_tcorrSize = fftSize; + + m_fftProdScale = SDR_RX_SCALEF / (8*m_fftSize); } InterferometerCorrelator::~InterferometerCorrelator() @@ -166,15 +168,18 @@ bool InterferometerCorrelator::performCorr( case InterferometerSettings::CorrelationMultiply: results = performOpCorr(data0, size0, data1, size1, sMulConj); break; - case InterferometerSettings::CorrelationFFT: + case InterferometerSettings::CorrelationIFFT: results = performFFTCorr(data0, size0, data1, size1); break; - case InterferometerSettings::CorrelationFFT2: + case InterferometerSettings::CorrelationIFFT2: results = performFFT2Corr(data0, size0, data1, size1); break; - case InterferometerSettings::CorrelationFFTStar: + case InterferometerSettings::CorrelationIFFTStar: results = performFFTCorr(data0, size0, data1, size1, true); break; + case InterferometerSettings::CorrelationFFT: + results = performFFTProd(data0, size0, data1, size1); + break; default: break; } @@ -195,15 +200,18 @@ bool InterferometerCorrelator::performCorr( case InterferometerSettings::CorrelationMultiply: results = performOpCorr(data0, size0, data1, size1, sMulConjInv); break; - case InterferometerSettings::CorrelationFFT: + case InterferometerSettings::CorrelationIFFT: results = performFFTCorr(data0, size0, m_data1p, size1); break; - case InterferometerSettings::CorrelationFFT2: + case InterferometerSettings::CorrelationIFFT2: results = performFFT2Corr(data0, size0, m_data1p, size1); break; - case InterferometerSettings::CorrelationFFTStar: + case InterferometerSettings::CorrelationIFFTStar: results = performFFTCorr(data0, size0, m_data1p, size1, true); break; + case InterferometerSettings::CorrelationFFT: + results = performFFTProd(data0, size0, m_data1p, size1); + break; default: break; } @@ -244,15 +252,18 @@ bool InterferometerCorrelator::performCorr( case InterferometerSettings::CorrelationMultiply: results = performOpCorr(data0, size0, m_data1p, size1, sMulConj); break; - case InterferometerSettings::CorrelationFFT: + case InterferometerSettings::CorrelationIFFT: results = performFFTCorr(data0, size0, m_data1p, size1); break; - case InterferometerSettings::CorrelationFFT2: + case InterferometerSettings::CorrelationIFFT2: results = performFFT2Corr(data0, size0, m_data1p, size1); break; - case InterferometerSettings::CorrelationFFTStar: + case InterferometerSettings::CorrelationIFFTStar: results = performFFTCorr(data0, size0, m_data1p, size1, true); break; + case InterferometerSettings::CorrelationFFT: + results = performFFTProd(data0, size0, m_data1p, size1); + break; default: break; } @@ -504,6 +515,103 @@ bool InterferometerCorrelator::performFFT2Corr( return nfft > 0; } +bool InterferometerCorrelator::performFFTProd( + const SampleVector& data0, + int size0, + const SampleVector& data1, + int size1 +) +{ + unsigned int size = std::min(size0, size1); + int nfft = 0; + SampleVector::const_iterator begin0 = data0.begin(); + SampleVector::const_iterator begin1 = data1.begin(); + adjustSCorrSize(size); + adjustTCorrSize(size); + + while (size >= m_fftSize) + { + // FFT[0] + std::transform( + begin0, + begin0 + m_fftSize, + m_fft2[0]->in(), + [](const Sample& s) -> std::complex { + return std::complex{s.real() / SDR_RX_SCALEF, s.imag() / SDR_RX_SCALEF}; + } + ); + m_window.apply(m_fft2[0]->in()); + m_fft2[0]->transform(); + + // FFT[1] + std::transform( + begin1, + begin1 + m_fftSize, + m_fft2[1]->in(), + [](const Sample& s) -> std::complex { + return std::complex{s.real() / SDR_RX_SCALEF, s.imag() / SDR_RX_SCALEF}; + } + ); + m_window.apply(m_fft2[1]->in()); + m_fft2[1]->transform(); + + // conjugate FFT[1] + std::transform( + m_fft2[1]->out(), + m_fft2[1]->out() + m_fftSize, + m_dataj, + [](const std::complex& c) -> std::complex { + return std::conj(c); + } + ); + + // product of FFT[1]* with FFT[0] and store in both results + std::transform( + m_fft2[0]->out(), + m_fft2[0]->out() + m_fftSize, + m_dataj, + m_invFFT2->in(), + [this](std::complex& a, const std::complex& b) -> std::complex { + return (a*b); + } + ); + + // copy product to time domain - convert and scale to FFT size + std::transform( + m_invFFT2->in(), + m_invFFT2->in() + m_fftSize, + m_tcorr.begin() + nfft*m_fftSize, + [this](const std::complex& a) -> Sample { + Sample s; + s.setReal(a.real()*m_fftProdScale); + s.setImag(a.imag()*m_fftProdScale); + return s; + } + ); + + // feed spectrum with the direct conjugate product + std::transform( + begin0, + begin0 + m_fftSize, + begin1, + m_scorr.begin() + nfft*m_fftSize, + sMulConj + ); + + size -= m_fftSize; + begin0 += m_fftSize; + begin1 += m_fftSize; + nfft++; + } + + // update the samples counters + m_processed = nfft*m_fftSize; + m_remaining[0] = size0 - nfft*m_fftSize; + m_remaining[1] = size1 - nfft*m_fftSize; + + return nfft > 0; +} + void InterferometerCorrelator::adjustSCorrSize(int size) { int nFFTSize = (size/m_fftSize)*m_fftSize; diff --git a/plugins/channelmimo/interferometer/interferometercorr.h b/plugins/channelmimo/interferometer/interferometercorr.h index ddeff47c0..1b964c1cb 100644 --- a/plugins/channelmimo/interferometer/interferometercorr.h +++ b/plugins/channelmimo/interferometer/interferometercorr.h @@ -75,6 +75,12 @@ private: const SampleVector& data1, int size1 ); + bool performFFTProd( //!< Returns true if results were produced + const SampleVector& data0, + int size0, + const SampleVector& data1, + int size1 + ); void adjustSCorrSize(int size); void adjustTCorrSize(int size); @@ -89,6 +95,7 @@ private: SampleVector m_data0w; //!< windowed data 0 SampleVector m_data1w; //!< windowed data 1 SampleVector m_data1p; //!< data1 with phase correction + float m_fftProdScale; //!< scaling factor for FFT products int m_scorrSize; //!< spectrum correlations vector size int m_tcorrSize; //!< time correlations vector size int m_phase; //!< phase correction diff --git a/plugins/channelmimo/interferometer/interferometergui.ui b/plugins/channelmimo/interferometer/interferometergui.ui index b5dd157ba..c1d8f23c4 100644 --- a/plugins/channelmimo/interferometer/interferometergui.ui +++ b/plugins/channelmimo/interferometer/interferometergui.ui @@ -189,21 +189,26 @@ A.B* + + + IFFT + + + + + IFFT2 + + + + + IFFT* + + FFT - - - FFT2 - - - - - FFT* - - diff --git a/plugins/channelmimo/interferometer/interferometersettings.h b/plugins/channelmimo/interferometer/interferometersettings.h index 4d24202c1..10c5f9f81 100644 --- a/plugins/channelmimo/interferometer/interferometersettings.h +++ b/plugins/channelmimo/interferometer/interferometersettings.h @@ -31,9 +31,10 @@ struct InterferometerSettings Correlation1, CorrelationAdd, CorrelationMultiply, - CorrelationFFT, - CorrelationFFT2, - CorrelationFFTStar + CorrelationIFFT, + CorrelationIFFT2, + CorrelationIFFTStar, + CorrelationFFT }; CorrelationType m_correlationType;