mirror of
https://github.com/cjcliffe/CubicSDR.git
synced 2025-09-04 06:07:49 -04:00
Merge pull request #422 from cjcliffe/squelch_improved
Squelch Improvements
This commit is contained in:
commit
1fd23b6d33
@ -1402,7 +1402,11 @@ void AppFrame::OnIdle(wxIdleEvent& event) {
|
|||||||
demodWaterfallCanvas->setBandwidth(demodBw);
|
demodWaterfallCanvas->setBandwidth(demodBw);
|
||||||
demodSpectrumCanvas->setBandwidth(demodBw);
|
demodSpectrumCanvas->setBandwidth(demodBw);
|
||||||
}
|
}
|
||||||
|
|
||||||
demodSignalMeter->setLevel(demod->getSignalLevel());
|
demodSignalMeter->setLevel(demod->getSignalLevel());
|
||||||
|
demodSignalMeter->setMin(demod->getSignalFloor());
|
||||||
|
demodSignalMeter->setMax(demod->getSignalCeil());
|
||||||
|
|
||||||
demodGainMeter->setLevel(demod->getGain());
|
demodGainMeter->setLevel(demod->getGain());
|
||||||
if (demodSignalMeter->inputChanged()) {
|
if (demodSignalMeter->inputChanged()) {
|
||||||
demod->setSquelchLevel(demodSignalMeter->getInputValue());
|
demod->setSquelchLevel(demodSignalMeter->getInputValue());
|
||||||
|
@ -257,6 +257,14 @@ float DemodulatorInstance::getSignalLevel() {
|
|||||||
return demodulatorThread->getSignalLevel();
|
return demodulatorThread->getSignalLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float DemodulatorInstance::getSignalFloor() {
|
||||||
|
return demodulatorThread->getSignalFloor();
|
||||||
|
}
|
||||||
|
|
||||||
|
float DemodulatorInstance::getSignalCeil() {
|
||||||
|
return demodulatorThread->getSignalCeil();
|
||||||
|
}
|
||||||
|
|
||||||
void DemodulatorInstance::setSquelchLevel(float signal_level_in) {
|
void DemodulatorInstance::setSquelchLevel(float signal_level_in) {
|
||||||
demodulatorThread->setSquelchLevel(signal_level_in);
|
demodulatorThread->setSquelchLevel(signal_level_in);
|
||||||
wxGetApp().getDemodMgr().setLastSquelchLevel(signal_level_in);
|
wxGetApp().getDemodMgr().setLastSquelchLevel(signal_level_in);
|
||||||
|
@ -63,6 +63,8 @@ public:
|
|||||||
void setSquelchEnabled(bool state);
|
void setSquelchEnabled(bool state);
|
||||||
|
|
||||||
float getSignalLevel();
|
float getSignalLevel();
|
||||||
|
float getSignalFloor();
|
||||||
|
float getSignalCeil();
|
||||||
void setSquelchLevel(float signal_level_in);
|
void setSquelchLevel(float signal_level_in);
|
||||||
float getSquelchLevel();
|
float getSquelchLevel();
|
||||||
|
|
||||||
|
@ -13,9 +13,12 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent)
|
std::atomic<DemodulatorInstance *> DemodulatorThread::squelchLock(nullptr);
|
||||||
|
std::mutex DemodulatorThread::squelchLockMutex;
|
||||||
|
|
||||||
|
DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent)
|
||||||
: IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100),
|
: IOThread(), outputBuffers("DemodulatorThreadBuffers"), squelchLevel(-100),
|
||||||
signalLevel(-100), squelchEnabled(false) {
|
signalLevel(-100), signalFloor(-30), signalCeil(30), squelchEnabled(false) {
|
||||||
|
|
||||||
demodInstance = parent;
|
demodInstance = parent;
|
||||||
muted.store(false);
|
muted.store(false);
|
||||||
@ -23,6 +26,10 @@ DemodulatorThread::DemodulatorThread(DemodulatorInstance *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorThread::~DemodulatorThread() {
|
DemodulatorThread::~DemodulatorThread() {
|
||||||
|
std::lock_guard < std::mutex > lock(squelchLockMutex);
|
||||||
|
if (squelchLock.load() == demodInstance) {
|
||||||
|
squelchLock.store(nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBase *threadQueue) {
|
void DemodulatorThread::onBindOutput(std::string name, ThreadQueueBase *threadQueue) {
|
||||||
@ -102,18 +109,6 @@ void DemodulatorThread::run() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
float currentSignalLevel = 0;
|
|
||||||
float accum = 0;
|
|
||||||
|
|
||||||
for (std::vector<liquid_float_complex>::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<liquid_float_complex> *inputData;
|
std::vector<liquid_float_complex> *inputData;
|
||||||
|
|
||||||
inputData = &inp->data;
|
inputData = &inp->data;
|
||||||
@ -140,23 +135,83 @@ void DemodulatorThread::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cModem->demodulate(cModemKit, &modemData, ati);
|
cModem->demodulate(cModemKit, &modemData, ati);
|
||||||
|
|
||||||
|
float currentSignalLevel = 0;
|
||||||
|
float sampleTime = float(inp->data.size()) / float(inp->sampleRate);
|
||||||
|
|
||||||
|
if (audioOutputQueue != nullptr && ati && ati->data.size()) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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.05f;
|
||||||
|
sf += ((currentSignalLevel - 5.0f) - sf) * sampleTime * 0.15f;
|
||||||
|
|
||||||
|
signalFloor.store(sf);
|
||||||
|
signalCeil.store(sc);
|
||||||
|
}
|
||||||
|
|
||||||
if (currentSignalLevel > signalLevel) {
|
if (currentSignalLevel > signalLevel) {
|
||||||
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5;
|
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.5;
|
||||||
} else {
|
} else {
|
||||||
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05;
|
signalLevel = signalLevel + (currentSignalLevel - signalLevel) * 0.05 * sampleTime * 30.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool squelched = (squelchEnabled && (signalLevel < squelchLevel));
|
bool squelched = (muted.load() || (squelchEnabled && (signalLevel < squelchLevel)));
|
||||||
|
|
||||||
if (squelchEnabled) {
|
if (squelchEnabled) {
|
||||||
if (!squelched && !squelchBreak) {
|
if (!squelched && !squelchBreak) {
|
||||||
if (wxGetApp().getSoloMode() && !muted.load()) {
|
if (wxGetApp().getSoloMode()) {
|
||||||
wxGetApp().getDemodMgr().setActiveDemodulator(demodInstance, false);
|
std::lock_guard < std::mutex > lock(squelchLockMutex);
|
||||||
}
|
if (squelchLock.load() == nullptr) {
|
||||||
squelchBreak = true;
|
squelchLock.store(demodInstance);
|
||||||
demodInstance->getVisualCue()->triggerSquelchBreak(120);
|
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) {
|
} else if (squelched && squelchBreak) {
|
||||||
|
std::lock_guard < std::mutex > lock(squelchLockMutex);
|
||||||
|
if (squelchLock.load() == demodInstance) {
|
||||||
|
squelchLock.store(nullptr);
|
||||||
|
}
|
||||||
squelchBreak = false;
|
squelchBreak = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,8 +219,8 @@ void DemodulatorThread::run() {
|
|||||||
if (audioOutputQueue != nullptr && ati && ati->data.size() && !squelched) {
|
if (audioOutputQueue != nullptr && ati && ati->data.size() && !squelched) {
|
||||||
std::vector<float>::iterator data_i;
|
std::vector<float>::iterator data_i;
|
||||||
ati->peak = 0;
|
ati->peak = 0;
|
||||||
for (data_i = ati->data.begin(); data_i != ati->data.end(); data_i++) {
|
for (auto data_i : ati->data) {
|
||||||
float p = fabs(*data_i);
|
float p = fabs(data_i);
|
||||||
if (p > ati->peak) {
|
if (p > ati->peak) {
|
||||||
ati->peak = p;
|
ati->peak = p;
|
||||||
}
|
}
|
||||||
@ -330,6 +385,14 @@ float DemodulatorThread::getSignalLevel() {
|
|||||||
return signalLevel.load();
|
return signalLevel.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float DemodulatorThread::getSignalFloor() {
|
||||||
|
return signalFloor.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
float DemodulatorThread::getSignalCeil() {
|
||||||
|
return signalCeil.load();
|
||||||
|
}
|
||||||
|
|
||||||
void DemodulatorThread::setSquelchLevel(float signal_level_in) {
|
void DemodulatorThread::setSquelchLevel(float signal_level_in) {
|
||||||
if (!squelchEnabled) {
|
if (!squelchEnabled) {
|
||||||
squelchEnabled = true;
|
squelchEnabled = true;
|
||||||
|
@ -30,6 +30,8 @@ public:
|
|||||||
bool isMuted();
|
bool isMuted();
|
||||||
|
|
||||||
float getSignalLevel();
|
float getSignalLevel();
|
||||||
|
float getSignalCeil();
|
||||||
|
float getSignalFloor();
|
||||||
void setSquelchLevel(float signal_level_in);
|
void setSquelchLevel(float signal_level_in);
|
||||||
float getSquelchLevel();
|
float getSquelchLevel();
|
||||||
|
|
||||||
@ -46,9 +48,13 @@ protected:
|
|||||||
std::atomic_bool muted;
|
std::atomic_bool muted;
|
||||||
|
|
||||||
std::atomic<float> squelchLevel;
|
std::atomic<float> squelchLevel;
|
||||||
std::atomic<float> signalLevel;
|
std::atomic<float> signalLevel, signalFloor, signalCeil;
|
||||||
bool squelchEnabled, squelchBreak;
|
bool squelchEnabled, squelchBreak;
|
||||||
|
|
||||||
|
static std::atomic<DemodulatorInstance *> squelchLock;
|
||||||
|
static std::mutex squelchLockMutex;
|
||||||
|
|
||||||
|
|
||||||
Modem *cModem = nullptr;
|
Modem *cModem = nullptr;
|
||||||
ModemKit *cModemKit = nullptr;
|
ModemKit *cModemKit = nullptr;
|
||||||
|
|
||||||
|
@ -313,7 +313,7 @@ void SpectrumVisualProcessor::process() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!resampler || resampleBw != lastBandwidth || lastInputBandwidth != iqData->sampleRate) {
|
if (!resampler || resampleBw != lastBandwidth || lastInputBandwidth != iqData->sampleRate) {
|
||||||
float As = 60.0f;
|
float As = 480.0;
|
||||||
|
|
||||||
if (resampler) {
|
if (resampler) {
|
||||||
msresamp_crcf_destroy(resampler);
|
msresamp_crcf_destroy(resampler);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user