From 75050347deca8699ffc6d4feaeaa52d8d8306081 Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Mon, 27 Mar 2023 01:50:34 +0200 Subject: [PATCH] noise reduction work --- core/src/dsp/convert/stereo_to_mono.h | 2 +- core/src/dsp/noise_reduction/noise_blanker.h | 22 ++++++------- decoder_modules/radio/src/demod.h | 1 + decoder_modules/radio/src/demodulators/am.h | 1 + decoder_modules/radio/src/demodulators/cw.h | 1 + decoder_modules/radio/src/demodulators/dsb.h | 1 + decoder_modules/radio/src/demodulators/lsb.h | 1 + decoder_modules/radio/src/demodulators/nfm.h | 1 + decoder_modules/radio/src/demodulators/raw.h | 1 + decoder_modules/radio/src/demodulators/usb.h | 1 + decoder_modules/radio/src/demodulators/wfm.h | 1 + decoder_modules/radio/src/radio_module.h | 34 +++++++++++++++++++- 12 files changed, 52 insertions(+), 15 deletions(-) diff --git a/core/src/dsp/convert/stereo_to_mono.h b/core/src/dsp/convert/stereo_to_mono.h index b3857c9f..db5fc325 100644 --- a/core/src/dsp/convert/stereo_to_mono.h +++ b/core/src/dsp/convert/stereo_to_mono.h @@ -9,7 +9,7 @@ namespace dsp::convert { StereoToMono(stream* in) { base_type::init(in); } - inline int process(int count, const stereo_t* in, float* out) { + static inline int process(int count, const stereo_t* in, float* out) { for (int i = 0; i < count; i++) { out[i] = (in[i].l + in[i].r) / 2.0f; } diff --git a/core/src/dsp/noise_reduction/noise_blanker.h b/core/src/dsp/noise_reduction/noise_blanker.h index bbbb89b8..5e84aaf9 100644 --- a/core/src/dsp/noise_reduction/noise_blanker.h +++ b/core/src/dsp/noise_reduction/noise_blanker.h @@ -37,21 +37,17 @@ namespace dsp::noise_reduction { inline int process(int count, complex_t* in, complex_t* out) { for (int i = 0; i < count; i++) { - // Get signal amplitude + // Get signal amplitude and pass value if null float inAmp = in[i].amplitude(); - - // Update average amplitude - float gain = 1.0f; - if (inAmp != 0.0f) { - amp = (amp * _invRate) + (inAmp * _rate); - float excess = inAmp / amp; - if (excess > _level) { - gain = 1.0f / excess; - } + if (!inAmp) { + out[i] = in[i]; } - - // Scale output by gain - out[i] = in[i] * gain; + + // Update running average of amplitude + amp = (_rate*inAmp) + (_invRate*amp); + + // Null out if spike (Note: ideally, it should try to guess the real data) + out[i] = (inAmp > _level*amp) ? complex_t{0.0f,0.0f} : in[i]; } return count; } diff --git a/decoder_modules/radio/src/demod.h b/decoder_modules/radio/src/demod.h index b250aefa..7d13bfe5 100644 --- a/decoder_modules/radio/src/demod.h +++ b/decoder_modules/radio/src/demod.h @@ -45,6 +45,7 @@ namespace demod { virtual int getDefaultDeemphasisMode() = 0; virtual bool getFMIFNRAllowed() = 0; virtual bool getNBAllowed() = 0; + virtual bool getAFNRAllowed() = 0; virtual dsp::stream* getOutput() = 0; }; } diff --git a/decoder_modules/radio/src/demodulators/am.h b/decoder_modules/radio/src/demodulators/am.h index 81d71806..7ac08832 100644 --- a/decoder_modules/radio/src/demodulators/am.h +++ b/decoder_modules/radio/src/demodulators/am.h @@ -86,6 +86,7 @@ namespace demod { int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } bool getFMIFNRAllowed() { return false; } bool getNBAllowed() { return false; } + bool getAFNRAllowed() { return false; } dsp::stream* getOutput() { return &demod.out; } private: diff --git a/decoder_modules/radio/src/demodulators/cw.h b/decoder_modules/radio/src/demodulators/cw.h index df2bdcfb..e8f9ac95 100644 --- a/decoder_modules/radio/src/demodulators/cw.h +++ b/decoder_modules/radio/src/demodulators/cw.h @@ -92,6 +92,7 @@ namespace demod { int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } bool getFMIFNRAllowed() { return false; } bool getNBAllowed() { return false; } + bool getAFNRAllowed() { return false; } dsp::stream* getOutput() { return &demod.out; } private: diff --git a/decoder_modules/radio/src/demodulators/dsb.h b/decoder_modules/radio/src/demodulators/dsb.h index 2c56565e..4c3bf907 100644 --- a/decoder_modules/radio/src/demodulators/dsb.h +++ b/decoder_modules/radio/src/demodulators/dsb.h @@ -79,6 +79,7 @@ namespace demod { int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } bool getFMIFNRAllowed() { return false; } bool getNBAllowed() { return true; } + bool getAFNRAllowed() { return false; } dsp::stream* getOutput() { return &demod.out; } private: diff --git a/decoder_modules/radio/src/demodulators/lsb.h b/decoder_modules/radio/src/demodulators/lsb.h index e442a87f..44b8784f 100644 --- a/decoder_modules/radio/src/demodulators/lsb.h +++ b/decoder_modules/radio/src/demodulators/lsb.h @@ -79,6 +79,7 @@ namespace demod { int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } bool getFMIFNRAllowed() { return false; } bool getNBAllowed() { return true; } + bool getAFNRAllowed() { return false; } dsp::stream* getOutput() { return &demod.out; } private: diff --git a/decoder_modules/radio/src/demodulators/nfm.h b/decoder_modules/radio/src/demodulators/nfm.h index c631c6b1..8f5f0326 100644 --- a/decoder_modules/radio/src/demodulators/nfm.h +++ b/decoder_modules/radio/src/demodulators/nfm.h @@ -75,6 +75,7 @@ namespace demod { int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } bool getFMIFNRAllowed() { return true; } bool getNBAllowed() { return false; } + bool getAFNRAllowed() { return false; } dsp::stream* getOutput() { return &demod.out; } private: diff --git a/decoder_modules/radio/src/demodulators/raw.h b/decoder_modules/radio/src/demodulators/raw.h index 094494de..bcc6f6bd 100644 --- a/decoder_modules/radio/src/demodulators/raw.h +++ b/decoder_modules/radio/src/demodulators/raw.h @@ -59,6 +59,7 @@ namespace demod { int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } bool getFMIFNRAllowed() { return false; } bool getNBAllowed() { return true; } + bool getAFNRAllowed() { return false; } dsp::stream* getOutput() { return &c2s.out; } private: diff --git a/decoder_modules/radio/src/demodulators/usb.h b/decoder_modules/radio/src/demodulators/usb.h index 41195ba6..050b69bb 100644 --- a/decoder_modules/radio/src/demodulators/usb.h +++ b/decoder_modules/radio/src/demodulators/usb.h @@ -80,6 +80,7 @@ namespace demod { int getDefaultDeemphasisMode() { return DEEMP_MODE_NONE; } bool getFMIFNRAllowed() { return false; } bool getNBAllowed() { return true; } + bool getAFNRAllowed() { return true; } dsp::stream* getOutput() { return &demod.out; } private: diff --git a/decoder_modules/radio/src/demodulators/wfm.h b/decoder_modules/radio/src/demodulators/wfm.h index 2761b28e..54aa59dc 100644 --- a/decoder_modules/radio/src/demodulators/wfm.h +++ b/decoder_modules/radio/src/demodulators/wfm.h @@ -130,6 +130,7 @@ namespace demod { int getDefaultDeemphasisMode() { return DEEMP_MODE_50US; } bool getFMIFNRAllowed() { return true; } bool getNBAllowed() { return false; } + bool getAFNRAllowed() { return false; } dsp::stream* getOutput() { return &demod.out; } // ============= DEDICATED FUNCTIONS ============= diff --git a/decoder_modules/radio/src/radio_module.h b/decoder_modules/radio/src/radio_module.h index c0605fd5..5bff7681 100644 --- a/decoder_modules/radio/src/radio_module.h +++ b/decoder_modules/radio/src/radio_module.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -83,9 +84,11 @@ public: resamp.init(NULL, 250000.0, 48000.0); deemp.init(NULL, 50e-6, 48000.0); + afNR.init(NULL, 1024); afChain.addBlock(&resamp, true); afChain.addBlock(&deemp, false); + afChain.addBlock(&afNR, false); // Initialize the sink srChangeHandler.ctx = this; @@ -247,6 +250,12 @@ private: if (!_this->nbEnabled && _this->enabled) { style::endDisabled(); } } + // Noise reduction + if (_this->afNRAllowed) { + if (ImGui::Checkbox(("Audio Noise Reduction##_radio_afnr_ena_" + _this->name).c_str(), &_this->afNREnabled)) { + _this->setAFNREnabled(_this->afNREnabled); + } + } // Squelch if (ImGui::Checkbox(("Squelch##_radio_sqelch_ena_" + _this->name).c_str(), &_this->squelchEnabled)) { @@ -370,6 +379,8 @@ private: fmIFPresetId = ifnrPresets.valueId(IFNR_PRESET_VOICE); nbAllowed = selectedDemod->getNBAllowed(); nbEnabled = false; + afNRAllowed = selectedDemod->getAFNRAllowed(); + afNREnabled = false; nbLevel = 0.0f; double ifSamplerate = selectedDemod->getIFSampleRate(); config.acquire(); @@ -411,6 +422,9 @@ private: if (config.conf[name][selectedDemod->getName()].contains("noiseBlankerLevel")) { nbLevel = config.conf[name][selectedDemod->getName()]["noiseBlankerLevel"]; } + if (config.conf[name][selectedDemod->getName()].contains("audioNoiseReductionEnabled")) { + nbEnabled = config.conf[name][selectedDemod->getName()]["audioNoiseReductionEnabled"]; + } config.release(); // Configure VFO @@ -446,7 +460,10 @@ private: afChain.enableBlock(&resamp, [=](dsp::stream* out){ stream.setInput(out); }); // Configure deemphasis - setDeemphasisMode(deempModes[deempId]); + setDeemphasisMode(deempAllowed ? deempModes[deempId] : DEEMP_MODE_NONE); + + // Configure AF NR + setAFNREnabled(afNRAllowed && afNREnabled); } else { // Disable everything if post processing is disabled @@ -508,6 +525,17 @@ private: config.release(true); } + void setAFNREnabled(bool enable) { + afNREnabled = enable; + if (!postProcEnabled || !selectedDemod) { return; } + afChain.setBlockEnabled(&afNR, afNREnabled, [=](dsp::stream* out){ stream.setInput(out); }); + + // Save config + config.acquire(); + config.conf[name][selectedDemod->getName()]["audioNoiseReductionEnabled"] = nbEnabled; + config.release(true); + } + void setNBEnabled(bool enable) { nbEnabled = enable; if (!selectedDemod) { return; } @@ -660,6 +688,7 @@ private: dsp::chain afChain; dsp::multirate::RationalResampler resamp; dsp::filter::Deemphasis deemp; + dsp::noise_reduction::Audio afNR; SinkManager::Stream stream; @@ -683,6 +712,9 @@ private: int deempId = 0; bool deempAllowed; + bool afNREnabled = false; + bool afNRAllowed; + bool FMIFNRAllowed; bool FMIFNREnabled = false; int fmIFPresetId;