More DSP cleanup + Remove FastFFT option because it should never be used

This commit is contained in:
AlexandreRouma 2022-07-27 21:35:36 +02:00
parent 8efd5cd01a
commit 575a941e24
25 changed files with 335 additions and 86 deletions

View File

@ -11,6 +11,7 @@ FIRST: Before reporting any bug, make sure that the bug you are reporting has no
**Hardware**
- CPU:
- RAM:
- GPU:
- SDR: (Remote or local? If remote, what protocol?)

View File

@ -95,18 +95,18 @@ jobs:
- name: Install SDRplay API
run: wget https://www.sdrplay.com/software/SDRplay_RSP_API-MacOSX-3.07.3.pkg && sudo installer -pkg SDRplay_RSP_API-MacOSX-3.07.3.pkg -target /
# - name: Install libiio
# run: git clone https://github.com/analogdevicesinc/libiio && cd libiio && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install libiio
run: git clone https://github.com/analogdevicesinc/libiio && cd libiio && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
# - name: Install libad9361
# run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install libad9361
run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install LimeSuite
run: git clone https://github.com/myriadrf/LimeSuite && cd LimeSuite && mkdir builddir && cd builddir && cmake -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Prepare CMake
working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=OFF -DOPT_BUILD_SOAPY_SOURCE=OFF -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -DOPT_BUILD_SOAPY_SOURCE=OFF -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
- name: Build
working-directory: ${{runner.workspace}}/build

View File

