mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-07-09 10:35:21 +02:00
lots o shit
This commit is contained in:
@ -1,278 +0,0 @@
|
||||
#include <signal_path/dsp.h>
|
||||
#include <core.h>
|
||||
|
||||
SignalPath::SignalPath() {
|
||||
}
|
||||
|
||||
void SignalPath::init(uint64_t sampleRate, int fftRate, int fftSize, dsp::stream<dsp::complex_t>* input, dsp::complex_t* fftBuffer, void fftHandler(dsp::complex_t*, int, void*), void* fftHandlerCtx) {
|
||||
this->sampleRate = sampleRate;
|
||||
this->sourceSampleRate = sampleRate;
|
||||
this->fftRate = fftRate;
|
||||
this->fftSize = fftSize;
|
||||
inputBlockSize = sampleRate / 200.0f;
|
||||
|
||||
halfBandWindow.init(1000000, 200000, 4000000);
|
||||
|
||||
inputBuffer.init(input);
|
||||
corrector.init(&inputBuffer.out, 50.0f / sampleRate);
|
||||
split.init(&inputBuffer.out);
|
||||
|
||||
// Allocate the fft taps
|
||||
fftTaps = new float[fftSize];
|
||||
|
||||
// Calculate the parameters for the reshaper
|
||||
int fftInterval = sampleRate / fftRate;
|
||||
fftOutputSampleCount = std::min<int>(fftInterval, fftSize);
|
||||
int fftSkip = fftInterval - fftOutputSampleCount;
|
||||
|
||||
// Generate FFT Windows
|
||||
generateFFTWindow(fftWindow, fftTaps, fftOutputSampleCount);
|
||||
|
||||
reshape.init(&fftStream, fftSize, fftSkip);
|
||||
split.bindStream(&fftStream);
|
||||
fftHandlerSink.init(&reshape.out, fftHandler, fftHandlerCtx);
|
||||
}
|
||||
|
||||
void SignalPath::setSampleRate(double sampleRate) {
|
||||
this->sampleRate = sampleRate;
|
||||
|
||||
// Stop the splitter
|
||||
split.stop();
|
||||
reshape.stop();
|
||||
|
||||
// Stop all VFOs
|
||||
for (auto const& [name, vfo] : vfos) {
|
||||
vfo.vfo->stop();
|
||||
}
|
||||
|
||||
updateFFTDSP();
|
||||
|
||||
// Update the sample rate for all VFOs and start them up
|
||||
for (auto const& [name, vfo] : vfos) {
|
||||
vfo.vfo->setInSampleRate(sampleRate);
|
||||
vfo.vfo->start();
|
||||
}
|
||||
|
||||
// Update correction rate on the IQ corrector
|
||||
corrector.setCorrectionRate(50.0f / sampleRate);
|
||||
|
||||
// Start the splitter
|
||||
split.start();
|
||||
reshape.start();
|
||||
}
|
||||
|
||||
double SignalPath::getSampleRate() {
|
||||
return sampleRate;
|
||||
}
|
||||
|
||||
void SignalPath::start() {
|
||||
for (auto& decimator : decimators) {
|
||||
decimator->start();
|
||||
}
|
||||
inputBuffer.start();
|
||||
if (iqCorrection) { corrector.start(); }
|
||||
split.start();
|
||||
reshape.start();
|
||||
fftHandlerSink.start();
|
||||
running = true;
|
||||
}
|
||||
|
||||
void SignalPath::stop() {
|
||||
for (auto& decimator : decimators) {
|
||||
decimator->stop();
|
||||
}
|
||||
inputBuffer.stop();
|
||||
if (iqCorrection) { corrector.stop(); }
|
||||
split.stop();
|
||||
reshape.stop();
|
||||
fftHandlerSink.stop();
|
||||
running = false;
|
||||
}
|
||||
|
||||
dsp::VFO* SignalPath::addVFO(std::string name, double outSampleRate, double bandwidth, double offset) {
|
||||
if (vfos.find(name) != vfos.end()) {
|
||||
return NULL;
|
||||
}
|
||||
VFO_t vfo;
|
||||
vfo.inputStream = new dsp::stream<dsp::complex_t>;
|
||||
split.bindStream(vfo.inputStream);
|
||||
vfo.vfo = new dsp::VFO();
|
||||
vfo.vfo->init(vfo.inputStream, offset, sampleRate, outSampleRate, bandwidth);
|
||||
vfo.vfo->start();
|
||||
vfos[name] = vfo;
|
||||
return vfo.vfo;
|
||||
}
|
||||
|
||||
void SignalPath::removeVFO(std::string name) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
VFO_t vfo = vfos[name];
|
||||
vfo.vfo->stop();
|
||||
split.unbindStream(vfo.inputStream);
|
||||
delete vfo.vfo;
|
||||
delete vfo.inputStream;
|
||||
vfos.erase(name);
|
||||
}
|
||||
|
||||
void SignalPath::setInput(dsp::stream<dsp::complex_t>* input) {
|
||||
inputBuffer.setInput(input);
|
||||
}
|
||||
|
||||
void SignalPath::bindIQStream(dsp::stream<dsp::complex_t>* stream) {
|
||||
split.bindStream(stream);
|
||||
}
|
||||
|
||||
void SignalPath::unbindIQStream(dsp::stream<dsp::complex_t>* stream) {
|
||||
split.unbindStream(stream);
|
||||
}
|
||||
|
||||
void SignalPath::setFFTSize(int size) {
|
||||
fftSize = size;
|
||||
reshape.stop();
|
||||
updateFFTDSP();
|
||||
reshape.start();
|
||||
}
|
||||
|
||||
void SignalPath::setFFTRate(double rate) {
|
||||
fftRate = rate;
|
||||
reshape.stop();
|
||||
updateFFTDSP();
|
||||
reshape.start();
|
||||
}
|
||||
|
||||
void SignalPath::startFFT() {
|
||||
reshape.start();
|
||||
fftHandlerSink.start();
|
||||
}
|
||||
|
||||
void SignalPath::stopFFT() {
|
||||
reshape.stop();
|
||||
fftHandlerSink.stop();
|
||||
}
|
||||
|
||||
void SignalPath::setBuffering(bool enabled) {
|
||||
inputBuffer.bypass = !enabled;
|
||||
}
|
||||
|
||||
void SignalPath::setDecimation(int dec) {
|
||||
decimation = dec;
|
||||
if (running) { split.stop(); }
|
||||
|
||||
// Stop existing decimators
|
||||
if (!decimators.empty()) {
|
||||
for (auto& decimator : decimators) {
|
||||
decimator->stop();
|
||||
}
|
||||
for (auto& decimator : decimators) {
|
||||
delete decimator;
|
||||
}
|
||||
}
|
||||
decimators.clear();
|
||||
|
||||
// If no decimation, reconnect
|
||||
if (!dec) {
|
||||
if (iqCorrection) {
|
||||
split.setInput(&corrector.out);
|
||||
}
|
||||
else {
|
||||
split.setInput(&inputBuffer.out);
|
||||
}
|
||||
|
||||
if (running) { split.start(); }
|
||||
core::setInputSampleRate(sourceSampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new decimators
|
||||
for (int i = 0; i < dec; i++) {
|
||||
dsp::HalfDecimator<dsp::complex_t>* decimator;
|
||||
if (iqCorrection && i == 0) {
|
||||
decimator = new dsp::HalfDecimator<dsp::complex_t>(&corrector.out, &halfBandWindow);
|
||||
}
|
||||
else if (i == 0) {
|
||||
decimator = new dsp::HalfDecimator<dsp::complex_t>(&inputBuffer.out, &halfBandWindow);
|
||||
}
|
||||
else {
|
||||
decimator = new dsp::HalfDecimator<dsp::complex_t>(&decimators[i - 1]->out, &halfBandWindow);
|
||||
}
|
||||
|
||||
if (running) { decimator->start(); }
|
||||
decimators.push_back(decimator);
|
||||
}
|
||||
split.setInput(&decimators[decimators.size() - 1]->out);
|
||||
if (running) { split.start(); }
|
||||
|
||||
// Update the DSP sample rate
|
||||
core::setInputSampleRate(sourceSampleRate);
|
||||
}
|
||||
|
||||
void SignalPath::setIQCorrection(bool enabled) {
|
||||
if (iqCorrection == enabled) { return; }
|
||||
|
||||
if (!iqCorrection && enabled) {
|
||||
if (decimation) {
|
||||
decimators[0]->setInput(&corrector.out);
|
||||
}
|
||||
else {
|
||||
split.setInput(&corrector.out);
|
||||
}
|
||||
if (running) { corrector.start(); }
|
||||
}
|
||||
else if (iqCorrection && !enabled) {
|
||||
if (running) { corrector.stop(); }
|
||||
if (decimation) {
|
||||
decimators[0]->setInput(&inputBuffer.out);
|
||||
}
|
||||
else {
|
||||
split.setInput(&inputBuffer.out);
|
||||
}
|
||||
}
|
||||
|
||||
iqCorrection = enabled;
|
||||
if (!enabled) {
|
||||
corrector.offset.re = 0;
|
||||
corrector.offset.im = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SignalPath::setFFTWindow(int win) {
|
||||
fftWindow = win;
|
||||
reshape.stop();
|
||||
updateFFTDSP();
|
||||
reshape.start();
|
||||
}
|
||||
|
||||
void SignalPath::generateFFTWindow(int win, float* taps, int size) {
|
||||
if (win == FFT_WINDOW_RECTANGULAR) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
taps[i] = (i % 2) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
else if (win == FFT_WINDOW_BLACKMAN) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
taps[i] = ((i % 2) ? dsp::window_function::blackman(i, size) : -dsp::window_function::blackman(i, size)) * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SignalPath::updateFFTDSP() {
|
||||
|
||||
// Allocate the fft taps
|
||||
if (fftTaps != NULL) { delete[] fftTaps; }
|
||||
fftTaps = new float[fftSize];
|
||||
|
||||
// Calculate the parameters for the reshaper
|
||||
int fftInterval = sampleRate / fftRate;
|
||||
fftOutputSampleCount = std::min<int>(fftInterval, fftSize);
|
||||
int fftSkip = fftInterval - fftOutputSampleCount;
|
||||
|
||||
// Generate FFT Windows
|
||||
generateFFTWindow(fftWindow, fftTaps, fftOutputSampleCount);
|
||||
|
||||
// Update parameters of the reshaper
|
||||
reshape.setKeep(fftOutputSampleCount);
|
||||
reshape.setSkip(fftSkip);
|
||||
|
||||
spdlog::info("Updating FFT DSP settings: Keep: {0}, Skip: {1}", fftOutputSampleCount, fftSkip);
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
#pragma once
|
||||
#include <dsp/routing.h>
|
||||
#include <dsp/vfo.h>
|
||||
#include <map>
|
||||
#include <dsp/sink.h>
|
||||
#include <dsp/decimation.h>
|
||||
#include <dsp/correction.h>
|
||||
|
||||
enum {
|
||||
FFT_WINDOW_RECTANGULAR,
|
||||
FFT_WINDOW_BLACKMAN,
|
||||
_FFT_WINDOW_COUNT
|
||||
};
|
||||
|
||||
class SignalPath {
|
||||
public:
|
||||
SignalPath();
|
||||
void init(uint64_t sampleRate, int fftRate, int fftSize, dsp::stream<dsp::complex_t>* input, dsp::complex_t* fftBuffer, void fftHandler(dsp::complex_t*, int, void*), void* fftHandlerCtx);
|
||||
void start();
|
||||
void stop();
|
||||
void setSampleRate(double sampleRate);
|
||||
double getSampleRate();
|
||||
dsp::VFO* addVFO(std::string name, double outSampleRate, double bandwidth, double offset);
|
||||
void removeVFO(std::string name);
|
||||
void setInput(dsp::stream<dsp::complex_t>* input);
|
||||
void bindIQStream(dsp::stream<dsp::complex_t>* stream);
|
||||
void unbindIQStream(dsp::stream<dsp::complex_t>* stream);
|
||||
void setFFTSize(int size);
|
||||
void setFFTRate(double rate);
|
||||
void startFFT();
|
||||
void stopFFT();
|
||||
void setBuffering(bool enabled);
|
||||
void setDecimation(int dec);
|
||||
void setIQCorrection(bool enabled);
|
||||
void setFFTWindow(int win);
|
||||
|
||||
dsp::SampleFrameBuffer<dsp::complex_t> inputBuffer;
|
||||
double sourceSampleRate = 0;
|
||||
int decimation = 0;
|
||||
|
||||
float* fftTaps = NULL;
|
||||
|
||||
private:
|
||||
void generateFFTWindow(int win, float* taps, int size);
|
||||
void updateFFTDSP();
|
||||
|
||||
struct VFO_t {
|
||||
dsp::stream<dsp::complex_t>* inputStream;
|
||||
dsp::VFO* vfo;
|
||||
};
|
||||
|
||||
dsp::Splitter<dsp::complex_t> split;
|
||||
dsp::IQCorrector corrector;
|
||||
|
||||
// FFT
|
||||
dsp::stream<dsp::complex_t> fftStream;
|
||||
dsp::Reshaper<dsp::complex_t> reshape;
|
||||
dsp::HandlerSink<dsp::complex_t> fftHandlerSink;
|
||||
|
||||
// VFO
|
||||
std::map<std::string, VFO_t> vfos;
|
||||
std::vector<dsp::HalfDecimator<dsp::complex_t>*> decimators;
|
||||
dsp::filter_window::BlackmanWindow halfBandWindow;
|
||||
|
||||
int fftOutputSampleCount = 0;
|
||||
double sampleRate;
|
||||
double fftRate;
|
||||
int fftSize;
|
||||
int inputBlockSize;
|
||||
int fftWindow = FFT_WINDOW_RECTANGULAR;
|
||||
bool bufferingEnabled = false;
|
||||
bool running = false;
|
||||
bool iqCorrection = false;
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
#include <signal_path/signal_path.h>
|
||||
|
||||
namespace sigpath {
|
||||
SignalPath signalPath;
|
||||
IQFrontEnd iqFrontEnd;
|
||||
VFOManager vfoManager;
|
||||
SourceManager sourceManager;
|
||||
SinkManager sinkManager;
|
||||
|
@ -1,12 +1,12 @@
|
||||
#pragma once
|
||||
#include <signal_path/dsp.h>
|
||||
#include <signal_path/vfo_manager.h>
|
||||
#include <signal_path/source.h>
|
||||
#include <signal_path/sink.h>
|
||||
#include "iq_frontend.h"
|
||||
#include "vfo_manager.h"
|
||||
#include "source.h"
|
||||
#include "sink.h"
|
||||
#include <module.h>
|
||||
|
||||
namespace sigpath {
|
||||
SDRPP_EXPORT SignalPath signalPath;
|
||||
SDRPP_EXPORT IQFrontEnd iqFrontEnd;
|
||||
SDRPP_EXPORT VFOManager vfoManager;
|
||||
SDRPP_EXPORT SourceManager sourceManager;
|
||||
SDRPP_EXPORT SinkManager sinkManager;
|
||||
|
@ -24,7 +24,7 @@ void SinkManager::Stream::init(dsp::stream<dsp::stereo_t>* in, EventHandler<floa
|
||||
_sampleRate = sampleRate;
|
||||
splitter.init(_in);
|
||||
splitter.bindStream(&volumeInput);
|
||||
volumeAjust.init(&volumeInput, 1.0f);
|
||||
volumeAjust.init(&volumeInput, 1.0f, false);
|
||||
sinkOut = &volumeAjust.out;
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
#include <string>
|
||||
#include <dsp/stream.h>
|
||||
#include <dsp/types.h>
|
||||
#include <dsp/routing.h>
|
||||
#include <dsp/processing.h>
|
||||
#include <dsp/sink.h>
|
||||
#include "../dsp/routing/splitter.h"
|
||||
#include "../dsp/audio/volume.h"
|
||||
#include "../dsp/sink/null_sink.h"
|
||||
#include <mutex>
|
||||
#include <utils/event.h>
|
||||
#include <vector>
|
||||
@ -52,10 +52,10 @@ public:
|
||||
|
||||
private:
|
||||
dsp::stream<dsp::stereo_t>* _in;
|
||||
dsp::Splitter<dsp::stereo_t> splitter;
|
||||
dsp::routing::Splitter<dsp::stereo_t> splitter;
|
||||
SinkManager::Sink* sink;
|
||||
dsp::stream<dsp::stereo_t> volumeInput;
|
||||
dsp::Volume<dsp::stereo_t> volumeAjust;
|
||||
dsp::audio::Volume volumeAjust;
|
||||
std::mutex ctrlMtx;
|
||||
float _sampleRate;
|
||||
int providerId = 0;
|
||||
@ -85,7 +85,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
dsp::NullSink<dsp::stereo_t> ns;
|
||||
dsp::sink::Null<dsp::stereo_t> ns;
|
||||
};
|
||||
|
||||
void registerSinkProvider(std::string name, SinkProvider provider);
|
||||
|
@ -26,7 +26,7 @@ void SourceManager::unregisterSource(std::string name) {
|
||||
if (selectedHandler != NULL) {
|
||||
sources[selectedName]->deselectHandler(sources[selectedName]->ctx);
|
||||
}
|
||||
sigpath::signalPath.setInput(&nullSource);
|
||||
sigpath::iqFrontEnd.setInput(&nullSource);
|
||||
selectedHandler = NULL;
|
||||
}
|
||||
sources.erase(name);
|
||||
@ -54,7 +54,7 @@ void SourceManager::selectSource(std::string name) {
|
||||
server::setInput(selectedHandler->stream);
|
||||
}
|
||||
else {
|
||||
sigpath::signalPath.setInput(selectedHandler->stream);
|
||||
sigpath::iqFrontEnd.setInput(selectedHandler->stream);
|
||||
}
|
||||
// Set server input here
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
VFOManager::VFO::VFO(std::string name, int reference, double offset, double bandwidth, double sampleRate, double minBandwidth, double maxBandwidth, bool bandwidthLocked) {
|
||||
this->name = name;
|
||||
dspVFO = sigpath::signalPath.addVFO(name, sampleRate, bandwidth, offset);
|
||||
dspVFO = sigpath::iqFrontEnd.addVFO(name, sampleRate, bandwidth, offset);
|
||||
wtfVFO = new ImGui::WaterfallVFO;
|
||||
wtfVFO->setReference(reference);
|
||||
wtfVFO->setBandwidth(bandwidth);
|
||||
@ -12,7 +12,7 @@ VFOManager::VFO::VFO(std::string name, int reference, double offset, double band
|
||||
wtfVFO->minBandwidth = minBandwidth;
|
||||
wtfVFO->maxBandwidth = maxBandwidth;
|
||||
wtfVFO->bandwidthLocked = bandwidthLocked;
|
||||
output = dspVFO->out;
|
||||
output = &dspVFO->out;
|
||||
gui::waterfall.vfos[name] = wtfVFO;
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ VFOManager::VFO::~VFO() {
|
||||
if (gui::waterfall.selectedVFO == name) {
|
||||
gui::waterfall.selectFirstVFO();
|
||||
}
|
||||
sigpath::signalPath.removeVFO(name);
|
||||
sigpath::iqFrontEnd.removeVFO(name);
|
||||
delete wtfVFO;
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ void VFOManager::VFO::setBandwidth(double bandwidth, bool updateWaterfall) {
|
||||
}
|
||||
|
||||
void VFOManager::VFO::setSampleRate(double sampleRate, double bandwidth) {
|
||||
dspVFO->setOutSampleRate(sampleRate, bandwidth);
|
||||
dspVFO->setOutSamplerate(sampleRate, bandwidth);
|
||||
wtfVFO->setBandwidth(bandwidth);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <dsp/vfo.h>
|
||||
#include "../dsp/channel/rx_vfo.h"
|
||||
#include <gui/widgets/waterfall.h>
|
||||
#include <utils/event.h>
|
||||
|
||||
@ -30,7 +30,7 @@ public:
|
||||
|
||||
friend class VFOManager;
|
||||
|
||||
dsp::VFO* dspVFO;
|
||||
dsp::channel::RxVFO* dspVFO;
|
||||
ImGui::WaterfallVFO* wtfVFO;
|
||||
|
||||
private:
|
||||
|
Reference in New Issue
Block a user