mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-06-26 04:17:50 +02:00
Fixed some stuff
This commit is contained in:
@ -47,6 +47,65 @@ namespace dsp {
|
||||
|
||||
};
|
||||
|
||||
class ChannelsToStereo : public generic_block<ChannelsToStereo> {
|
||||
public:
|
||||
ChannelsToStereo() {}
|
||||
|
||||
ChannelsToStereo(stream<float>* in_left, stream<float>* in_right) { init(in_left, in_right); }
|
||||
|
||||
~ChannelsToStereo() { generic_block<ChannelsToStereo>::stop(); }
|
||||
|
||||
void init(stream<float>* in_left, stream<float>* in_right) {
|
||||
_in_left = in_left;
|
||||
_in_right = in_right;
|
||||
generic_block<ChannelsToStereo>::registerInput(_in_left);
|
||||
generic_block<ChannelsToStereo>::registerInput(_in_right);
|
||||
generic_block<ChannelsToStereo>::registerOutput(&out);
|
||||
}
|
||||
|
||||
void setInput(stream<float>* in_left, stream<float>* in_right) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<ChannelsToStereo>::ctrlMtx);
|
||||
generic_block<ChannelsToStereo>::tempStop();
|
||||
generic_block<ChannelsToStereo>::unregisterInput(_in_left);
|
||||
generic_block<ChannelsToStereo>::unregisterInput(_in_right);
|
||||
_in_left = in_left;
|
||||
_in_right = in_right;
|
||||
generic_block<ChannelsToStereo>::registerInput(_in_left);
|
||||
generic_block<ChannelsToStereo>::registerInput(_in_right);
|
||||
generic_block<ChannelsToStereo>::tempStart();
|
||||
}
|
||||
|
||||
int run() {
|
||||
count_l = _in_left->read();
|
||||
if (count_l < 0) { return -1; }
|
||||
count_r = _in_right->read();
|
||||
if (count_r < 0) { return -1; }
|
||||
|
||||
if (count_l != count_r) {
|
||||
spdlog::warn("ChannelsToStereo block size missmatch");
|
||||
}
|
||||
|
||||
for (int i = 0; i < count_l; i++) {
|
||||
out.writeBuf[i].l = _in_left->readBuf[i];
|
||||
out.writeBuf[i].r = _in_right->readBuf[i];
|
||||
}
|
||||
|
||||
_in_left->flush();
|
||||
_in_right->flush();
|
||||
if (!out.swap(count_l)) { return -1; }
|
||||
return count_l;
|
||||
}
|
||||
|
||||
stream<stereo_t> out;
|
||||
|
||||
private:
|
||||
int count_l;
|
||||
int count_r;
|
||||
stream<float>* _in_left;
|
||||
stream<float>* _in_right;
|
||||
|
||||
};
|
||||
|
||||
class StereoToMono : public generic_block<StereoToMono> {
|
||||
public:
|
||||
StereoToMono() {}
|
||||
@ -90,4 +149,52 @@ namespace dsp {
|
||||
stream<stereo_t>* _in;
|
||||
|
||||
};
|
||||
|
||||
class StereoToChannels : public generic_block<StereoToChannels> {
|
||||
public:
|
||||
StereoToChannels() {}
|
||||
|
||||
StereoToChannels(stream<stereo_t>* in) { init(in); }
|
||||
|
||||
~StereoToChannels() { generic_block<StereoToChannels>::stop(); }
|
||||
|
||||
void init(stream<stereo_t>* in) {
|
||||
_in = in;
|
||||
generic_block<StereoToChannels>::registerInput(_in);
|
||||
generic_block<StereoToChannels>::registerOutput(&out_left);
|
||||
generic_block<StereoToChannels>::registerOutput(&out_right);
|
||||
}
|
||||
|
||||
void setInput(stream<stereo_t>* in) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<StereoToChannels>::ctrlMtx);
|
||||
generic_block<StereoToChannels>::tempStop();
|
||||
generic_block<StereoToChannels>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<StereoToChannels>::registerInput(_in);
|
||||
generic_block<StereoToChannels>::tempStart();
|
||||
}
|
||||
|
||||
int run() {
|
||||
count = _in->read();
|
||||
if (count < 0) { return -1; }
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
out_left.writeBuf[i] = _in->readBuf[i].l;
|
||||
out_right.writeBuf[i] = _in->readBuf[i].r;
|
||||
}
|
||||
|
||||
_in->flush();
|
||||
if (!out_left.swap(count)) { return -1; }
|
||||
if (!out_right.swap(count)) { return -1; }
|
||||
return count;
|
||||
}
|
||||
|
||||
stream<float> out_left;
|
||||
stream<float> out_right;
|
||||
|
||||
private:
|
||||
int count;
|
||||
stream<stereo_t>* _in;
|
||||
|
||||
};
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include <dsp/block.h>
|
||||
#include <volk/volk.h>
|
||||
#include <dsp/filter.h>
|
||||
#include <dsp/processing.h>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
@ -26,6 +28,86 @@ inline float fast_arctan2(float y, float x) {
|
||||
}
|
||||
|
||||
namespace dsp {
|
||||
class FloatFMDemod : public generic_block<FloatFMDemod> {
|
||||
public:
|
||||
FloatFMDemod() {}
|
||||
|
||||
FloatFMDemod(stream<complex_t>* in, float sampleRate, float deviation) { init(in, sampleRate, deviation); }
|
||||
|
||||
~FloatFMDemod() { generic_block<FloatFMDemod>::stop(); }
|
||||
|
||||
void init(stream<complex_t>* in, float sampleRate, float deviation) {
|
||||
_in = in;
|
||||
_sampleRate = sampleRate;
|
||||
_deviation = deviation;
|
||||
phasorSpeed = (2 * FL_M_PI) / (_sampleRate / _deviation);
|
||||
generic_block<FloatFMDemod>::registerInput(_in);
|
||||
generic_block<FloatFMDemod>::registerOutput(&out);
|
||||
}
|
||||
|
||||
void setInput(stream<complex_t>* in) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<FloatFMDemod>::ctrlMtx);
|
||||
generic_block<FloatFMDemod>::tempStop();
|
||||
generic_block<FloatFMDemod>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<FloatFMDemod>::registerInput(_in);
|
||||
generic_block<FloatFMDemod>::tempStart();
|
||||
}
|
||||
|
||||
void setSampleRate(float sampleRate) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<FloatFMDemod>::ctrlMtx);
|
||||
generic_block<FloatFMDemod>::tempStop();
|
||||
_sampleRate = sampleRate;
|
||||
phasorSpeed = (2 * FL_M_PI) / (_sampleRate / _deviation);
|
||||
generic_block<FloatFMDemod>::tempStart();
|
||||
}
|
||||
|
||||
float getSampleRate() {
|
||||
return _sampleRate;
|
||||
}
|
||||
|
||||
void setDeviation(float deviation) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<FloatFMDemod>::ctrlMtx);
|
||||
generic_block<FloatFMDemod>::tempStop();
|
||||
_deviation = deviation;
|
||||
phasorSpeed = (2 * FL_M_PI) / (_sampleRate / _deviation);
|
||||
generic_block<FloatFMDemod>::tempStart();
|
||||
}
|
||||
|
||||
float getDeviation() {
|
||||
return _deviation;
|
||||
}
|
||||
|
||||
int run() {
|
||||
count = _in->read();
|
||||
if (count < 0) { return -1; }
|
||||
|
||||
// This is somehow faster than volk...
|
||||
|
||||
float diff, currentPhase;
|
||||
for (int i = 0; i < count; i++) {
|
||||
currentPhase = fast_arctan2(_in->readBuf[i].i, _in->readBuf[i].q);
|
||||
diff = currentPhase - phase;
|
||||
if (diff > 3.1415926535f) { diff -= 2 * 3.1415926535f; }
|
||||
else if (diff <= -3.1415926535f) { diff += 2 * 3.1415926535f; }
|
||||
out.writeBuf[i] = diff / phasorSpeed;
|
||||
phase = currentPhase;
|
||||
}
|
||||
|
||||
_in->flush();
|
||||
if (!out.swap(count)) { return -1; }
|
||||
return count;
|
||||
}
|
||||
|
||||
stream<float> out;
|
||||
|
||||
private:
|
||||
int count;
|
||||
float phase, phasorSpeed, _sampleRate, _deviation;
|
||||
stream<complex_t>* _in;
|
||||
|
||||
};
|
||||
|
||||
class FMDemod : public generic_block<FMDemod> {
|
||||
public:
|
||||
FMDemod() {}
|
||||
@ -88,7 +170,8 @@ namespace dsp {
|
||||
diff = currentPhase - phase;
|
||||
if (diff > 3.1415926535f) { diff -= 2 * 3.1415926535f; }
|
||||
else if (diff <= -3.1415926535f) { diff += 2 * 3.1415926535f; }
|
||||
out.writeBuf[i] = diff / phasorSpeed;
|
||||
out.writeBuf[i].l = diff / phasorSpeed;
|
||||
out.writeBuf[i].r = diff / phasorSpeed;
|
||||
phase = currentPhase;
|
||||
}
|
||||
|
||||
@ -97,7 +180,7 @@ namespace dsp {
|
||||
return count;
|
||||
}
|
||||
|
||||
stream<float> out;
|
||||
stream<stereo_t> out;
|
||||
|
||||
private:
|
||||
int count;
|
||||
@ -106,6 +189,149 @@ namespace dsp {
|
||||
|
||||
};
|
||||
|
||||
class StereoFMDemod : public generic_block<StereoFMDemod> {
|
||||
public:
|
||||
StereoFMDemod() {}
|
||||
|
||||
StereoFMDemod(stream<complex_t>* in, float sampleRate, float deviation) { init(in, sampleRate, deviation); }
|
||||
|
||||
~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> {
|
||||
public:
|
||||
AMDemod() {}
|
||||
|
@ -92,11 +92,11 @@ namespace dsp {
|
||||
public:
|
||||
BFMDeemp() {}
|
||||
|
||||
BFMDeemp(stream<float>* in, float sampleRate, float tau) { init(in, sampleRate, tau); }
|
||||
BFMDeemp(stream<stereo_t>* in, float sampleRate, float tau) { init(in, sampleRate, tau); }
|
||||
|
||||
~BFMDeemp() { generic_block<BFMDeemp>::stop(); }
|
||||
|
||||
void init(stream<float>* in, float sampleRate, float tau) {
|
||||
void init(stream<stereo_t>* in, float sampleRate, float tau) {
|
||||
_in = in;
|
||||
_sampleRate = sampleRate;
|
||||
_tau = tau;
|
||||
@ -106,7 +106,7 @@ namespace dsp {
|
||||
generic_block<BFMDeemp>::registerOutput(&out);
|
||||
}
|
||||
|
||||
void setInput(stream<float>* in) {
|
||||
void setInput(stream<stereo_t>* in) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<BFMDeemp>::ctrlMtx);
|
||||
generic_block<BFMDeemp>::tempStop();
|
||||
generic_block<BFMDeemp>::unregisterInput(_in);
|
||||
@ -132,20 +132,26 @@ namespace dsp {
|
||||
if (count < 0) { return -1; }
|
||||
|
||||
if (bypass) {
|
||||
memcpy(out.writeBuf, _in->readBuf, count * sizeof(float));
|
||||
memcpy(out.writeBuf, _in->readBuf, count * sizeof(stereo_t));
|
||||
_in->flush();
|
||||
if (!out.swap(count)) { return -1; }
|
||||
return count;
|
||||
}
|
||||
|
||||
if (isnan(lastOut)) {
|
||||
lastOut = 0.0f;
|
||||
if (isnan(lastOutL)) {
|
||||
lastOutL = 0.0f;
|
||||
}
|
||||
out.writeBuf[0] = (alpha * _in->readBuf[0]) + ((1-alpha) * lastOut);
|
||||
if (isnan(lastOutR)) {
|
||||
lastOutR = 0.0f;
|
||||
}
|
||||
out.writeBuf[0].l = (alpha * _in->readBuf[0].l) + ((1-alpha) * lastOutL);
|
||||
out.writeBuf[0].r = (alpha * _in->readBuf[0].r) + ((1-alpha) * lastOutR);
|
||||
for (int i = 1; i < count; i++) {
|
||||
out.writeBuf[i] = (alpha * _in->readBuf[i]) + ((1 - alpha) * out.writeBuf[i - 1]);
|
||||
out.writeBuf[i].l = (alpha * _in->readBuf[i].l) + ((1 - alpha) * out.writeBuf[i - 1].l);
|
||||
out.writeBuf[i].r = (alpha * _in->readBuf[i].r) + ((1 - alpha) * out.writeBuf[i - 1].r);
|
||||
}
|
||||
lastOut = out.writeBuf[count - 1];
|
||||
lastOutL = out.writeBuf[count - 1].l;
|
||||
lastOutR = out.writeBuf[count - 1].r;
|
||||
|
||||
_in->flush();
|
||||
if (!out.swap(count)) { return -1; }
|
||||
@ -154,15 +160,16 @@ namespace dsp {
|
||||
|
||||
bool bypass = false;
|
||||
|
||||
stream<float> out;
|
||||
stream<stereo_t> out;
|
||||
|
||||
private:
|
||||
int count;
|
||||
float lastOut = 0.0f;
|
||||
float lastOutL = 0.0f;
|
||||
float lastOutR = 0.0f;
|
||||
float alpha;
|
||||
float _tau;
|
||||
float _sampleRate;
|
||||
stream<float>* _in;
|
||||
stream<stereo_t>* _in;
|
||||
|
||||
};
|
||||
}
|
@ -10,14 +10,14 @@ namespace dsp {
|
||||
|
||||
Add(stream<T>* a, stream<T>* b) { init(a, b); }
|
||||
|
||||
~Add() { generic_block<Add>::stop(); }
|
||||
~Add() { generic_block<Add<T>>::stop(); }
|
||||
|
||||
void init(stream<T>* a, stream<T>* b) {
|
||||
_a = a;
|
||||
_b = b;
|
||||
generic_block<Add>::registerInput(a);
|
||||
generic_block<Add>::registerInput(b);
|
||||
generic_block<Add>::registerOutput(&out);
|
||||
generic_block<Add<T>>::registerInput(a);
|
||||
generic_block<Add<T>>::registerInput(b);
|
||||
generic_block<Add<T>>::registerOutput(&out);
|
||||
}
|
||||
|
||||
int run() {
|
||||
@ -32,7 +32,57 @@ namespace dsp {
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<T, complex_t> || std::is_same_v<T, stereo_t>) {
|
||||
volk_32fc_x2_add_32fc(out.writeBuf, _a->readBuf, _b->readBuf, a_count);
|
||||
volk_32fc_x2_add_32fc((lv_32fc_t*)out.writeBuf, (lv_32fc_t*)_a->readBuf, (lv_32fc_t*)_b->readBuf, a_count);
|
||||
}
|
||||
else {
|
||||
volk_32f_x2_add_32f(out.writeBuf, _a->readBuf, _b->readBuf, a_count);
|
||||
}
|
||||
|
||||
_a->flush();
|
||||
_b->flush();
|
||||
if (!out.swap(a_count)) { return -1; }
|
||||
return a_count;
|
||||
}
|
||||
|
||||
stream<T> out;
|
||||
|
||||
private:
|
||||
int a_count, b_count;
|
||||
stream<T>* _a;
|
||||
stream<T>* _b;
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Substract : public generic_block<Substract<T>> {
|
||||
public:
|
||||
Substract() {}
|
||||
|
||||
Substract(stream<T>* a, stream<T>* b) { init(a, b); }
|
||||
|
||||
~Substract() { generic_block<Substract<T>>::stop(); }
|
||||
|
||||
void init(stream<T>* a, stream<T>* b) {
|
||||
_a = a;
|
||||
_b = b;
|
||||
generic_block<Substract<T>>::registerInput(a);
|
||||
generic_block<Substract<T>>::registerInput(b);
|
||||
generic_block<Substract<T>>::registerOutput(&out);
|
||||
}
|
||||
|
||||
int run() {
|
||||
a_count = _a->read();
|
||||
if (a_count < 0) { return -1; }
|
||||
b_count = _b->read();
|
||||
if (b_count < 0) { return -1; }
|
||||
if (a_count != b_count) {
|
||||
_a->flush();
|
||||
_b->flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<T, complex_t> || std::is_same_v<T, stereo_t>) {
|
||||
volk_32f_x2_subtract_32f((float*)out.writeBuf, (float*)_a->readBuf, (float*)_b->readBuf, a_count * 2);
|
||||
}
|
||||
else {
|
||||
volk_32f_x2_add_32f(out.writeBuf, _a->readBuf, _b->readBuf, a_count);
|
||||
|
@ -44,7 +44,7 @@ namespace dsp {
|
||||
_in->flush();
|
||||
|
||||
float _lvlL = 10.0f * logf(maxL);
|
||||
float _lvlR = 10.0f * logf(maxL);
|
||||
float _lvlR = 10.0f * logf(maxR);
|
||||
|
||||
// Update max values
|
||||
{
|
||||
|
@ -297,4 +297,72 @@ namespace dsp {
|
||||
stream<complex_t>* _in;
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Packer : public generic_block<Packer<T>> {
|
||||
public:
|
||||
Packer() {}
|
||||
|
||||
Packer(stream<T>* in, int count) { init(in, count); }
|
||||
|
||||
~Packer() {
|
||||
generic_block<Packer<T>>::stop();
|
||||
}
|
||||
|
||||
void init(stream<T>* in, int count) {
|
||||
_in = in;
|
||||
samples = count;
|
||||
generic_block<Packer<T>>::registerInput(_in);
|
||||
generic_block<Packer<T>>::registerOutput(&out);
|
||||
}
|
||||
|
||||
void setInput(stream<T>* in) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<Packer<T>>::ctrlMtx);
|
||||
generic_block<Packer<T>>::tempStop();
|
||||
generic_block<Packer<T>>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<Packer<T>>::registerInput(_in);
|
||||
generic_block<Packer<T>>::tempStart();
|
||||
}
|
||||
|
||||
void setSampleCount(int count) {
|
||||
std::lock_guard<std::mutex> lck(generic_block<Packer<T>>::ctrlMtx);
|
||||
generic_block<Packer<T>>::tempStop();
|
||||
samples = count;
|
||||
generic_block<Packer<T>>::tempStart();
|
||||
}
|
||||
|
||||
int run() {
|
||||
count = _in->read();
|
||||
if (count < 0) {
|
||||
read = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
out.writeBuf[read++] = _in->readBuf[i];
|
||||
if (read >= samples) {
|
||||
read = 0;
|
||||
if (!out.swap(samples)) {
|
||||
_in->flush();
|
||||
read = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_in->flush();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
stream<T> out;
|
||||
|
||||
private:
|
||||
int count;
|
||||
int samples = 1;
|
||||
int read = 0;
|
||||
stream<T>* _in;
|
||||
|
||||
};
|
||||
}
|
@ -117,7 +117,7 @@ namespace dsp {
|
||||
outIndex++;
|
||||
}
|
||||
}
|
||||
if constexpr (std::is_same_v<T, complex_t>) {
|
||||
if constexpr (std::is_same_v<T, complex_t> || std::is_same_v<T, stereo_t>) {
|
||||
for (int i = 0; outIndex < outCount; i += _decim) {
|
||||
int phase = i % _interp;
|
||||
volk_32fc_32f_dot_prod_32fc((lv_32fc_t*)&out.writeBuf[outIndex], (lv_32fc_t*)&buffer[(i / _interp)], tapPhases[phase], tapsPerPhase);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <dsp/block.h>
|
||||
#include <dsp/types.h>
|
||||
|
||||
namespace dsp {
|
||||
namespace filter_window {
|
||||
@ -9,6 +10,12 @@ namespace dsp {
|
||||
virtual void createTaps(float* taps, int tapCount, float factor = 1.0f) {}
|
||||
};
|
||||
|
||||
class generic_complex_window {
|
||||
public:
|
||||
virtual int getTapCount() { return -1; }
|
||||
virtual void createTaps(dsp::complex_t* taps, int tapCount, float factor = 1.0f) {}
|
||||
};
|
||||
|
||||
class BlackmanWindow : public filter_window::generic_window {
|
||||
public:
|
||||
BlackmanWindow() {}
|
||||
@ -72,5 +79,145 @@ namespace dsp {
|
||||
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 BlackmanBandpassWindow : public filter_window::generic_complex_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(dsp::complex_t* 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;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
@ -61,29 +61,30 @@ double findBestRange(double bandwidth, int maxSteps) {
|
||||
}
|
||||
|
||||
void printAndScale(double freq, char* buf) {
|
||||
if (freq < 1000) {
|
||||
sprintf(buf, "%.3lf", freq);
|
||||
double freqAbs = fabs(freq);
|
||||
if (freqAbs < 1000) {
|
||||
sprintf(buf, "%.6g", freq);
|
||||
}
|
||||
else if (freq < 1000000) {
|
||||
sprintf(buf, "%.3lfK", freq / 1000.0);
|
||||
else if (freqAbs < 1000000) {
|
||||
sprintf(buf, "%.6lgK", freq / 1000.0);
|
||||
}
|
||||
else if (freq < 1000000000) {
|
||||
sprintf(buf, "%.3lfM", freq / 1000000.0);
|
||||
else if (freqAbs < 1000000000) {
|
||||
sprintf(buf, "%.6lgM", freq / 1000000.0);
|
||||
}
|
||||
else if (freq < 1000000000000) {
|
||||
sprintf(buf, "%.3lfG", freq / 1000000000.0);
|
||||
}
|
||||
for (int i = strlen(buf) - 2; i >= 0; i--) {
|
||||
if (buf[i] != '0') {
|
||||
if (buf[i] == '.') {
|
||||
i--;
|
||||
}
|
||||
char scale = buf[strlen(buf) - 1];
|
||||
buf[i + 1] = scale;
|
||||
buf[i + 2] = 0;
|
||||
return;
|
||||
}
|
||||
else if (freqAbs < 1000000000000) {
|
||||
sprintf(buf, "%.6lgG", freq / 1000000000.0);
|
||||
}
|
||||
// for (int i = strlen(buf) - 2; i >= 0; i--) {
|
||||
// if (buf[i] != '0') {
|
||||
// if (buf[i] == '.') {
|
||||
// i--;
|
||||
// }
|
||||
// char scale = buf[strlen(buf) - 1];
|
||||
// buf[i + 1] = scale;
|
||||
// buf[i + 2] = 0;
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
namespace ImGui {
|
||||
|
@ -17,7 +17,7 @@ ModuleManager::Module_t ModuleManager::loadModule(std::string path) {
|
||||
#ifdef _WIN32
|
||||
mod.handle = LoadLibraryA(path.c_str());
|
||||
if (mod.handle == NULL) {
|
||||
spdlog::error("Couldn't load {0}.", path);
|
||||
spdlog::error("Couldn't load {0}. Error code: {1}", path, GetLastError());
|
||||
mod.handle = NULL;
|
||||
return mod;
|
||||
}
|
||||
|
Reference in New Issue
Block a user