mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-06-25 12:07:49 +02:00
Prototype noise blanker
This commit is contained in:
@ -38,17 +38,13 @@ namespace demod {
|
||||
virtual double getMinBandwidth() = 0;
|
||||
virtual double getMaxBandwidth() = 0;
|
||||
virtual bool getBandwidthLocked() = 0;
|
||||
virtual double getMaxAFBandwidth() = 0;
|
||||
virtual double getDefaultSnapInterval() = 0;
|
||||
virtual int getVFOReference() = 0;
|
||||
virtual bool getDeempAllowed() = 0;
|
||||
virtual bool getPostProcEnabled() = 0;
|
||||
virtual int getDefaultDeemphasisMode() = 0;
|
||||
virtual double getAFBandwidth(double bandwidth) = 0;
|
||||
virtual bool getFMIFNRAllowed() = 0;
|
||||
virtual bool getNBAllowed() = 0;
|
||||
|
||||
virtual bool getDynamicAFBandwidth() = 0;
|
||||
virtual dsp::stream<dsp::stereo_t>* getOutput() = 0;
|
||||
};
|
||||
}
|
||||
|
@ -79,14 +79,11 @@ namespace demod {
|
||||
double getMinBandwidth() { return 1000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate(); }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 1000.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth / 2.0; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return false; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||
|
@ -85,14 +85,11 @@ namespace demod {
|
||||
double getMinBandwidth() { return 50.0; }
|
||||
double getMaxBandwidth() { return 500.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 10.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return (bandwidth / 2.0) + (float)tone; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return false; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||
|
@ -72,14 +72,11 @@ namespace demod {
|
||||
double getMinBandwidth() { return 1000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 100.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth / 2.0; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||
|
@ -72,14 +72,11 @@ namespace demod {
|
||||
double getMinBandwidth() { return 500.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 100.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_UPPER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||
|
@ -50,14 +50,11 @@ namespace demod {
|
||||
double getMinBandwidth() { return 1000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate(); }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 2500.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return true; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth / 2.0; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return true; }
|
||||
bool getNBAllowed() { return false; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||
|
@ -52,14 +52,11 @@ namespace demod {
|
||||
double getMinBandwidth() { return audioSampleRate; }
|
||||
double getMaxBandwidth() { return audioSampleRate; }
|
||||
bool getBandwidthLocked() { return true; }
|
||||
double getMaxAFBandwidth() { return audioSampleRate; }
|
||||
double getDefaultSnapInterval() { return 2500.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return false; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth; }
|
||||
bool getDynamicAFBandwidth() { return false; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &c2s.out; }
|
||||
|
@ -73,14 +73,11 @@ namespace demod {
|
||||
double getMinBandwidth() { return 500.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return getIFSampleRate() / 2.0; }
|
||||
double getDefaultSnapInterval() { return 100.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_LOWER; }
|
||||
bool getDeempAllowed() { return false; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; }
|
||||
double getAFBandwidth(double bandwidth) { return bandwidth; }
|
||||
bool getDynamicAFBandwidth() { return true; }
|
||||
bool getFMIFNRAllowed() { return false; }
|
||||
bool getNBAllowed() { return true; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||
|
@ -76,14 +76,11 @@ namespace demod {
|
||||
double getMinBandwidth() { return 50000.0; }
|
||||
double getMaxBandwidth() { return getIFSampleRate(); }
|
||||
bool getBandwidthLocked() { return false; }
|
||||
double getMaxAFBandwidth() { return 16000.0; }
|
||||
double getDefaultSnapInterval() { return 100000.0; }
|
||||
int getVFOReference() { return ImGui::WaterfallVFO::REF_CENTER; }
|
||||
bool getDeempAllowed() { return true; }
|
||||
bool getPostProcEnabled() { return true; }
|
||||
int getDefaultDeemphasisMode() { return DEEMP_MODE_50US; }
|
||||
double getAFBandwidth(double bandwidth) { return 16000.0; }
|
||||
bool getDynamicAFBandwidth() { return false; }
|
||||
bool getFMIFNRAllowed() { return true; }
|
||||
bool getNBAllowed() { return false; }
|
||||
dsp::stream<dsp::stereo_t>* getOutput() { return &demod.out; }
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <signal_path/signal_path.h>
|
||||
#include <config.h>
|
||||
#include <dsp/chain.h>
|
||||
#include <dsp/noise_reduction/noise_blanker.h>
|
||||
#include <dsp/noise_reduction/fm_if.h>
|
||||
#include <dsp/noise_reduction/squelch.h>
|
||||
#include <dsp/multirate/rational_resampler.h>
|
||||
@ -68,9 +69,11 @@ public:
|
||||
ifChainOutputChanged.handler = ifChainOutputChangeHandler;
|
||||
ifChain.init(vfo->output);
|
||||
|
||||
nb.init(NULL, 500.0 / 24000.0, 10.0);
|
||||
fmnr.init(NULL, 32);
|
||||
squelch.init(NULL, MIN_SQUELCH);
|
||||
|
||||
ifChain.addBlock(&nb, false);
|
||||
ifChain.addBlock(&squelch, false);
|
||||
ifChain.addBlock(&fmnr, false);
|
||||
|
||||
@ -228,6 +231,18 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// Noise blanker
|
||||
if (ImGui::Checkbox(("Noise blanker (W.I.P.)##_radio_nb_ena_" + _this->name).c_str(), &_this->nbEnabled)) {
|
||||
_this->setNBEnabled(_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, _this->MIN_NB, _this->MAX_NB, "%.3fdB")) {
|
||||
_this->setNBLevel(_this->nbLevel);
|
||||
}
|
||||
if (!_this->nbEnabled && _this->enabled) { style::endDisabled(); }
|
||||
|
||||
// Squelch
|
||||
if (ImGui::Checkbox(("Squelch##_radio_sqelch_ena_" + _this->name).c_str(), &_this->squelchEnabled)) {
|
||||
_this->setSquelchEnabled(_this->squelchEnabled);
|
||||
@ -351,6 +366,7 @@ private:
|
||||
nbAllowed = selectedDemod->getNBAllowed();
|
||||
nbEnabled = false;
|
||||
nbLevel = 0.0f;
|
||||
double ifSamplerate = selectedDemod->getIFSampleRate();
|
||||
config.acquire();
|
||||
if (config.conf[name][selectedDemod->getName()].contains("bandwidth")) {
|
||||
bandwidth = config.conf[name][selectedDemod->getName()]["bandwidth"];
|
||||
@ -387,9 +403,6 @@ private:
|
||||
if (config.conf[name][selectedDemod->getName()].contains("noiseBlankerEnabled")) {
|
||||
nbEnabled = config.conf[name][selectedDemod->getName()]["noiseBlankerEnabled"];
|
||||
}
|
||||
if (config.conf[name][selectedDemod->getName()].contains("noiseBlankerEnabled")) {
|
||||
nbEnabled = config.conf[name][selectedDemod->getName()]["noiseBlankerEnabled"];
|
||||
}
|
||||
if (config.conf[name][selectedDemod->getName()].contains("noiseBlankerLevel")) {
|
||||
nbLevel = config.conf[name][selectedDemod->getName()]["noiseBlankerLevel"];
|
||||
}
|
||||
@ -400,18 +413,23 @@ private:
|
||||
vfo->setBandwidthLimits(minBandwidth, maxBandwidth, selectedDemod->getBandwidthLocked());
|
||||
vfo->setReference(selectedDemod->getVFOReference());
|
||||
vfo->setSnapInterval(snapInterval);
|
||||
vfo->setSampleRate(selectedDemod->getIFSampleRate(), bandwidth);
|
||||
vfo->setSampleRate(ifSamplerate, bandwidth);
|
||||
}
|
||||
|
||||
// Configure bandwidth
|
||||
setBandwidth(bandwidth);
|
||||
|
||||
// Configure noise blanker
|
||||
nb.setRate(500.0 / ifSamplerate);
|
||||
setNBLevel(nbLevel);
|
||||
setNBEnabled(nbEnabled);
|
||||
|
||||
// Configure FM IF Noise Reduction
|
||||
setIFNRPreset((selectedDemodID == RADIO_DEMOD_NFM) ? ifnrPresets[fmIFPresetId] : IFNR_PRESET_BROADCAST);
|
||||
setFMIFNREnabled(FMIFNRAllowed ? FMIFNREnabled : false);
|
||||
|
||||
// Configure squelch
|
||||
squelch.setLevel(squelchLevel);
|
||||
setSquelchLevel(squelchLevel);
|
||||
setSquelchEnabled(squelchEnabled);
|
||||
|
||||
// Configure AF chain
|
||||
@ -439,18 +457,9 @@ private:
|
||||
bw = std::clamp<double>(bw, minBandwidth, maxBandwidth);
|
||||
bandwidth = bw;
|
||||
if (!selectedDemod) { return; }
|
||||
float audioBW = std::min<float>(selectedDemod->getMaxAFBandwidth(), selectedDemod->getAFBandwidth(bandwidth));
|
||||
audioBW = std::min<float>(audioBW, audioSampleRate / 2.0);
|
||||
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);
|
||||
// }
|
||||
|
||||
config.acquire();
|
||||
config.conf[name][selectedDemod->getName()]["bandwidth"] = bandwidth;
|
||||
config.release(true);
|
||||
@ -469,17 +478,10 @@ private:
|
||||
vfo->setSampleRate(selectedDemod->getIFSampleRate(), bandwidth);
|
||||
return;
|
||||
}
|
||||
float audioBW = std::min<float>(selectedDemod->getMaxAFBandwidth(), selectedDemod->getAFBandwidth(bandwidth));
|
||||
audioBW = std::min<float>(audioBW, audioSampleRate / 2.0);
|
||||
|
||||
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.setOutSamplerate(audioSampleRate);
|
||||
|
||||
// Configure deemphasis sample rate
|
||||
@ -501,6 +503,27 @@ private:
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
void setNBEnabled(bool enable) {
|
||||
nbEnabled = enable;
|
||||
if (!selectedDemod) { return; }
|
||||
ifChain.setBlockEnabled(&nb, nbEnabled, [=](dsp::stream<dsp::complex_t>* out){ selectedDemod->setInput(out); });
|
||||
|
||||
// Save config
|
||||
config.acquire();
|
||||
config.conf[name][selectedDemod->getName()]["noiseBlankerEnabled"] = nbEnabled;
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
void setNBLevel(float level) {
|
||||
nbLevel = std::clamp<float>(level, MIN_NB, MAX_NB);
|
||||
nb.setLevel(nbLevel);
|
||||
|
||||
// Save config
|
||||
config.acquire();
|
||||
config.conf[name][selectedDemod->getName()]["noiseBlankerLevel"] = nbLevel;
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
void setSquelchEnabled(bool enable) {
|
||||
squelchEnabled = enable;
|
||||
if (!selectedDemod) { return; }
|
||||
@ -623,6 +646,7 @@ private:
|
||||
|
||||
// IF chain
|
||||
dsp::chain<dsp::complex_t> ifChain;
|
||||
dsp::noise_reduction::NoiseBlanker nb;
|
||||
dsp::noise_reduction::FMIF fmnr;
|
||||
dsp::noise_reduction::Squelch squelch;
|
||||
|
||||
@ -663,9 +687,11 @@ private:
|
||||
float notchWidth = 500;
|
||||
|
||||
bool nbAllowed;
|
||||
bool nbEnabled;
|
||||
float nbLevel = -100.0f;
|
||||
bool nbEnabled = false;
|
||||
float nbLevel = 10.0f;
|
||||
|
||||
const double MIN_NB = 1.0;
|
||||
const double MAX_NB = 10.0;
|
||||
const double MIN_SQUELCH = -100.0;
|
||||
const double MAX_SQUELCH = 0.0;
|
||||
|
||||
|
Reference in New Issue
Block a user