diff --git a/core/src/dsp/channel/rx_vfo.h b/core/src/dsp/channel/rx_vfo.h index 9bd933e..b1311b4 100644 --- a/core/src/dsp/channel/rx_vfo.h +++ b/core/src/dsp/channel/rx_vfo.h @@ -54,14 +54,13 @@ namespace dsp::channel { void setBandwidth(double bandwidth) { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); - base_type::tempStop(); + std::lock_guard lck2(filterMtx); _bandwidth = bandwidth; filterNeeded = (_bandwidth != _outSamplerate); if (filterNeeded) { generateTaps(); filter.setTaps(ftaps); } - base_type::tempStart(); } void setOffset(double offset) { @@ -87,7 +86,10 @@ namespace dsp::channel { return resamp.process(count, out, out); } count = resamp.process(count, out, out); - filter.process(count, out, out); + { + std::lock_guard lck(filterMtx); + filter.process(count, out, out); + } return count; } @@ -110,7 +112,6 @@ namespace dsp::channel { taps::free(ftaps); double filterWidth = _bandwidth / 2.0; ftaps = taps::lowPass(filterWidth, filterWidth * 0.1, _outSamplerate); - printf("New taps just dropped: %lf %lf %lf\n", filterWidth, filterWidth*0.1, _outSamplerate); } FrequencyXlator xlator; @@ -123,5 +124,7 @@ namespace dsp::channel { double _outSamplerate; double _bandwidth; double _offset; + + std::mutex filterMtx; }; } \ No newline at end of file diff --git a/core/src/dsp/demod/am.h b/core/src/dsp/demod/am.h index fca79a7..7102660 100644 --- a/core/src/dsp/demod/am.h +++ b/core/src/dsp/demod/am.h @@ -22,6 +22,9 @@ namespace dsp::demod { carrierAgc.init(NULL, 1.0, agcAttack, agcDecay, 10e6, 10.0); audioAgc.init(NULL, 1.0, agcAttack, agcDecay, 10e6, 10.0); dcBlock.init(NULL, dcBlockRate); + + audioAgc.out.free(); + dcBlock.out.free(); base_type::init(in); } diff --git a/core/src/dsp/demod/broadcast_fm.h b/core/src/dsp/demod/broadcast_fm.h index 54c2c01..ca751d6 100644 --- a/core/src/dsp/demod/broadcast_fm.h +++ b/core/src/dsp/demod/broadcast_fm.h @@ -52,6 +52,11 @@ namespace dsp::demod { l = buffer::alloc(STREAM_BUFFER_SIZE); r = buffer::alloc(STREAM_BUFFER_SIZE); + lprDelay.out.free(); + lmrDelay.out.free(); + arFir.out.free(); + alFir.out.free(); + base_type::init(in); } diff --git a/core/src/dsp/demod/ssb.h b/core/src/dsp/demod/ssb.h index 1d53816..b67feeb 100644 --- a/core/src/dsp/demod/ssb.h +++ b/core/src/dsp/demod/ssb.h @@ -22,8 +22,12 @@ namespace dsp::demod { _mode = mode; _bandwidth = bandwidth; _samplerate = samplerate; + xlator.init(NULL, getTranslation(), _samplerate); agc.init(NULL, 1.0, agcAttack, agcDecay, 10e6, 10.0); + + agc.out.free(); + base_type::init(in); } diff --git a/core/src/dsp/filter/fir.h b/core/src/dsp/filter/fir.h index 020aeb7..51b377b 100644 --- a/core/src/dsp/filter/fir.h +++ b/core/src/dsp/filter/fir.h @@ -33,12 +33,21 @@ namespace dsp::filter { std::lock_guard lck(base_type::ctrlMtx); base_type::tempStop(); + int oldTC = _taps.size; _taps = taps; - // Reset buffer + // Update start of buffer bufStart = &buffer[_taps.size - 1]; - buffer::clear(buffer, _taps.size - 1); + // Move existing data to make transition seemless + if (_taps.size < oldTC) { + memcpy(buffer, &buffer[oldTC - _taps.size], (_taps.size - 1) * sizeof(D)); + } + else if (_taps.size > oldTC) { + memcpy(&buffer[_taps.size - oldTC], buffer, (oldTC - 1) * sizeof(D)); + buffer::clear(buffer, _taps.size - oldTC); + } + base_type::tempStart(); } diff --git a/core/src/dsp/loop/agc.h b/core/src/dsp/loop/agc.h index 9c5a6ed..e20018b 100644 --- a/core/src/dsp/loop/agc.h +++ b/core/src/dsp/loop/agc.h @@ -19,7 +19,7 @@ namespace dsp::loop { _maxGain = maxGain; _maxOutputAmp = maxOutputAmp; _initGain = initGain; - gain = _initGain; + amp = _setPoint / _initGain; base_type::init(in); } @@ -64,14 +64,13 @@ namespace dsp::loop { void reset() { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); - gain = _initGain; - amp = 1.0f; + amp = _setPoint / _initGain; } inline int process(int count, T* in, T* out) { for (int i = 0; i < count; i++) { // Get signal amplitude - float inAmp; + float inAmp, gain; if constexpr (std::is_same_v) { inAmp = in[i].amplitude(); } @@ -85,6 +84,22 @@ namespace dsp::loop { gain = std::min(_setPoint / amp, _maxGain); } + // If clipping is detected look ahead and correct + if (inAmp*gain > _maxOutputAmp) { + float maxAmp = 0; + for (int j = i; j < count; j++) { + if constexpr (std::is_same_v) { + inAmp = in[i].amplitude(); + } + if constexpr (std::is_same_v) { + inAmp = fabsf(in[i]); + } + if (inAmp > maxAmp) { maxAmp = inAmp; } + } + amp = maxAmp; + gain = _setPoint / maxAmp; + } + // Scale output by gain out[i] = in[i] * gain; } @@ -112,7 +127,6 @@ namespace dsp::loop { float _maxOutputAmp; float _initGain; - float gain; float amp = 1.0; }; diff --git a/core/src/dsp/multirate/power_decimator.h b/core/src/dsp/multirate/power_decimator.h index f937e25..7e08c34 100644 --- a/core/src/dsp/multirate/power_decimator.h +++ b/core/src/dsp/multirate/power_decimator.h @@ -100,6 +100,7 @@ namespace dsp::multirate { for (int i = 0; i < stageCount; i++) { tap taps = taps::fromArray(plan.stages[i].tapcount, plan.stages[i].taps); auto fir = new filter::DecimatingFIR(NULL, taps, plan.stages[i].decimation); + fir->out.free(); decimTaps.push_back(taps); decimFirs.push_back(fir); } diff --git a/core/src/dsp/multirate/rational_resampler.h b/core/src/dsp/multirate/rational_resampler.h index 328cca4..2f61db2 100644 --- a/core/src/dsp/multirate/rational_resampler.h +++ b/core/src/dsp/multirate/rational_resampler.h @@ -27,6 +27,9 @@ namespace dsp::multirate { decim.init(NULL, 2); resamp.init(NULL, 1, 1, rtaps); + decim.out.free(); + resamp.out.free(); + // Proper configuration reconfigure(); diff --git a/core/src/dsp/noise_reduction/squelch.h b/core/src/dsp/noise_reduction/squelch.h index a663bcc..47e56fe 100644 --- a/core/src/dsp/noise_reduction/squelch.h +++ b/core/src/dsp/noise_reduction/squelch.h @@ -10,8 +10,16 @@ namespace dsp::noise_reduction { Squelch(stream* in, double level) {} + ~Squelch() { + if (!base_type::_block_init) { return; } + buffer::free(normBuffer); + } + void init(stream* in, double level) { _level = level; + + normBuffer = buffer::alloc(STREAM_BUFFER_SIZE); + base_type::init(in); } diff --git a/core/src/dsp/stream.h b/core/src/dsp/stream.h index e72df92..7a7205a 100644 --- a/core/src/dsp/stream.h +++ b/core/src/dsp/stream.h @@ -29,8 +29,7 @@ namespace dsp { } virtual ~stream() { - buffer::free(writeBuf); - buffer::free(readBuf); + free(); } virtual void setBufferSize(int samples) { @@ -115,6 +114,13 @@ namespace dsp { readerStop = false; } + void free() { + if (writeBuf) { buffer::free(writeBuf); } + if (readBuf) { buffer::free(readBuf); } + writeBuf = NULL; + readBuf = NULL; + } + T* writeBuf; T* readBuf; diff --git a/core/src/signal_path/vfo_manager.cpp b/core/src/signal_path/vfo_manager.cpp index 85f236c..f1743cb 100644 --- a/core/src/signal_path/vfo_manager.cpp +++ b/core/src/signal_path/vfo_manager.cpp @@ -4,6 +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; + _bandwidth = bandwidth; dspVFO = sigpath::iqFrontEnd.addVFO(name, sampleRate, bandwidth, offset); wtfVFO = new ImGui::WaterfallVFO; wtfVFO->setReference(reference); @@ -41,6 +42,8 @@ void VFOManager::VFO::setCenterOffset(double offset) { } void VFOManager::VFO::setBandwidth(double bandwidth, bool updateWaterfall) { + if (_bandwidth == bandwidth) { return; } + _bandwidth = bandwidth; if (updateWaterfall) { wtfVFO->setBandwidth(bandwidth); } dspVFO->setBandwidth(bandwidth); } diff --git a/core/src/signal_path/vfo_manager.h b/core/src/signal_path/vfo_manager.h index d8a65d8..f8d3169 100644 --- a/core/src/signal_path/vfo_manager.h +++ b/core/src/signal_path/vfo_manager.h @@ -35,6 +35,8 @@ public: private: std::string name; + double _bandwidth; + }; VFOManager::VFO* createVFO(std::string name, int reference, double offset, double bandwidth, double sampleRate, double minBandwidth, double maxBandwidth, bool bandwidthLocked); diff --git a/decoder_modules/radio/src/demodulators/am.h b/decoder_modules/radio/src/demodulators/am.h index 2bafeba..9b00e02 100644 --- a/decoder_modules/radio/src/demodulators/am.h +++ b/decoder_modules/radio/src/demodulators/am.h @@ -52,7 +52,7 @@ namespace demod { float menuWidth = ImGui::GetContentRegionAvail().x; ImGui::LeftLabel("AGC Attack"); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); - if (ImGui::SliderFloat(("##_radio_am_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 50.0f)) { + if (ImGui::SliderFloat(("##_radio_am_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 100.0f)) { demod.setAGCAttack(agcAttack / getIFSampleRate()); _config->acquire(); _config->conf[name][getName()]["agcAttack"] = agcAttack; @@ -60,7 +60,7 @@ namespace demod { } ImGui::LeftLabel("AGC Decay"); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); - if (ImGui::SliderFloat(("AGC Decay##_radio_am_agc_decay_" + name).c_str(), &agcDecay, 1.0f, 50.0f)) { + if (ImGui::SliderFloat(("AGC Decay##_radio_am_agc_decay_" + name).c_str(), &agcDecay, 1.0f, 20.0f)) { demod.setAGCDecay(agcDecay / getIFSampleRate()); _config->acquire(); _config->conf[name][getName()]["agcDecay"] = agcDecay; @@ -109,7 +109,7 @@ namespace demod { ConfigManager* _config = NULL; - float agcAttack = 40.0f; + float agcAttack = 50.0f; float agcDecay = 5.0f; bool carrierAgc = false; diff --git a/decoder_modules/radio/src/demodulators/cw.h b/decoder_modules/radio/src/demodulators/cw.h index 67b392e..a44c46b 100644 --- a/decoder_modules/radio/src/demodulators/cw.h +++ b/decoder_modules/radio/src/demodulators/cw.h @@ -62,7 +62,7 @@ namespace demod { float menuWidth = ImGui::GetContentRegionAvail().x; ImGui::LeftLabel("AGC Attack"); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); - if (ImGui::SliderFloat(("##_radio_cw_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 50.0f)) { + if (ImGui::SliderFloat(("##_radio_cw_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 100.0f)) { agc.setAttack(agcAttack / getIFSampleRate()); _config->acquire(); _config->conf[name][getName()]["agcAttack"] = agcAttack; @@ -70,7 +70,7 @@ namespace demod { } ImGui::LeftLabel("AGC Decay"); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); - if (ImGui::SliderFloat(("AGC Decay##_radio_cw_agc_decay_" + name).c_str(), &agcDecay, 1.0f, 50.0f)) { + if (ImGui::SliderFloat(("AGC Decay##_radio_cw_agc_decay_" + name).c_str(), &agcDecay, 1.0f, 20.0f)) { agc.setDecay(agcDecay / getIFSampleRate()); _config->acquire(); _config->conf[name][getName()]["agcDecay"] = agcDecay; @@ -101,7 +101,7 @@ namespace demod { const char* getName() { return "CW"; } double getIFSampleRate() { return 3000.0; } double getAFSampleRate() { return getIFSampleRate(); } - double getDefaultBandwidth() { return 500.0; } + double getDefaultBandwidth() { return 200.0; } double getMinBandwidth() { return 50.0; } double getMaxBandwidth() { return 500.0; } bool getBandwidthLocked() { return false; } @@ -126,7 +126,7 @@ namespace demod { std::string name; - float agcAttack = 40.0f; + float agcAttack = 50.0f; float agcDecay = 5.0f; int tone = 800; double _bandwidth; diff --git a/decoder_modules/radio/src/demodulators/dsb.h b/decoder_modules/radio/src/demodulators/dsb.h index 50cab85..053abe0 100644 --- a/decoder_modules/radio/src/demodulators/dsb.h +++ b/decoder_modules/radio/src/demodulators/dsb.h @@ -49,7 +49,7 @@ namespace demod { float menuWidth = ImGui::GetContentRegionAvail().x; ImGui::LeftLabel("AGC Attack"); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); - if (ImGui::SliderFloat(("##_radio_dsb_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 50.0f)) { + if (ImGui::SliderFloat(("##_radio_dsb_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 100.0f)) { demod.setAGCAttack(agcAttack / getIFSampleRate()); _config->acquire(); _config->conf[name][getName()]["agcAttack"] = agcAttack; @@ -57,7 +57,7 @@ namespace demod { } ImGui::LeftLabel("AGC Decay"); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); - if (ImGui::SliderFloat(("AGC Decay##_radio_dsb_agc_decay_" + name).c_str(), &agcDecay, 1.0f, 50.0f)) { + if (ImGui::SliderFloat(("AGC Decay##_radio_dsb_agc_decay_" + name).c_str(), &agcDecay, 1.0f, 20.0f)) { demod.setAGCDecay(agcDecay / getIFSampleRate()); _config->acquire(); _config->conf[name][getName()]["agcDecay"] = agcDecay; @@ -102,7 +102,7 @@ namespace demod { ConfigManager* _config; - float agcAttack = 40.0f; + float agcAttack = 50.0f; float agcDecay = 5.0f; std::string name; diff --git a/decoder_modules/radio/src/demodulators/lsb.h b/decoder_modules/radio/src/demodulators/lsb.h index 3652374..ffffd05 100644 --- a/decoder_modules/radio/src/demodulators/lsb.h +++ b/decoder_modules/radio/src/demodulators/lsb.h @@ -49,7 +49,7 @@ namespace demod { float menuWidth = ImGui::GetContentRegionAvail().x; ImGui::LeftLabel("AGC Attack"); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); - if (ImGui::SliderFloat(("##_radio_lsb_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 50.0f)) { + if (ImGui::SliderFloat(("##_radio_lsb_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 100.0f)) { demod.setAGCAttack(agcAttack / getIFSampleRate()); _config->acquire(); _config->conf[name][getName()]["agcAttack"] = agcAttack; @@ -57,7 +57,7 @@ namespace demod { } ImGui::LeftLabel("AGC Decay"); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); - if (ImGui::SliderFloat(("AGC Decay##_radio_lsb_agc_decay_" + name).c_str(), &agcDecay, 1.0f, 50.0f)) { + if (ImGui::SliderFloat(("AGC Decay##_radio_lsb_agc_decay_" + name).c_str(), &agcDecay, 1.0f, 20.0f)) { demod.setAGCDecay(agcDecay / getIFSampleRate()); _config->acquire(); _config->conf[name][getName()]["agcDecay"] = agcDecay; @@ -102,7 +102,7 @@ namespace demod { ConfigManager* _config; - float agcAttack = 40.0f; + float agcAttack = 50.0f; float agcDecay = 5.0f; std::string name; diff --git a/decoder_modules/radio/src/demodulators/usb.h b/decoder_modules/radio/src/demodulators/usb.h index a802d85..82f8683 100644 --- a/decoder_modules/radio/src/demodulators/usb.h +++ b/decoder_modules/radio/src/demodulators/usb.h @@ -49,7 +49,7 @@ namespace demod { float menuWidth = ImGui::GetContentRegionAvail().x; ImGui::LeftLabel("AGC Attack"); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); - if (ImGui::SliderFloat(("##_radio_usb_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 50.0f)) { + if (ImGui::SliderFloat(("##_radio_usb_agc_attack_" + name).c_str(), &agcAttack, 1.0f, 100.0f)) { demod.setAGCAttack(agcAttack / getIFSampleRate()); _config->acquire(); _config->conf[name][getName()]["agcAttack"] = agcAttack; @@ -57,7 +57,7 @@ namespace demod { } ImGui::LeftLabel("AGC Decay"); ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); - if (ImGui::SliderFloat(("AGC Decay##_radio_usb_agc_decay_" + name).c_str(), &agcDecay, 1.0f, 50.0f)) { + if (ImGui::SliderFloat(("AGC Decay##_radio_usb_agc_decay_" + name).c_str(), &agcDecay, 1.0f, 20.0f)) { demod.setAGCDecay(agcDecay / getIFSampleRate()); _config->acquire(); _config->conf[name][getName()]["agcDecay"] = agcDecay; @@ -102,7 +102,7 @@ namespace demod { ConfigManager* _config; - float agcAttack = 40.0f; + float agcAttack = 50.0f; float agcDecay = 5.0f; std::string name;