mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-07-09 18:45:22 +02:00
lots o shit
This commit is contained in:
@ -6,7 +6,10 @@
|
||||
#include <signal_path/signal_path.h>
|
||||
#include <config.h>
|
||||
#include <dsp/chain.h>
|
||||
#include <dsp/noise_reduction.h>
|
||||
#include <dsp/noise_reduction/fm_if.h>
|
||||
#include <dsp/noise_reduction/squelch.h>
|
||||
#include <dsp/multirate/rational_resampler.h>
|
||||
#include <dsp/filter/deephasis.h>
|
||||
#include <core.h>
|
||||
#include <utils/optionlist.h>
|
||||
#include "radio_interface.h"
|
||||
@ -74,17 +77,13 @@ public:
|
||||
// Initialize IF DSP chain
|
||||
ifChainOutputChanged.ctx = this;
|
||||
ifChainOutputChanged.handler = ifChainOutputChangeHandler;
|
||||
ifChain.init(vfo->output, &ifChainOutputChanged);
|
||||
ifChain.init(vfo->output);
|
||||
|
||||
fmnr.block.init(NULL, 32);
|
||||
notch.block.init(NULL, 0.5, 0, 250000); // TODO: The rate has to depend on IF sample rate so the width is always the same
|
||||
squelch.block.init(NULL, MIN_SQUELCH);
|
||||
nb.block.init(NULL, -100.0f);
|
||||
fmnr.init(NULL, 32);
|
||||
squelch.init(NULL, MIN_SQUELCH);
|
||||
|
||||
ifChain.add(¬ch);
|
||||
ifChain.add(&squelch);
|
||||
ifChain.add(&fmnr);
|
||||
ifChain.add(&nb);
|
||||
ifChain.addBlock(&squelch, false);
|
||||
ifChain.addBlock(&fmnr, false);
|
||||
|
||||
// Load configuration for and enabled all demodulators
|
||||
EventHandler<dsp::stream<dsp::stereo_t>*> _demodOutputChangeHandler;
|
||||
@ -107,26 +106,22 @@ public:
|
||||
bw = std::clamp<double>(bw, demod->getMinBandwidth(), demod->getMaxBandwidth());
|
||||
|
||||
// Initialize
|
||||
demod->init(name, &config, ifChain.getOutput(), bw, _demodOutputChangeHandler, _demodAfbwChangedHandler, stream.getSampleRate());
|
||||
demod->init(name, &config, ifChain.out, bw, _demodOutputChangeHandler, _demodAfbwChangedHandler, stream.getSampleRate());
|
||||
}
|
||||
|
||||
// Initialize audio DSP chain
|
||||
afChainOutputChanged.ctx = this;
|
||||
afChainOutputChanged.handler = afChainOutputChangeHandler;
|
||||
afChain.init(&dummyAudioStream, &afChainOutputChanged);
|
||||
afChain.init(&dummyAudioStream);
|
||||
|
||||
win.init(24000, 24000, 48000);
|
||||
resamp.block.init(NULL, &win, 250000, 48000);
|
||||
deemp.block.init(NULL, 48000, 50e-6);
|
||||
deemp.block.bypass = false;
|
||||
resamp.init(NULL, 250000.0, 48000.0);
|
||||
deemp.init(NULL, 50e-6, 48000.0);
|
||||
|
||||
afChain.add(&resamp);
|
||||
afChain.add(&deemp);
|
||||
afChain.addBlock(&resamp, true);
|
||||
afChain.addBlock(&deemp, false);
|
||||
|
||||
// Initialize the sink
|
||||
srChangeHandler.ctx = this;
|
||||
srChangeHandler.handler = sampleRateChangeHandler;
|
||||
stream.init(afChain.getOutput(), &srChangeHandler, audioSampleRate);
|
||||
stream.init(afChain.out, &srChangeHandler, audioSampleRate);
|
||||
sigpath::sinkManager.registerStream(name, &stream);
|
||||
|
||||
// Select the demodulator
|
||||
@ -165,7 +160,7 @@ public:
|
||||
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 200000, 200000, 50000, 200000, false);
|
||||
vfo->wtfVFO->onUserChangedBandwidth.bindHandler(&onUserChangedBandwidthHandler);
|
||||
}
|
||||
ifChain.setInput(vfo->output);
|
||||
ifChain.setInput(vfo->output, [=](dsp::stream<dsp::complex_t>* out){ ifChainOutputChangeHandler(out, this); });
|
||||
ifChain.start();
|
||||
selectDemodByID((DemodID)selectedDemodID);
|
||||
afChain.start();
|
||||
@ -280,32 +275,6 @@ private:
|
||||
}
|
||||
if (!_this->squelchEnabled && _this->enabled) { style::endDisabled(); }
|
||||
|
||||
// Noise blanker
|
||||
if (_this->nbAllowed) {
|
||||
if (ImGui::Checkbox(("Noise Blanker##_radio_nb_ena_" + _this->name).c_str(), &_this->nbEnabled)) {
|
||||
_this->setNoiseBlankerEnabled(_this->nbEnabled);
|
||||
}
|
||||
if (!_this->nbEnabled && _this->enabled) { style::beginDisabled(); }
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||
if (ImGui::SliderFloat(("##_radio_nb_lvl_" + _this->name).c_str(), &_this->nbLevel, 0.0f, -100.0f, "%.3fdB")) {
|
||||
_this->setNoiseBlankerLevel(_this->nbLevel);
|
||||
}
|
||||
if (!_this->nbEnabled && _this->enabled) { style::endDisabled(); }
|
||||
}
|
||||
|
||||
|
||||
// // Notch filter
|
||||
// if (ImGui::Checkbox("Notch##_radio_notch_ena_", &_this->notchEnabled)) {
|
||||
// _this->ifChain.setState(&_this->notch, _this->notchEnabled);
|
||||
// }
|
||||
// if (ImGui::SliderFloat(("NF##_radio_notch_freq_" + _this->name).c_str(), &_this->notchPos, -7500, 7500)) {
|
||||
// _this->notch.block.setOffset(_this->notchPos);
|
||||
// }
|
||||
// if (ImGui::SliderFloat(("NW##_radio_notch_width_" + _this->name).c_str(), &_this->notchWidth, 0, 1000)) {
|
||||
// // TODO: Implement
|
||||
// }
|
||||
|
||||
// FM IF Noise Reduction
|
||||
if (_this->FMIFNRAllowed) {
|
||||
if (ImGui::Checkbox(("IF Noise Reduction##_radio_fmifnr_ena_" + _this->name).c_str(), &_this->FMIFNREnabled)) {
|
||||
@ -352,10 +321,10 @@ private:
|
||||
selectedDemod->AFSampRateChanged(audioSampleRate);
|
||||
|
||||
// Set the demodulator's input
|
||||
selectedDemod->setInput(ifChain.getOutput());
|
||||
selectedDemod->setInput(ifChain.out);
|
||||
|
||||
// Set AF chain's input
|
||||
afChain.setInput(selectedDemod->getOutput());
|
||||
afChain.setInput(selectedDemod->getOutput(), [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
|
||||
|
||||
// Load config
|
||||
bandwidth = selectedDemod->getDefaultBandwidth();
|
||||
@ -433,31 +402,24 @@ private:
|
||||
setIFNRPreset((selectedDemodID == RADIO_DEMOD_NFM) ? ifnrPresets[fmIFPresetId] : IFNR_PRESET_BROADCAST);
|
||||
setFMIFNREnabled(FMIFNRAllowed ? FMIFNREnabled : false);
|
||||
|
||||
// Configure notch
|
||||
notch.block.setSampleRate(selectedDemod->getIFSampleRate());
|
||||
|
||||
// Configure squelch
|
||||
squelch.block.setLevel(squelchLevel);
|
||||
squelch.setLevel(squelchLevel);
|
||||
setSquelchEnabled(squelchEnabled);
|
||||
|
||||
// Configure noise blanker
|
||||
nb.block.setLevel(nbLevel);
|
||||
setNoiseBlankerEnabled(nbEnabled);
|
||||
|
||||
// Configure AF chain
|
||||
if (postProcEnabled) {
|
||||
// Configure resampler
|
||||
afChain.stop();
|
||||
resamp.block.setInSampleRate(selectedDemod->getAFSampleRate());
|
||||
resamp.setInSamplerate(selectedDemod->getAFSampleRate());
|
||||
setAudioSampleRate(audioSampleRate);
|
||||
afChain.enable(&resamp);
|
||||
afChain.enableBlock(&resamp, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
|
||||
|
||||
// Configure deemphasis
|
||||
setDeemphasisMode(deempModes[deempId]);
|
||||
}
|
||||
else {
|
||||
// Disable everything if post processing is disabled
|
||||
afChain.disableAll();
|
||||
afChain.disableAllBlocks([=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
|
||||
}
|
||||
|
||||
// Start new demodulator
|
||||
@ -474,12 +436,12 @@ private:
|
||||
vfo->setBandwidth(bandwidth);
|
||||
selectedDemod->setBandwidth(bandwidth);
|
||||
|
||||
// Only bother with setting the resampling setting if we're actually post processing and dynamic bw is enabled
|
||||
if (selectedDemod->getDynamicAFBandwidth() && postProcEnabled) {
|
||||
win.setCutoff(audioBW);
|
||||
win.setTransWidth(audioBW);
|
||||
resamp.block.updateWindow(&win);
|
||||
}
|
||||
// // Only bother with setting the resampling setting if we're actually post processing and dynamic bw is enabled
|
||||
// if (selectedDemod->getDynamicAFBandwidth() && postProcEnabled) {
|
||||
// win.setCutoff(audioBW);
|
||||
// win.setTransWidth(audioBW);
|
||||
// resamp.block.updateWindow(&win);
|
||||
// }
|
||||
|
||||
config.acquire();
|
||||
config.conf[name][selectedDemod->getName()]["bandwidth"] = bandwidth;
|
||||
@ -504,15 +466,16 @@ private:
|
||||
|
||||
afChain.stop();
|
||||
|
||||
// Configure resampler
|
||||
resamp.block.setOutSampleRate(audioSampleRate);
|
||||
win.setSampleRate(selectedDemod->getAFSampleRate() * resamp.block.getInterpolation());
|
||||
win.setCutoff(audioBW);
|
||||
win.setTransWidth(audioBW);
|
||||
resamp.block.updateWindow(&win);
|
||||
// // Configure resampler
|
||||
// resamp.block.setOutSampleRate(audioSampleRate);
|
||||
// win.setSampleRate(selectedDemod->getAFSampleRate() * resamp.block.getInterpolation());
|
||||
// win.setCutoff(audioBW);
|
||||
// win.setTransWidth(audioBW);
|
||||
// resamp.block.updateWindow(&win);
|
||||
resamp.setOutSamplerate(audioSampleRate);
|
||||
|
||||
// Configure deemphasis sample rate
|
||||
deemp.block.setSampleRate(audioSampleRate);
|
||||
deemp.setSamplerate(audioSampleRate);
|
||||
|
||||
afChain.start();
|
||||
}
|
||||
@ -521,8 +484,8 @@ private:
|
||||
deempId = deempModes.valueId(mode);
|
||||
if (!postProcEnabled || !selectedDemod) { return; }
|
||||
bool deempEnabled = (mode != DEEMP_MODE_NONE);
|
||||
if (deempEnabled) { deemp.block.setTau(deempTaus[mode]); }
|
||||
afChain.setState(&deemp, deempEnabled);
|
||||
if (deempEnabled) { deemp.setTau(deempTaus[mode]); }
|
||||
afChain.setBlockEnabled(&deemp, deempEnabled, [=](dsp::stream<dsp::stereo_t>* out){ stream.setInput(out); });
|
||||
|
||||
// Save config
|
||||
config.acquire();
|
||||
@ -533,7 +496,7 @@ private:
|
||||
void setSquelchEnabled(bool enable) {
|
||||
squelchEnabled = enable;
|
||||
if (!selectedDemod) { return; }
|
||||
ifChain.setState(&squelch, squelchEnabled);
|
||||
ifChain.setBlockEnabled(&squelch, squelchEnabled, [=](dsp::stream<dsp::complex_t>* out){ selectedDemod->setInput(out); });
|
||||
|
||||
// Save config
|
||||
config.acquire();
|
||||
@ -543,7 +506,7 @@ private:
|
||||
|
||||
void setSquelchLevel(float level) {
|
||||
squelchLevel = std::clamp<float>(level, MIN_SQUELCH, MAX_SQUELCH);
|
||||
squelch.block.setLevel(squelchLevel);
|
||||
squelch.setLevel(squelchLevel);
|
||||
|
||||
// Save config
|
||||
config.acquire();
|
||||
@ -554,7 +517,7 @@ private:
|
||||
void setFMIFNREnabled(bool enabled) {
|
||||
FMIFNREnabled = enabled;
|
||||
if (!selectedDemod) { return; }
|
||||
ifChain.setState(&fmnr, FMIFNREnabled);
|
||||
ifChain.setBlockEnabled(&fmnr, FMIFNREnabled, [=](dsp::stream<dsp::complex_t>* out){ selectedDemod->setInput(out); });
|
||||
|
||||
// Save config
|
||||
config.acquire();
|
||||
@ -562,39 +525,17 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
void setNoiseBlankerEnabled(bool enabled) {
|
||||
nbEnabled = enabled;
|
||||
if (!selectedDemod) { return; }
|
||||
ifChain.setState(&nb, nbEnabled);
|
||||
|
||||
// Save config
|
||||
config.acquire();
|
||||
config.conf[name][selectedDemod->getName()]["noiseBlankerEnabled"] = nbEnabled;
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
void setNoiseBlankerLevel(float level) {
|
||||
nbLevel = level;
|
||||
if (!selectedDemod) { return; }
|
||||
nb.block.setLevel(nbLevel);
|
||||
|
||||
// Save config
|
||||
config.acquire();
|
||||
config.conf[name][selectedDemod->getName()]["noiseBlankerLevel"] = nbLevel;
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
void setIFNRPreset(IFNRPreset preset) {
|
||||
// Don't save if in broadcast mode
|
||||
if (preset == IFNR_PRESET_BROADCAST) {
|
||||
if (!selectedDemod) { return; }
|
||||
fmnr.block.setTapCount(ifnrTaps[preset]);
|
||||
fmnr.setBins(ifnrTaps[preset]);
|
||||
return;
|
||||
}
|
||||
|
||||
fmIFPresetId = ifnrPresets.valueId(preset);
|
||||
if (!selectedDemod) { return; }
|
||||
fmnr.block.setTapCount(ifnrTaps[preset]);
|
||||
fmnr.setBins(ifnrTaps[preset]);
|
||||
|
||||
// Save config
|
||||
config.acquire();
|
||||
@ -614,7 +555,7 @@ private:
|
||||
|
||||
static void demodOutputChangeHandler(dsp::stream<dsp::stereo_t>* output, void* ctx) {
|
||||
RadioModule* _this = (RadioModule*)ctx;
|
||||
_this->afChain.setInput(output);
|
||||
_this->afChain.setInput(output, [=](dsp::stream<dsp::stereo_t>* out){ _this->stream.setInput(out); });
|
||||
}
|
||||
|
||||
static void demodAfbwChangedHandler(float output, void* ctx) {
|
||||
@ -623,9 +564,9 @@ private:
|
||||
float audioBW = std::min<float>(_this->selectedDemod->getMaxAFBandwidth(), _this->selectedDemod->getAFBandwidth(_this->bandwidth));
|
||||
audioBW = std::min<float>(audioBW, _this->audioSampleRate / 2.0);
|
||||
|
||||
_this->win.setCutoff(audioBW);
|
||||
_this->win.setTransWidth(audioBW);
|
||||
_this->resamp.block.updateWindow(&_this->win);
|
||||
// _this->win.setCutoff(audioBW);
|
||||
// _this->win.setTransWidth(audioBW);
|
||||
// _this->resamp.block.updateWindow(&_this->win);
|
||||
}
|
||||
|
||||
static void ifChainOutputChangeHandler(dsp::stream<dsp::complex_t>* output, void* ctx) {
|
||||
@ -634,11 +575,6 @@ private:
|
||||
_this->selectedDemod->setInput(output);
|
||||
}
|
||||
|
||||
static void afChainOutputChangeHandler(dsp::stream<dsp::stereo_t>* output, void* ctx) {
|
||||
RadioModule* _this = (RadioModule*)ctx;
|
||||
_this->stream.setInput(output);
|
||||
}
|
||||
|
||||
static void moduleInterfaceHandler(int code, void* in, void* out, void* ctx) {
|
||||
RadioModule* _this = (RadioModule*)ctx;
|
||||
if (!_this->enabled || !_this->selectedDemod) { return; }
|
||||
@ -694,18 +630,15 @@ private:
|
||||
VFOManager::VFO* vfo = NULL;
|
||||
|
||||
// IF chain
|
||||
dsp::Chain<dsp::complex_t> ifChain;
|
||||
dsp::ChainLink<dsp::FMIFNoiseReduction, dsp::complex_t> fmnr;
|
||||
dsp::ChainLink<dsp::NotchFilter, dsp::complex_t> notch;
|
||||
dsp::ChainLink<dsp::Squelch, dsp::complex_t> squelch;
|
||||
dsp::ChainLink<dsp::NoiseBlanker, dsp::complex_t> nb;
|
||||
dsp::chain<dsp::complex_t> ifChain;
|
||||
dsp::noise_reduction::FMIF fmnr;
|
||||
dsp::noise_reduction::Squelch squelch;
|
||||
|
||||
// Audio chain
|
||||
dsp::stream<dsp::stereo_t> dummyAudioStream;
|
||||
dsp::Chain<dsp::stereo_t> afChain;
|
||||
dsp::filter_window::BlackmanWindow win;
|
||||
dsp::ChainLink<dsp::PolyphaseResampler<dsp::stereo_t>, dsp::stereo_t> resamp;
|
||||
dsp::ChainLink<dsp::BFMDeemp, dsp::stereo_t> deemp;
|
||||
dsp::chain<dsp::stereo_t> afChain;
|
||||
dsp::multirate::RationalResampler<dsp::stereo_t> resamp;
|
||||
dsp::filter::Deemphasis<dsp::stereo_t> deemp;
|
||||
|
||||
SinkManager::Stream stream;
|
||||
|
||||
|
Reference in New Issue
Block a user