@ -1,6 +1,6 @@
#pragma once
#include "../processor.h"
#include "../math/freq_to_omega.h"
#include "../math/hz_to_rads.h"
namespace dsp::channel {
class FrequencyXlator : public Processor<complex_t, complex_t> {
@ -19,7 +19,7 @@ namespace dsp::channel {
}
void init(stream<complex_t>* in, double offset, double samplerate) {
init(in, math::freqToOmega(offset, samplerate));
init(in, math::hzToRads(offset, samplerate));
}
void setOffset(double offset) {
@ -29,7 +29,7 @@ namespace dsp::channel {
}
void setOffset(double offset, double samplerate) {
setOffset(math::freqToOmega(offset, samplerate));
setOffset(math::hzToRads(offset, samplerate));
}
void reset() {

View File

@ -168,7 +168,7 @@ namespace dsp::clock_recovery {
protected:
void generateInterpTaps() {
double bw = 0.5 / (double)_interpPhaseCount;
dsp::tap<float> lp = dsp::taps::windowedSinc<float>(_interpPhaseCount * _interpTapCount, dsp::math::freqToOmega(bw, 1.0), dsp::window::nuttall, _interpPhaseCount);
dsp::tap<float> lp = dsp::taps::windowedSinc<float>(_interpPhaseCount * _interpTapCount, dsp::math::hzToRads(bw, 1.0), dsp::window::nuttall, _interpPhaseCount);
interpBank = dsp::multirate::buildPolyphaseBank<float>(_interpPhaseCount, lp);
taps::free(lp);
}

View File

@ -172,7 +172,7 @@ namespace dsp::clock_recovery {
protected:
void generateInterpTaps() {
double bw = 0.5 / (double)_interpPhaseCount;
dsp::tap<float> lp = dsp::taps::windowedSinc<float>(_interpPhaseCount * _interpTapCount, dsp::math::freqToOmega(bw, 1.0), dsp::window::nuttall, _interpPhaseCount);
dsp::tap<float> lp = dsp::taps::windowedSinc<float>(_interpPhaseCount * _interpTapCount, dsp::math::hzToRads(bw, 1.0), dsp::window::nuttall, _interpPhaseCount);
interpBank = dsp::multirate::buildPolyphaseBank<float>(_interpPhaseCount, lp);
taps::free(lp);
}

View File

@ -43,7 +43,7 @@ namespace dsp::demod {
pilotFirTaps = taps::bandPass<complex_t>(18750.0, 19250.0, 3000.0, _samplerate, true);
pilotFir.init(NULL, pilotFirTaps);
rtoc.init(NULL);
pilotPLL.init(NULL, 25000.0 / _samplerate, 0.0, math::freqToOmega(19000.0, _samplerate), math::freqToOmega(18750.0, _samplerate), math::freqToOmega(19250.0, _samplerate));
pilotPLL.init(NULL, 25000.0 / _samplerate, 0.0, math::hzToRads(19000.0, _samplerate), math::hzToRads(18750.0, _samplerate), math::hzToRads(19250.0, _samplerate));
lprDelay.init(NULL, ((pilotFirTaps.size - 1) / 2) + 1);
lmrDelay.init(NULL, ((pilotFirTaps.size - 1) / 2) + 1);
audioFirTaps = taps::lowPass(15000.0, 4000.0, _samplerate);
@ -82,8 +82,8 @@ namespace dsp::demod {
pilotFirTaps = taps::bandPass<complex_t>(18750.0, 19250.0, 3000.0, samplerate, true);
pilotFir.setTaps(pilotFirTaps);
pilotPLL.setFrequencyLimits(math::freqToOmega(18750.0, _samplerate), math::freqToOmega(19250.0, _samplerate));
pilotPLL.setInitialFreq(math::freqToOmega(19000.0, _samplerate));
pilotPLL.setFrequencyLimits(math::hzToRads(18750.0, _samplerate), math::hzToRads(19250.0, _samplerate));
pilotPLL.setInitialFreq(math::hzToRads(19000.0, _samplerate));
lprDelay.setDelay(((pilotFirTaps.size - 1) / 2) + 1);
lmrDelay.setDelay(((pilotFirTaps.size - 1) / 2) + 1);

View File

@ -1,8 +1,8 @@
#pragma once
#include "../processor.h"
#include "../math/fast_atan2.h"
#include "../math/freq_to_omega.h"
#include "../math/norm_phase_diff.h"
#include "../math/hz_to_rads.h"
#include "../math/normalize_phase.h"
namespace dsp::demod {
class Quadrature : public Processor<complex_t, float> {
@ -21,7 +21,7 @@ namespace dsp::demod {
}
virtual void init(stream<complex_t>* in, double deviation, double samplerate) {
init(in, math::freqToOmega(deviation, samplerate));
init(in, math::hzToRads(deviation, samplerate));
}
void setDeviation(double deviation) {
@ -33,13 +33,13 @@ namespace dsp::demod {
void setDeviation(double deviation, double samplerate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
_invDeviation = 1.0 / math::freqToOmega(deviation, samplerate);
_invDeviation = 1.0 / math::hzToRads(deviation, samplerate);
}
inline int process(int count, complex_t* in, float* out) {
for (int i = 0; i < count; i++) {
float cphase = in[i].phase();
out[i] = math::normPhaseDiff(cphase - phase) * _invDeviation;
out[i] = math::normalizePhase(cphase - phase) * _invDeviation;
phase = cphase;
}
return count;

View File

@ -5,10 +5,16 @@ namespace dsp::loop {
class CarrierTrackingPLL : public PLL {
using base_type = PLL;
public:
CarrierTrackingPLL() {}
CarrierTrackingPLL(stream<complex_t>* in, double bandwidth, double initPhase = 0.0, double initFreq = 0.0, double minFreq = -FL_M_PI, double maxFreq = FL_M_PI) {
base_type::init(in, bandwidth, initFreq, initPhase, minFreq, maxFreq);
}
inline int process(int count, complex_t* in, complex_t* out) {
for (int i = 0; i < count; i++) {
out[i] = in[i] * math::phasor(-pcl.phase);
pcl.advance(math::normPhaseDiff(in[i].phase() - pcl.phase));
pcl.advance(math::normalizePhase(in[i].phase() - pcl.phase));
}
return count;
}

View File

@ -8,6 +8,12 @@ namespace dsp::loop {
static_assert(ORDER == 2 || ORDER == 4 || ORDER == 8, "Invalid costas order");
using base_type = PLL;
public:
Costas() {}
Costas(stream<complex_t>* in, double bandwidth, double initPhase = 0.0, double initFreq = 0.0, double minFreq = -FL_M_PI, double maxFreq = FL_M_PI) {
base_type::init(in, bandwidth, initFreq, initPhase, minFreq, maxFreq);
}
inline int process(int count, complex_t* in, complex_t* out) {
for (int i = 0; i < count; i++) {
out[i] = in[i] * math::phasor(-pcl.phase);

View File

@ -1,6 +1,6 @@
#pragma once
#include "../processor.h"
#include "../math/norm_phase_diff.h"
#include "../math/normalize_phase.h"
#include "../math/phasor.h"
#include "phase_control_loop.h"
@ -64,7 +64,7 @@ namespace dsp::loop {
virtual inline int process(int count, complex_t* in, complex_t* out) {
for (int i = 0; i < count; i++) {
out[i] = math::phasor(pcl.phase);
pcl.advance(math::normPhaseDiff(in[i].phase() - pcl.phase));
pcl.advance(math::normalizePhase(in[i].phase() - pcl.phase));
}
return count;
}

View File

@ -3,7 +3,7 @@
#include "constants.h"
namespace dsp::math {
inline double freqToOmega(double freq, double samplerate) {
inline double hzToRads(double freq, double samplerate) {
return 2.0 * DB_M_PI * (freq / samplerate);
}
}

View File

@ -3,7 +3,7 @@
namespace dsp::math {
template<class T>
T normPhaseDiff(T diff) {
T normalizePhase(T diff) {
if (diff > FL_M_PI) { diff -= 2.0f * FL_M_PI; }
else if (diff <= -FL_M_PI) { diff += 2.0f * FL_M_PI; }
return diff;

86
core/src/dsp/mod/gfsk.h Normal file
View File

@ -0,0 +1,86 @@
#pragma once
#include "../multirate/rrc_interpolator.h"
#include "quadrature.h"
namespace dsp::mod {
class GFSK : public Processor<float, complex_t> {
using base_type = Processor<float, complex_t>;
public:
GFSK() {}
GFSK(stream<float>* in, double symbolrate, double samplerate, double rrcBeta, int rrcTapCount, double deviation) {
init(in, symbolrate, samplerate, rrcBeta, rrcTapCount, deviation);
}
void init(stream<float>* in, double symbolrate, double samplerate, double rrcBeta, int rrcTapCount, double deviation) {
_samplerate = samplerate;
_deviation = deviation;
interp.init(NULL, symbolrate, _samplerate, rrcBeta, rrcTapCount);
mod.init(NULL, _deviation, _samplerate);
base_type::init(in);
}
void setRates(double symbolrate, double samplerate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_samplerate = samplerate;
interp.setRates(symbolrate, _samplerate);
mod.setDeviation(_deviation, _samplerate);
base_type::tempStart();
}
void setRRCParams(double rrcBeta, int rrcTapCount) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
interp.setRRCParam(rrcBeta, rrcTapCount);
base_type::tempStart();
}
void setDeviation(double deviation) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
_deviation = deviation;
mod.setDeviation(_deviation, _samplerate);
}
void reset() {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
interp.reset();
mod.reset();
base_type::tempStart();
}
inline int process(int count, const float* in, complex_t* out) {
count = interp.process(count, in, interp.out.writeBuf);
mod.process(count, interp.out.writeBuf, out);
return count;
}
int run() {
int count = base_type::_in->read();
if (count < 0) { return -1; }
int outCount = process(count, base_type::_in->readBuf, base_type::out.writeBuf);
// Swap if some data was generated
base_type::_in->flush();
if (outCount) {
if (!base_type::out.swap(outCount)) { return -1; }
}
return outCount;
}
private:
double _samplerate;
double _deviation;
multirate::RRCInterpolator<float> interp;
Quadrature mod;
};
}

6
core/src/dsp/mod/psk.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include "../multirate/rrc_interpolator.h"
namespace dsp::mod {
typedef multirate::RRCInterpolator<complex_t> PSK;
}

View File

@ -0,0 +1,67 @@
#pragma once
#include "../processor.h"
#include "../math/phasor.h"
#include "../math/normalize_phase.h"
#include "../math/hz_to_rads.h"
namespace dsp::mod {
class Quadrature : Processor<float, complex_t> {
using base_type = Processor<float, complex_t>;
public:
Quadrature() {}
Quadrature(stream<float>* in, double deviation) { init(in, deviation); }
Quadrature(stream<float>* in, double deviation, double samplerate) { init(in, deviation, samplerate); }
void init(stream<float>* in, double deviation) {
_deviation = deviation;
base_type::init(in);
}
void init(stream<float>* in, double deviation, double samplerate) {
init(in, math::hzToRads(deviation, samplerate));
}
void setDeviation(double deviation) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
_deviation = deviation;
}
void setDeviation(double deviation, double samplerate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
_deviation = math::hzToRads(deviation, samplerate);
}
void reset() {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
phase = 0.0f;
}
inline int process(int count, const float* in, complex_t* out) {
for (int i = 0; i < count; i++) {
phase = math::normalizePhase(phase + (_deviation * in[i]));
out[i] = math::phasor(phase);
}
return count;
}
virtual int run() {
int count = base_type::_in->read();
if (count < 0) { return -1; }
process(count, base_type::_in->readBuf, base_type::out.writeBuf);
base_type::_in->flush();
if (!base_type::out.swap(count)) { return -1; }
return count;
}
private:
float _deviation;
float phase = 0.0f;
};
}

View File

@ -69,6 +69,16 @@ namespace dsp::multirate {
base_type::tempStart();
}
void setRates(double inSamplerate, double outSamplerate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_inSamplerate = inSamplerate;
_outSamplerate = outSamplerate;
reconfigure();
base_type::tempStart();
}
inline int process(int count, const T* in, T* out) {
switch(mode) {
case Mode::BOTH:

View File

@ -0,0 +1,103 @@
#pragma once
#include "../multirate/polyphase_resampler.h"
#include "../taps/root_raised_cosine.h"
#include <numeric>
namespace dsp::multirate {
template <class T>
class RRCInterpolator : public Processor<T, T> {
using base_type = Processor<T, T>;
public:
RRCInterpolator() {}
RRCInterpolator(stream<T>* in, double symbolrate, double samplerate, double rrcBeta, int rrcTapCount) { init(in, symbolrate, samplerate, rrcBeta, rrcTapCount); }
void init(stream<T>* in, double symbolrate, double samplerate, double rrcBeta, int rrcTapCount) {
_symbolrate = symbolrate;
_samplerate = samplerate;
_rrcTapCount = rrcTapCount;
rrcTaps = taps::rootRaisedCosine<float>(_rrcTapCount, rrcBeta, _symbolrate, _samplerate);
resamp.init(NULL, 1, 1, rrcTaps);
resamp.out.free();
genTaps();
base_type::init(in);
}
void setRates(double symbolrate, double samplerate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_symbolrate = symbolrate;
_samplerate = samplerate;
genTaps();
base_type::tempStart();
}
void setRRCParam(double rrcBeta, int rrcTapCount) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_rrcBeta = rrcBeta;
_rrcTapCount = rrcTapCount;
genTaps();
base_type::tempStart();
}
void reset() {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
resamp.reset();
base_type::tempStart();
}
inline int process(int count, const T* in, T* out) {
return resamp.process(count, in, out);
}
int run() {
int count = base_type::_in->read();
if (count < 0) { return -1; }
int outCount = process(count, base_type::_in->readBuf, base_type::out.writeBuf);
// Swap if some data was generated
base_type::_in->flush();
if (outCount) {
if (!base_type::out.swap(outCount)) { return -1; }
}
return outCount;
}
private:
void genTaps() {
// Free current taps if they exist
taps::free(rrcTaps);
// Calculate the rational samplerate ratio
int InSR = round(_symbolrate);
int OutSR = round(_samplerate);
int gcd = std::gcd(InSR, OutSR);
int interp = OutSR / gcd;
int decim = InSR / gcd;
spdlog::warn("interp: {0}, decim: {1}", interp, decim);
// Configure resampler
double tapSamplerate = _symbolrate * (double)interp;
rrcTaps = taps::rootRaisedCosine<float>(_rrcTapCount * interp, _rrcBeta, _symbolrate, tapSamplerate);
resamp.setRatio(interp, decim, rrcTaps);
}
double _symbolrate;
double _samplerate;
double _rrcBeta;
int _rrcTapCount;
tap<float> rrcTaps;
multirate::PolyphaseResampler<T> resamp;
};
}

View File

@ -4,13 +4,13 @@
#include "estimate_tap_count.h"
#include "../window/nuttall.h"
#include "../math/phasor.h"
#include "../math/freq_to_omega.h"
#include "../math/hz_to_rads.h"
namespace dsp::taps {
template<class T>
inline tap<T> bandPass(double bandStart, double bandStop, double transWidth, double sampleRate, bool oddTapCount = false) {
assert(bandStop > bandStart);
float offsetOmega = math::freqToOmega((bandStart + bandStop) / 2.0, sampleRate);
float offsetOmega = math::hzToRads((bandStart + bandStop) / 2.0, sampleRate);
int count = estimateTapCount(transWidth, sampleRate);
if (oddTapCount && !(count % 2)) { count++; }
return windowedSinc<T>(count, (bandStop - bandStart) / 2.0, sampleRate, [=](double n, double N) {

View File

@ -1,7 +1,7 @@
#pragma once
#include "tap.h"
#include "../math/sinc.h"
#include "../math/freq_to_omega.h"
#include "../math/hz_to_rads.h"
#include "../window/nuttall.h"
namespace dsp::taps {

View File

@ -1,7 +1,7 @@
#pragma once
#include "tap.h"
#include "../math/sinc.h"
#include "../math/freq_to_omega.h"
#include "../math/hz_to_rads.h"
#include "../window/nuttall.h"
namespace dsp::taps {
@ -30,6 +30,6 @@ namespace dsp::taps {
template<class T, typename Func>
inline tap<T> windowedSinc(int count, double cutoff, double samplerate, Func window, double norm = 1.0) {
return windowedSinc<T>(count, math::freqToOmega(cutoff, samplerate), window, norm);
return windowedSinc<T>(count, math::hzToRads(cutoff, samplerate), window, norm);
}
}

View File

@ -11,7 +11,6 @@
namespace displaymenu {
bool showWaterfall;
bool fastFFT = true;
bool fullWaterfallUpdate = true;
int colorMapId = 0;
std::vector<std::string> colorMapNames;
@ -81,9 +80,6 @@ namespace displaymenu {
}
}
fastFFT = core::configManager.conf["fastFFT"];
gui::waterfall.setFastFFT(fastFFT);
fullWaterfallUpdate = core::configManager.conf["fullWaterfallUpdate"];
gui::waterfall.setFullWaterfallUpdate(fullWaterfallUpdate);
@ -129,13 +125,6 @@ namespace displaymenu {
core::configManager.release(true);
}
if (ImGui::Checkbox("Fast FFT##_sdrpp", &fastFFT)) {
gui::waterfall.setFastFFT(fastFFT);
core::configManager.acquire();
core::configManager.conf["fastFFT"] = fastFFT;
core::configManager.release(true);
}
if (ImGui::Checkbox("Full Waterfall Update##_sdrpp", &fullWaterfallUpdate)) {
gui::waterfall.setFullWaterfallUpdate(fullWaterfallUpdate);
core::configManager.acquire();

View File

@ -570,11 +570,6 @@ namespace ImGui {
return true;
}
void WaterFall::setFastFFT(bool fastFFT) {
std::lock_guard<std::recursive_mutex> lck(buf_mtx);
_fastFFT = fastFFT;
}
void WaterFall::updateWaterfallFb() {
if (!waterfallVisible || rawFFTs == NULL) {
return;
@ -591,7 +586,7 @@ namespace ImGui {
for (int i = 0; i < count; i++) {
drawDataSize = (viewBandwidth / wholeBandwidth) * rawFFTSize;
drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[((i + currentFFTLine) % waterfallHeight) * rawFFTSize], tempData, _fastFFT);
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[((i + currentFFTLine) % waterfallHeight) * rawFFTSize], tempData);
for (int j = 0; j < dataWidth; j++) {
pixel = (std::clamp<float>(tempData[j], waterfallMin, waterfallMax) - waterfallMin) / dataRange;
waterfallFb[(i * dataWidth) + j] = waterfallPallet[(int)(pixel * (WATERFALL_RESOLUTION - 1))];
@ -861,18 +856,8 @@ namespace ImGui {
int drawDataSize = (viewBandwidth / wholeBandwidth) * rawFFTSize;
int drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
// If in fast mode, apply IIR filtering
float* buf = &rawFFTs[currentFFTLine * rawFFTSize];
if (_fastFFT) {
float last = buf[0];
for (int i = 0; i < rawFFTSize; i++) {
last = (buf[i] * 0.1f) + (last * 0.9f);
buf[i] = last;
}
}
if (waterfallVisible) {
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[currentFFTLine * rawFFTSize], latestFFT, _fastFFT);
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[currentFFTLine * rawFFTSize], latestFFT);
memmove(&waterfallFb[dataWidth], waterfallFb, dataWidth * (waterfallHeight - 1) * sizeof(uint32_t));
float pixel;
float dataRange = waterfallMax - waterfallMin;
@ -884,7 +869,7 @@ namespace ImGui {
waterfallUpdate = true;
}
else {
doZoom(drawDataStart, drawDataSize, dataWidth, rawFFTs, latestFFT, _fastFFT);
doZoom(drawDataStart, drawDataSize, dataWidth, rawFFTs, latestFFT);
fftLines = 1;
}

View File

@ -90,7 +90,7 @@ namespace ImGui {
float* getFFTBuffer();
void pushFFT();
inline void doZoom(int offset, int width, int outWidth, float* data, float* out, bool fast) {
inline void doZoom(int offset, int width, int outWidth, float* data, float* out) {
// NOTE: REMOVE THAT SHIT, IT'S JUST A HACKY FIX
if (offset < 0) {
offset = 0;
@ -100,28 +100,20 @@ namespace ImGui {
}
float factor = (float)width / (float)outWidth;
if (fast) {
for (int i = 0; i < outWidth; i++) {
out[i] = data[(int)(offset + ((float)i * factor))];
}
}
else {
float sFactor = ceilf(factor);
float uFactor;
float id = offset;
float maxVal;
int sId;
for (int i = 0; i < outWidth; i++) {
maxVal = -INFINITY;
sId = (int)id;
uFactor = (sId + sFactor > rawFFTSize) ? sFactor - ((sId + sFactor) - rawFFTSize) : sFactor;
for (int j = 0; j < uFactor; j++) {
if (data[sId + j] > maxVal) { maxVal = data[sId + j]; }
}
out[i] = maxVal;
id += factor;
float sFactor = ceilf(factor);
float uFactor;
float id = offset;
float maxVal;
int sId;
for (int i = 0; i < outWidth; i++) {
maxVal = -INFINITY;
sId = (int)id;
uFactor = (sId + sFactor > rawFFTSize) ? sFactor - ((sId + sFactor) - rawFFTSize) : sFactor;
for (int j = 0; j < uFactor; j++) {
if (data[sId + j] > maxVal) { maxVal = data[sId + j]; }
}
out[i] = maxVal;
id += factor;
}
}
@ -170,8 +162,6 @@ namespace ImGui {
void setRawFFTSize(int size);
void setFastFFT(bool fastFFT);
void setFullWaterfallUpdate(bool fullUpdate);
void setBandPlanPos(int pos);
@ -328,7 +318,6 @@ namespace ImGui {
bool waterfallVisible = true;
bool bandplanVisible = false;
bool _fastFFT = true;
bool _fullUpdate = true;
int bandPlanPos = BANDPLAN_POS_BOTTOM;

View File

@ -39,10 +39,10 @@ namespace dsp::loop {
const float PHASE4 = -0.29067248091319986;
float phase = val.phase();
float dp1 = math::normPhaseDiff(phase - PHASE1);
float dp2 = math::normPhaseDiff(phase - PHASE2);
float dp3 = math::normPhaseDiff(phase - PHASE3);
float dp4 = math::normPhaseDiff(phase - PHASE4);
float dp1 = math::normalizePhase(phase - PHASE1);
float dp2 = math::normalizePhase(phase - PHASE2);
float dp3 = math::normalizePhase(phase - PHASE3);
float dp4 = math::normalizePhase(phase - PHASE4);
float lowest = dp1;
if (fabsf(dp2) < fabsf(lowest)) { lowest = dp2; }
if (fabsf(dp3) < fabsf(lowest)) { lowest = dp3; }

View File

@ -112,6 +112,7 @@ public:
}
~RadioModule() {
core::modComManager.unregisterInterface(name);
gui::menu.removeEntry(name);
stream.stop();
if (enabled) {