mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-07-01 06:37:51 +02:00
More DSP cleanup + Remove FastFFT option because it should never be used
This commit is contained in:
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
86
core/src/dsp/mod/gfsk.h
Normal 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
6
core/src/dsp/mod/psk.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "../multirate/rrc_interpolator.h"
|
||||
|
||||
namespace dsp::mod {
|
||||
typedef multirate::RRCInterpolator<complex_t> PSK;
|
||||
}
|
67
core/src/dsp/mod/quadrature.h
Normal file
67
core/src/dsp/mod/quadrature.h
Normal 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;
|
||||
};
|
||||
}
|
@ -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:
|
||||
|
103
core/src/dsp/multirate/rrc_interpolator.h
Normal file
103
core/src/dsp/multirate/rrc_interpolator.h
Normal 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;
|
||||
|
||||
};
|
||||
}
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user