From dedac01709aa770d14ee2973299fe7318ccb4adf Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Wed, 10 Aug 2016 14:02:25 -0400 Subject: [PATCH 1/4] Moving signal ceil/floor for squelch --- src/AppFrame.cpp | 4 ++++ src/demod/DemodulatorInstance.cpp | 8 +++++++ src/demod/DemodulatorInstance.h | 2 ++ src/demod/DemodulatorThread.cpp | 37 ++++++++++++++++++++++++++++++- src/demod/DemodulatorThread.h | 4 +++- 5 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/AppFrame.cpp b/src/AppFrame.cpp index a0de6c0..3e39091 100644 --- a/src/AppFrame.cpp +++ b/src/AppFrame.cpp @@ -1402,7 +1402,11 @@ void AppFrame::OnIdle(wxIdleEvent& event) { demodWaterfallCanvas->setBandwidth(demodBw); demodSpectrumCanvas->setBandwidth(demodBw); } + demodSignalMeter->setLevel(demod->getSignalLevel()); + demodSignalMeter->setMin(demod->getSignalFloor()); + demodSignalMeter->setMax(demod->getSignalCeil()); + demodGainMeter->setLevel(demod->getGain()); if (demodSignalMeter->inputChanged()) { demod->setSquelchLevel(demodSignalMeter->getInputValue()); diff --git a/src/demod/DemodulatorInstance.cpp b/src/demod/DemodulatorInstance.cpp index c3a22ee..7b770b3 100644 --- a/src/demod/DemodulatorInstance.cpp +++ b/src/demod/DemodulatorInstance.cpp @@ -257,6 +257,14 @@ float DemodulatorInstance::getSignalLevel() { return demodulatorThread->getSignalLevel(); } +float DemodulatorInstance::getSignalFloor() { + return demodulatorThread->getSignalFloor(); +} + +float DemodulatorInstance::getSignalCeil() { + return demodulatorThread->getSignalCeil(); +} + void DemodulatorInstance::setSquelchLevel(float signal_level_in) { demodulatorThread->setSquelchLevel(signal_level_in); wxGetApp().getDemodMgr().setLastSquelchLevel(signal_level_in); diff --git a/src/demod/DemodulatorInstance.h b/src/demod/DemodulatorInstance.h index 07d7c29..554ed48 100644 --- a/src/demod/DemodulatorInstance.h +++ b/src/demod/DemodulatorInstance.h @@ -63,6 +63,8 @@ public: void setSquelchEnabled(bool state); float getSignalLevel(); + float getSignalFloor(); + float getSignalCeil(); void setSquelchLevel(float signal_level_in); float getSquelchLevel(); diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index fcde477..e7ef7c6 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -15,7 +15,7 @@ DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) : IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100), - signalLevel(-100), squelchEnabled(false) { + signalLevel(-100), signalFloor(-30), signalCeil(30), squelchEnabled(false) { demodInstance = parent; muted.store(false); @@ -114,6 +114,33 @@ void DemodulatorThread::run() { currentSignalLevel = DEMOD_SIGNAL_MIN+1; } + float sampleTime = float(inp->data.size()) / float(inp->sampleRate); + float sf = signalFloor.load(), sc = signalCeil.load(), sl = squelchLevel.load(); + + if (currentSignalLevel > sc) { + sc = currentSignalLevel; + } + + if (currentSignalLevel < sf) { + sf = currentSignalLevel; + } + + if (sl+1.0f > sc) { + sc = sl+1.0f; + } + + if ((sf+2.0f) > sc) { + sc = sf+2.0f; + } + + sc -= (sc - (currentSignalLevel + 2.0f)) * sampleTime * 0.15f; + sf += ((currentSignalLevel - 5.0f) - sf) * sampleTime * 0.15f; + + signalFloor.store(sf); + signalCeil.store(sc); + +// std::cout << "sf:" << sf << "sc: " << sc << std::endl; + std::vector *inputData; inputData = &inp->data; @@ -330,6 +357,14 @@ float DemodulatorThread::getSignalLevel() { return signalLevel.load(); } +float DemodulatorThread::getSignalFloor() { + return signalFloor.load(); +} + +float DemodulatorThread::getSignalCeil() { + return signalCeil.load(); +} + void DemodulatorThread::setSquelchLevel(float signal_level_in) { if (!squelchEnabled) { squelchEnabled = true; diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 0892589..6a582b9 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -30,6 +30,8 @@ public: bool isMuted(); float getSignalLevel(); + float getSignalCeil(); + float getSignalFloor(); void setSquelchLevel(float signal_level_in); float getSquelchLevel(); @@ -46,7 +48,7 @@ protected: std::atomic_bool muted; std::atomic squelchLevel; - std::atomic signalLevel; + std::atomic signalLevel, signalFloor, signalCeil; bool squelchEnabled, squelchBreak; Modem *cModem = nullptr; From 606d41bc30d75e785e3a13d72c73990b9eac13b4 Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 12 Aug 2016 20:31:20 -0400 Subject: [PATCH 2/4] Make audio the signal level instead of I/Q.. Fix attack/decay base to sample time. --- src/demod/DemodulatorThread.cpp | 82 ++++++++++++++++----------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index e7ef7c6..347ad73 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -102,45 +102,6 @@ void DemodulatorThread::run() { continue; } - float currentSignalLevel = 0; - float accum = 0; - - for (std::vector::iterator i = inp->data.begin(); i != inp->data.end(); i++) { - accum += abMagnitude(0.948059448969, 0.392699081699, i->real, i->imag); - } - - currentSignalLevel = linearToDb(accum / float(inp->data.size())); - if (currentSignalLevel < DEMOD_SIGNAL_MIN+1) { - currentSignalLevel = DEMOD_SIGNAL_MIN+1; - } - - float sampleTime = float(inp->data.size()) / float(inp->sampleRate); - float sf = signalFloor.load(), sc = signalCeil.load(), sl = squelchLevel.load(); - - if (currentSignalLevel > sc) { - sc = currentSignalLevel; - } - - if (currentSignalLevel < sf) { - sf = currentSignalLevel; - } - - if (sl+1.0f > sc) { - sc = sl+1.0f; - } - - if ((sf+2.0f) > sc) { - sc = sf+2.0f; - } - - sc -= (sc - (currentSignalLevel + 2.0f)) * sampleTime * 0.15f; - sf += ((currentSignalLevel - 5.0f) - sf) * sampleTime * 0.15f; - - signalFloor.store(sf); - signalCeil.store(sc); - -// std::cout << "sf:" << sf << "sc: " << sc << std::endl; - std::vector *inputData; inputData = &inp->data; @@ -167,11 +128,50 @@ void DemodulatorThread::run() { } cModem->demodulate(cModemKit, &modemData, ati); + + float currentSignalLevel = 0; + float accum = 0; + float sampleTime = float(inp->data.size()) / float(inp->sampleRate); + + if (audioOutputQueue != nullptr && ati && ati->data.size()) { + for (std::vector::iterator i = ati->data.begin(); i != ati->data.end(); i++) { + accum += abMagnitude(0.948059448969, 0.392699081699, *i, 0.0); + } + + currentSignalLevel = linearToDb(accum / float(inp->data.size())); + if (currentSignalLevel < DEMOD_SIGNAL_MIN+1) { + currentSignalLevel = DEMOD_SIGNAL_MIN+1; + } + + float sf = signalFloor.load(), sc = signalCeil.load(), sl = squelchLevel.load(); + + if (currentSignalLevel > sc) { + sc = currentSignalLevel; + } + + if (currentSignalLevel < sf) { + sf = currentSignalLevel; + } + + if (sl+1.0f > sc) { + sc = sl+1.0f; + } + + if ((sf+2.0f) > sc) { + sc = sf+2.0f; + } + + sc -= (sc - (currentSignalLevel + 2.0f)) * sampleTime * 0.15f; + sf += ((currentSignalLevel - 5.0f) - sf) * sampleTime * 0.15f; + + signalFloor.store(sf); + signalCeil.store(sc); + } if (currentSignalLevel > signalLevel) { - signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5; + signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5 * sampleTime * 10.0; } else { - signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05; + signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05 * sampleTime * 10.0; } bool squelched = (squelchEnabled && (signalLevel < squelchLevel)); From 6ea2b5b8e81d824ee42a288f5d60a8bd147c000e Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 12 Aug 2016 21:34:34 -0400 Subject: [PATCH 3/4] More squelch tweaks; include I/Q dB and compare to audio for peak --- src/demod/DemodulatorThread.cpp | 30 ++++++++++++++++--------- src/process/SpectrumVisualProcessor.cpp | 2 +- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 347ad73..3ea60ca 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -130,18 +130,26 @@ void DemodulatorThread::run() { cModem->demodulate(cModemKit, &modemData, ati); float currentSignalLevel = 0; - float accum = 0; float sampleTime = float(inp->data.size()) / float(inp->sampleRate); if (audioOutputQueue != nullptr && ati && ati->data.size()) { - for (std::vector::iterator i = ati->data.begin(); i != ati->data.end(); i++) { - accum += abMagnitude(0.948059448969, 0.392699081699, *i, 0.0); + float accum = 0; + + for (auto i : ati->data) { + accum += abMagnitude(0.948059448969, 0.392699081699, i, 0.0); } + + float audioSignalLevel = linearToDb(accum / float(ati->data.size())); + + accum = 0; - currentSignalLevel = linearToDb(accum / float(inp->data.size())); - if (currentSignalLevel < DEMOD_SIGNAL_MIN+1) { - currentSignalLevel = DEMOD_SIGNAL_MIN+1; + for (auto i : inp->data) { + accum += abMagnitude(0.948059448969, 0.392699081699, i.real, i.imag); } + + float iqSignalLevel = linearToDb(accum / float(inp->data.size())); + + currentSignalLevel = iqSignalLevel>audioSignalLevel?iqSignalLevel:audioSignalLevel; float sf = signalFloor.load(), sc = signalCeil.load(), sl = squelchLevel.load(); @@ -161,7 +169,7 @@ void DemodulatorThread::run() { sc = sf+2.0f; } - sc -= (sc - (currentSignalLevel + 2.0f)) * sampleTime * 0.15f; + sc -= (sc - (currentSignalLevel + 2.0f)) * sampleTime * 0.05f; sf += ((currentSignalLevel - 5.0f) - sf) * sampleTime * 0.15f; signalFloor.store(sf); @@ -169,9 +177,9 @@ void DemodulatorThread::run() { } if (currentSignalLevel > signalLevel) { - signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5 * sampleTime * 10.0; + signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5; } else { - signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05 * sampleTime * 10.0; + signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05 * sampleTime * 30.0; } bool squelched = (squelchEnabled && (signalLevel < squelchLevel)); @@ -191,8 +199,8 @@ void DemodulatorThread::run() { if (audioOutputQueue != nullptr && ati && ati->data.size() && !squelched) { std::vector::iterator data_i; ati->peak = 0; - for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) { - float p = fabs(*data_i); + for (auto data_i : ati->data) { + float p = fabs(data_i); if (p > ati->peak) { ati->peak = p; } diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index 0ec0ff2..33efcde 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -313,7 +313,7 @@ void SpectrumVisualProcessor::process() { } if (!resampler || resampleBw != lastBandwidth || lastInputBandwidth != iqData->sampleRate) { - float As = 60.0f; + float As = 120.0f; if (resampler) { msresamp_crcf_destroy(resampler); From 2bbae7209f66712b94a758278e28103719857a5b Mon Sep 17 00:00:00 2001 From: "Charles J. Cliffe" Date: Fri, 12 Aug 2016 22:58:33 -0400 Subject: [PATCH 4/4] Solo squelch break focus lock/tweak --- src/demod/DemodulatorThread.cpp | 34 ++++++++++++++++++++----- src/demod/DemodulatorThread.h | 4 +++ src/process/SpectrumVisualProcessor.cpp | 2 +- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/demod/DemodulatorThread.cpp b/src/demod/DemodulatorThread.cpp index 3ea60ca..63414b1 100644 --- a/src/demod/DemodulatorThread.cpp +++ b/src/demod/DemodulatorThread.cpp @@ -13,7 +13,10 @@ #include #endif -DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) +std::atomic DemodulatorThread::squelchLock(nullptr); +std::mutex DemodulatorThread::squelchLockMutex; + +DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) : IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100), signalLevel(-100), signalFloor(-30), signalCeil(30), squelchEnabled(false) { @@ -23,6 +26,10 @@ DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent) } DemodulatorThread::~DemodulatorThread() { + std::lock_guard < std::mutex > lock(squelchLockMutex); + if (squelchLock.load() == demodInstance) { + squelchLock.store(nullptr); + } } void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBase *threadQueue) { @@ -182,16 +189,29 @@ void DemodulatorThread::run() { signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05 * sampleTime * 30.0; } - bool squelched = (squelchEnabled && (signalLevel < squelchLevel)); + bool squelched = (muted.load() || (squelchEnabled && (signalLevel < squelchLevel))); if (squelchEnabled) { if (!squelched && !squelchBreak) { - if (wxGetApp().getSoloMode() && !muted.load()) { - wxGetApp().getDemodMgr().setActiveDemodulator(demodInstance, false); - } - squelchBreak = true; - demodInstance->getVisualCue()->triggerSquelchBreak(120); + if (wxGetApp().getSoloMode()) { + std::lock_guard < std::mutex > lock(squelchLockMutex); + if (squelchLock.load() == nullptr) { + squelchLock.store(demodInstance); + wxGetApp().getDemodMgr().setActiveDemodulator(nullptr); + wxGetApp().getDemodMgr().setActiveDemodulator(demodInstance, false); + squelchBreak = true; + demodInstance->getVisualCue()->triggerSquelchBreak(120); + } + } else { + squelchBreak = true; + demodInstance->getVisualCue()->triggerSquelchBreak(120); + } + } else if (squelched && squelchBreak) { + std::lock_guard < std::mutex > lock(squelchLockMutex); + if (squelchLock.load() == demodInstance) { + squelchLock.store(nullptr); + } squelchBreak = false; } } diff --git a/src/demod/DemodulatorThread.h b/src/demod/DemodulatorThread.h index 6a582b9..5176c72 100644 --- a/src/demod/DemodulatorThread.h +++ b/src/demod/DemodulatorThread.h @@ -51,6 +51,10 @@ protected: std::atomic signalLevel, signalFloor, signalCeil; bool squelchEnabled, squelchBreak; + static std::atomic squelchLock; + static std::mutex squelchLockMutex; + + Modem *cModem = nullptr; ModemKit *cModemKit = nullptr; diff --git a/src/process/SpectrumVisualProcessor.cpp b/src/process/SpectrumVisualProcessor.cpp index 33efcde..ad80374 100644 --- a/src/process/SpectrumVisualProcessor.cpp +++ b/src/process/SpectrumVisualProcessor.cpp @@ -313,7 +313,7 @@ void SpectrumVisualProcessor::process() { } if (!resampler || resampleBw != lastBandwidth || lastInputBandwidth != iqData->sampleRate) { - float As = 120.0f; + float As = 480.0; if (resampler) { msresamp_crcf_destroy(resampler);