mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-01-11 18:57:11 +01:00
Push before merge
This commit is contained in:
parent
098f09844b
commit
b16ab3f0c0
@ -7,6 +7,7 @@
|
|||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <dsp/pll.h>
|
#include <dsp/pll.h>
|
||||||
#include <dsp/clock_recovery.h>
|
#include <dsp/clock_recovery.h>
|
||||||
|
#include <dsp/math.h>
|
||||||
|
|
||||||
#define FAST_ATAN2_COEF1 FL_M_PI / 4.0f
|
#define FAST_ATAN2_COEF1 FL_M_PI / 4.0f
|
||||||
#define FAST_ATAN2_COEF2 3.0f * FAST_ATAN2_COEF1
|
#define FAST_ATAN2_COEF2 3.0f * FAST_ATAN2_COEF1
|
||||||
@ -186,149 +187,6 @@ namespace dsp {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class StereoFMDemod : public generic_block<StereoFMDemod> {
|
|
||||||
public:
|
|
||||||
StereoFMDemod() {}
|
|
||||||
|
|
||||||
StereoFMDemod(stream<complex_t>* in, float sampleRate, float deviation) { init(in, sampleRate, deviation); }
|
|
||||||
|
|
||||||
~StereoFMDemod() {
|
|
||||||
generic_block<StereoFMDemod>::stop();
|
|
||||||
delete[] doubledPilot;
|
|
||||||
delete[] a_minus_b;
|
|
||||||
delete[] a_out;
|
|
||||||
delete[] b_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(stream<complex_t>* in, float sampleRate, float deviation) {
|
|
||||||
_sampleRate = sampleRate;
|
|
||||||
|
|
||||||
doubledPilot = new float[STREAM_BUFFER_SIZE];
|
|
||||||
a_minus_b = new float[STREAM_BUFFER_SIZE];
|
|
||||||
a_out = new float[STREAM_BUFFER_SIZE];
|
|
||||||
b_out = new float[STREAM_BUFFER_SIZE];
|
|
||||||
|
|
||||||
fmDemod.init(in, sampleRate, deviation);
|
|
||||||
split.init(&fmDemod.out);
|
|
||||||
split.bindStream(&filterInput);
|
|
||||||
split.bindStream(&decodeInput);
|
|
||||||
|
|
||||||
// Filter init
|
|
||||||
win.init(1000, 1000, 19000, sampleRate);
|
|
||||||
filter.init(&filterInput, &win);
|
|
||||||
agc.init(&filter.out, 20.0f, sampleRate);
|
|
||||||
|
|
||||||
generic_block<StereoFMDemod>::registerInput(&decodeInput);
|
|
||||||
generic_block<StereoFMDemod>::registerOutput(&out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInput(stream<complex_t>* in) {
|
|
||||||
std::lock_guard<std::mutex> lck(generic_block<StereoFMDemod>::ctrlMtx);
|
|
||||||
generic_block<StereoFMDemod>::tempStop();
|
|
||||||
fmDemod.setInput(in);
|
|
||||||
generic_block<StereoFMDemod>::tempStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSampleRate(float sampleRate) {
|
|
||||||
std::lock_guard<std::mutex> lck(generic_block<StereoFMDemod>::ctrlMtx);
|
|
||||||
generic_block<StereoFMDemod>::tempStop();
|
|
||||||
_sampleRate = sampleRate;
|
|
||||||
fmDemod.setSampleRate(sampleRate);
|
|
||||||
win.setSampleRate(_sampleRate);
|
|
||||||
filter.updateWindow(&win);
|
|
||||||
generic_block<StereoFMDemod>::tempStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
float getSampleRate() {
|
|
||||||
return _sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDeviation(float deviation) {
|
|
||||||
std::lock_guard<std::mutex> lck(generic_block<StereoFMDemod>::ctrlMtx);
|
|
||||||
generic_block<StereoFMDemod>::tempStop();
|
|
||||||
fmDemod.setDeviation(deviation);
|
|
||||||
generic_block<StereoFMDemod>::tempStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
float getDeviation() {
|
|
||||||
return fmDemod.getDeviation();
|
|
||||||
}
|
|
||||||
|
|
||||||
int run() {
|
|
||||||
count = decodeInput.read();
|
|
||||||
if (count < 0) { return -1; }
|
|
||||||
countFilter = agc.out.read();
|
|
||||||
if (countFilter < 0) { return -1; }
|
|
||||||
|
|
||||||
volk_32f_x2_multiply_32f(doubledPilot, agc.out.readBuf, agc.out.readBuf, count);
|
|
||||||
|
|
||||||
volk_32f_x2_multiply_32f(a_minus_b, decodeInput.readBuf, doubledPilot, count);
|
|
||||||
|
|
||||||
volk_32f_x2_add_32f(a_out, decodeInput.readBuf, a_minus_b, count);
|
|
||||||
volk_32f_x2_subtract_32f(b_out, decodeInput.readBuf, a_minus_b, count);
|
|
||||||
|
|
||||||
decodeInput.flush();
|
|
||||||
agc.out.flush();
|
|
||||||
|
|
||||||
volk_32f_x2_interleave_32fc((lv_32fc_t*)out.writeBuf, a_out, b_out, count);
|
|
||||||
|
|
||||||
if (!out.swap(count)) { return -1; }
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() {
|
|
||||||
std::lock_guard<std::mutex> lck(generic_block<StereoFMDemod>::ctrlMtx);
|
|
||||||
if (generic_block<StereoFMDemod>::running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
generic_block<StereoFMDemod>::running = true;
|
|
||||||
generic_block<StereoFMDemod>::doStart();
|
|
||||||
fmDemod.start();
|
|
||||||
split.start();
|
|
||||||
filter.start();
|
|
||||||
agc.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop() {
|
|
||||||
std::lock_guard<std::mutex> lck(generic_block<StereoFMDemod>::ctrlMtx);
|
|
||||||
if (!generic_block<StereoFMDemod>::running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fmDemod.stop();
|
|
||||||
split.stop();
|
|
||||||
filter.stop();
|
|
||||||
agc.stop();
|
|
||||||
generic_block<StereoFMDemod>::doStop();
|
|
||||||
generic_block<StereoFMDemod>::running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream<stereo_t> out;
|
|
||||||
|
|
||||||
private:
|
|
||||||
int count;
|
|
||||||
int countFilter;
|
|
||||||
|
|
||||||
float _sampleRate;
|
|
||||||
|
|
||||||
FloatFMDemod fmDemod;
|
|
||||||
Splitter<float> split;
|
|
||||||
|
|
||||||
// Pilot tone filtering
|
|
||||||
stream<float> filterInput;
|
|
||||||
FIR<float> filter;
|
|
||||||
filter_window::BlackmanBandpassWindow win;
|
|
||||||
AGC agc;
|
|
||||||
|
|
||||||
stream<float> decodeInput;
|
|
||||||
|
|
||||||
// Buffers
|
|
||||||
float* doubledPilot;
|
|
||||||
float* a_minus_b;
|
|
||||||
float* a_out;
|
|
||||||
float* b_out;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class AMDemod : public generic_block<AMDemod> {
|
class AMDemod : public generic_block<AMDemod> {
|
||||||
public:
|
public:
|
||||||
AMDemod() {}
|
AMDemod() {}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <dsp/interpolation_taps.h>
|
#include <dsp/interpolation_taps.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <dsp/utils/macros.h>
|
#include <dsp/utils/macros.h>
|
||||||
|
#include <dsp/math.h>
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
template <int ORDER>
|
template <int ORDER>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <dsp/math.h>
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <dsp/window.h>
|
#include <dsp/window.h>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <dsp/math.h>
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -192,11 +193,22 @@ namespace dsp {
|
|||||||
public:
|
public:
|
||||||
PowerDecimator() {}
|
PowerDecimator() {}
|
||||||
|
|
||||||
PowerDecimator(stream<complex_t>* in, unsigned int power) { init(in, power); }
|
PowerDecimator(stream<complex_t>* in, int power, int tapCount) { init(in, power, tapCount); }
|
||||||
|
|
||||||
void init(stream<complex_t>* in, unsigned int power) {
|
void init(stream<complex_t>* in, int power, int tapCount) {
|
||||||
_in = in;
|
_in = in;
|
||||||
_power = power;
|
_power = power;
|
||||||
|
_tapCount = tapCount;
|
||||||
|
|
||||||
|
// Allocate buffers
|
||||||
|
for (int i = 0; i < _power; i++) {
|
||||||
|
buffers[i] = new complex_t[STREAM_BUFFER_SIZE / (i+1)];
|
||||||
|
bufferStart[i] = &buffers[i][_tapCount - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create taps
|
||||||
|
genHalfbandTaps();
|
||||||
|
|
||||||
generic_block<PowerDecimator>::registerInput(_in);
|
generic_block<PowerDecimator>::registerInput(_in);
|
||||||
generic_block<PowerDecimator>::registerOutput(&out);
|
generic_block<PowerDecimator>::registerOutput(&out);
|
||||||
}
|
}
|
||||||
@ -221,39 +233,42 @@ namespace dsp {
|
|||||||
int count = _in->read();
|
int count = _in->read();
|
||||||
if (count < 0) { return -1; }
|
if (count < 0) { return -1; }
|
||||||
|
|
||||||
if (_power == 0) {
|
|
||||||
memcpy(out.writeBuf, _in->readBuf, count * sizeof(complex_t));
|
|
||||||
}
|
|
||||||
else if (_power == 1) {
|
|
||||||
for (int j = 0; j < count; j += 2) {
|
|
||||||
out.writeBuf[j / 2].re = (_in->readBuf[j].re + _in->readBuf[j + 1].re) * 0.5f;
|
|
||||||
out.writeBuf[j / 2].im = (_in->readBuf[j].im + _in->readBuf[j + 1].im) * 0.5f;
|
|
||||||
}
|
|
||||||
count /= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
_in->flush();
|
|
||||||
|
|
||||||
if (_power > 1) {
|
|
||||||
for (int i = 1; i < _power; i++) {
|
|
||||||
for (int j = 0; j < count; j += 2) {
|
|
||||||
out.writeBuf[j / 2].re = (_in->readBuf[j].re + _in->readBuf[j + 1].re) * 0.5f;
|
|
||||||
out.writeBuf[j / 2].im = (_in->readBuf[j].im + _in->readBuf[j + 1].im) * 0.5f;
|
|
||||||
}
|
|
||||||
count /= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!out.swap(count)) { return -1; }
|
if (!out.swap(count)) { return -1; }
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream<complex_t> out;
|
stream<complex_t> out;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int _power = 0;
|
void genHalfbandTaps() {
|
||||||
|
if (taps != NULL) { delete[] taps; }
|
||||||
|
taps = new float[_tapCount];
|
||||||
|
|
||||||
|
// Using Blackman-harris windows
|
||||||
|
int half = _tapCount / 2;
|
||||||
|
for (int i = 0; i < _tapCount; i++) {
|
||||||
|
taps[i] = sinc((FL_M_PI / 2.0f) * (i-half)) * blackmanHarrisWin(i, _tapCount - 1);
|
||||||
|
printf("%f\n", taps[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float sinc(float x) {
|
||||||
|
return ((x == 0) ? 1.0f : (sinf(x)/x)) / FL_M_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float blackmanHarrisWin(float n, float N) {
|
||||||
|
return 0.35875f - (0.48829f*cosf(2.0f*FL_M_PI*(n/N))) + (0.14128f*cosf(4.0f*FL_M_PI*(n/N))) - (0.01168f*cosf(6.0f*FL_M_PI*(n/N)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int _power = 0;
|
||||||
|
int _tapCount = 31;
|
||||||
stream<complex_t>* _in;
|
stream<complex_t>* _in;
|
||||||
|
|
||||||
|
// Buffer lists, sets max decimation to 2^32
|
||||||
|
complex_t* buffers[32];
|
||||||
|
complex_t* bufferStart[32];
|
||||||
|
|
||||||
|
float* taps = NULL;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <dsp/block.h>
|
#include <dsp/block.h>
|
||||||
|
#include <dsp/math.h>
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
class SineSource : public generic_block<SineSource> {
|
class SineSource : public generic_block<SineSource> {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <dsp/utils/math.h>
|
||||||
#define FL_M_PI 3.1415926535f
|
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
struct complex_t {
|
struct complex_t {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <dsp/block.h>
|
#include <dsp/block.h>
|
||||||
#include <dsp/types.h>
|
#include <dsp/types.h>
|
||||||
|
#include <dsp/utils/window_functions.h>
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
namespace filter_window {
|
namespace filter_window {
|
||||||
@ -50,6 +51,25 @@ namespace dsp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void createTaps(float* taps, int tapCount, float factor = 1.0f) {
|
void createTaps(float* taps, int tapCount, float factor = 1.0f) {
|
||||||
|
// // Calculate cuttoff frequency
|
||||||
|
// float omega = 2.0f * FL_M_PI * (_cutoff / _sampleRate);
|
||||||
|
// if (omega > FL_M_PI) { omega = FL_M_PI; }
|
||||||
|
|
||||||
|
// // Generate taps
|
||||||
|
// float val;
|
||||||
|
// float sum = 0.0f;
|
||||||
|
// for (int i = 0; i < tapCount; i++) {
|
||||||
|
// val = math::sinc(omega, i-(tapCount/2), FL_M_PI) * window_function::blackman(i, tapCount - 1);
|
||||||
|
// taps[i] = val;
|
||||||
|
// sum += val;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Normalize taps and multiply by supplied factor
|
||||||
|
// for (int i = 0; i < tapCount; i++) {
|
||||||
|
// taps[i] *= factor;
|
||||||
|
// taps[i] /= sum;
|
||||||
|
// }
|
||||||
|
|
||||||
float fc = _cutoff / _sampleRate;
|
float fc = _cutoff / _sampleRate;
|
||||||
if (fc > 1.0f) {
|
if (fc > 1.0f) {
|
||||||
fc = 1.0f;
|
fc = 1.0f;
|
||||||
@ -73,79 +93,8 @@ namespace dsp {
|
|||||||
float _cutoff, _transWidth, _sampleRate;
|
float _cutoff, _transWidth, _sampleRate;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BlackmanBandpassWindow : public filter_window::generic_window {
|
|
||||||
public:
|
|
||||||
BlackmanBandpassWindow() {}
|
|
||||||
BlackmanBandpassWindow(float cutoff, float transWidth, float offset, float sampleRate) { init(cutoff, transWidth, offset, sampleRate); }
|
|
||||||
|
|
||||||
void init(float cutoff, float transWidth, float offset, float sampleRate) {
|
|
||||||
_cutoff = cutoff;
|
|
||||||
_transWidth = transWidth;
|
|
||||||
_offset = offset;
|
|
||||||
_sampleRate = sampleRate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSampleRate(float sampleRate) {
|
|
||||||
_sampleRate = sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCutoff(float cutoff) {
|
|
||||||
_cutoff = cutoff;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTransWidth(float transWidth) {
|
|
||||||
_transWidth = transWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOffset(float offset) {
|
|
||||||
_offset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getTapCount() {
|
|
||||||
float fc = _cutoff / _sampleRate;
|
|
||||||
if (fc > 1.0f) {
|
|
||||||
fc = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _M = 4.0f / (_transWidth / _sampleRate);
|
|
||||||
if (_M < 4) {
|
|
||||||
_M = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_M % 2 == 0) { _M++; }
|
|
||||||
|
|
||||||
return _M;
|
|
||||||
}
|
|
||||||
|
|
||||||
void createTaps(float* taps, int tapCount, float factor = 1.0f) {
|
|
||||||
float fc = _cutoff / _sampleRate;
|
|
||||||
if (fc > 1.0f) {
|
|
||||||
fc = 1.0f;
|
|
||||||
}
|
|
||||||
float tc = tapCount;
|
|
||||||
float sum = 0.0f;
|
|
||||||
float val;
|
|
||||||
for (int i = 0; i < tapCount; i++) {
|
|
||||||
val = (sin(2.0f * FL_M_PI * fc * ((float)i - (tc / 2))) / ((float)i - (tc / 2))) *
|
|
||||||
(0.42f - (0.5f * cos(2.0f * FL_M_PI / tc)) + (0.8f * cos(4.0f * FL_M_PI / tc)));
|
|
||||||
taps[i] = val; // tapCount - i - 1
|
|
||||||
sum += val;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < tapCount; i++) {
|
|
||||||
taps[i] *= cos(2.0f * (_offset / _sampleRate) * FL_M_PI * (float)i);
|
|
||||||
taps[i] *= factor;
|
|
||||||
taps[i] /= sum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
float _cutoff, _transWidth, _sampleRate, _offset;
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class RRCTaps : public filter_window::generic_window {
|
class RRCTaps : public filter_window::generic_window {
|
||||||
public:
|
public:
|
||||||
RRCTaps() {}
|
RRCTaps() {}
|
||||||
|
@ -69,7 +69,7 @@ double freq_ranges[] = {
|
|||||||
10000000.0, 20000000.0, 25000000.0, 50000000.0
|
10000000.0, 20000000.0, 25000000.0, 50000000.0
|
||||||
};
|
};
|
||||||
|
|
||||||
double findBestRange(double bandwidth, int maxSteps) {
|
inline double findBestRange(double bandwidth, int maxSteps) {
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
if (bandwidth / freq_ranges[i] < (double)maxSteps) {
|
if (bandwidth / freq_ranges[i] < (double)maxSteps) {
|
||||||
return freq_ranges[i];
|
return freq_ranges[i];
|
||||||
@ -78,7 +78,7 @@ double findBestRange(double bandwidth, int maxSteps) {
|
|||||||
return 50000000.0;
|
return 50000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAndScale(double freq, char* buf) {
|
inline void printAndScale(double freq, char* buf) {
|
||||||
double freqAbs = fabs(freq);
|
double freqAbs = fabs(freq);
|
||||||
if (freqAbs < 1000) {
|
if (freqAbs < 1000) {
|
||||||
sprintf(buf, "%.6g", freq);
|
sprintf(buf, "%.6g", freq);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <signal_path/signal_path.h>
|
#include <signal_path/signal_path.h>
|
||||||
#include <core.h>
|
#include <core.h>
|
||||||
#include <gui/style.h>
|
#include <gui/style.h>
|
||||||
|
#include <dsp/math.h>
|
||||||
#include <openFX3.h>
|
#include <openFX3.h>
|
||||||
#include <Si5351.h>
|
#include <Si5351.h>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user