mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 17:58:43 -05:00
UDPSrc plugin: full squelch implementation
This commit is contained in:
parent
c6b58431fe
commit
32510091df
@ -15,14 +15,15 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "udpsrc.h"
|
||||
|
||||
#include <dsp/downchannelizer.h>
|
||||
#include <QUdpSocket>
|
||||
#include <QHostAddress>
|
||||
|
||||
#include "dsp/downchannelizer.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "util/db.h"
|
||||
|
||||
#include "udpsrcgui.h"
|
||||
#include "udpsrc.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(UDPSrc::MsgUDPSrcConfigure, Message)
|
||||
MESSAGE_CLASS_DEFINITION(UDPSrc::MsgUDPSrcConfigureImmediate, Message)
|
||||
@ -38,6 +39,12 @@ UDPSrc::UDPSrc(MessageQueue* uiMessageQueue, UDPSrcGUI* udpSrcGUI, BasebandSampl
|
||||
m_outMovingAverage(480, 1e-10),
|
||||
m_inMovingAverage(480, 1e-10),
|
||||
m_audioFifo(4, 24000),
|
||||
m_squelch(1e-6),
|
||||
m_squelchEnabled(true),
|
||||
m_squelchOpen(false),
|
||||
m_squelchOpenCount(0),
|
||||
m_squelchCloseCount(0),
|
||||
m_squelchThreshold(4800),
|
||||
m_settingsMutex(QMutex::Recursive)
|
||||
{
|
||||
setObjectName("UDPSrc");
|
||||
@ -144,7 +151,7 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
||||
{
|
||||
Complex ci;
|
||||
fftfilt::cmplx* sideband;
|
||||
Real l, r;
|
||||
double l, r;
|
||||
|
||||
m_sampleBuffer.clear();
|
||||
m_settingsMutex.lock();
|
||||
@ -157,17 +164,18 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
||||
if(m_interpolator.decimate(&m_sampleDistanceRemain, c, &ci))
|
||||
{
|
||||
double inMagSq = ci.real()*ci.real() + ci.imag()*ci.imag();
|
||||
//m_magsq = (inMagSq*m_gain*m_gain) / (1<<30);
|
||||
m_outMovingAverage.feed((inMagSq*m_gain*m_gain) / (1<<30));
|
||||
|
||||
m_inMovingAverage.feed(inMagSq / (1<<30));
|
||||
m_magsq = m_outMovingAverage.average();
|
||||
m_inMagsq = m_inMovingAverage.average();
|
||||
|
||||
Sample s(ci.real() * m_gain, ci.imag() * m_gain);
|
||||
m_sampleBuffer.push_back(s);
|
||||
Sample ss(ci.real(), ci.imag());
|
||||
m_sampleBuffer.push_back(ss);
|
||||
|
||||
m_sampleDistanceRemain += m_inputSampleRate / m_outputSampleRate;
|
||||
|
||||
if (m_sampleFormat == FormatLSB)
|
||||
calculateSquelch(m_inMagsq);
|
||||
|
||||
if (m_sampleFormat == FormatLSB) // binaural LSB
|
||||
{
|
||||
int n_out = UDPFilter->runSSB(ci, &sideband, false);
|
||||
|
||||
@ -175,13 +183,14 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
||||
{
|
||||
for (int i = 0; i < n_out; i++)
|
||||
{
|
||||
l = sideband[i].real();
|
||||
r = sideband[i].imag();
|
||||
m_udpBuffer->write(Sample(l, r));
|
||||
l = m_squelchOpen ? sideband[i].real() * m_gain : 0;
|
||||
r = m_squelchOpen ? sideband[i].imag() * m_gain : 0;
|
||||
m_udpBuffer->write(Sample(l, r));
|
||||
m_outMovingAverage.feed((l*l + r*r) / (1<<30));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_sampleFormat == FormatUSB)
|
||||
if (m_sampleFormat == FormatUSB) // binaural USB
|
||||
{
|
||||
int n_out = UDPFilter->runSSB(ci, &sideband, true);
|
||||
|
||||
@ -189,23 +198,26 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
||||
{
|
||||
for (int i = 0; i < n_out; i++)
|
||||
{
|
||||
l = sideband[i].real();
|
||||
r = sideband[i].imag();
|
||||
l = m_squelchOpen ? sideband[i].real() * m_gain : 0;
|
||||
r = m_squelchOpen ? sideband[i].imag() * m_gain : 0;
|
||||
m_udpBuffer->write(Sample(l, r));
|
||||
m_outMovingAverage.feed((l*l + r*r) / (1<<30));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_sampleFormat == FormatNFM)
|
||||
{
|
||||
Real demod = 32768.0f * m_phaseDiscri.phaseDiscriminator(ci);
|
||||
double demod = m_squelchOpen ? 32768.0 * m_phaseDiscri.phaseDiscriminator(ci) * m_gain : 0;
|
||||
m_udpBuffer->write(Sample(demod, demod));
|
||||
m_outMovingAverage.feed((demod * demod) / (1<<30));
|
||||
}
|
||||
else if (m_sampleFormat == FormatNFMMono)
|
||||
{
|
||||
FixReal demod = (FixReal) (32768.0f * m_phaseDiscri.phaseDiscriminator(ci));
|
||||
FixReal demod = m_squelchOpen ? (FixReal) (32768.0f * m_phaseDiscri.phaseDiscriminator(ci) * m_gain) : 0;
|
||||
m_udpBufferMono->write(demod);
|
||||
m_outMovingAverage.feed((demod * demod) / 1073741824.0);
|
||||
}
|
||||
else if (m_sampleFormat == FormatLSBMono)
|
||||
else if (m_sampleFormat == FormatLSBMono) // Monaural LSB
|
||||
{
|
||||
int n_out = UDPFilter->runSSB(ci, &sideband, false);
|
||||
|
||||
@ -213,12 +225,13 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
||||
{
|
||||
for (int i = 0; i < n_out; i++)
|
||||
{
|
||||
l = (sideband[i].real() + sideband[i].imag()) * 0.7;
|
||||
l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_gain : 0;
|
||||
m_udpBufferMono->write(l);
|
||||
m_outMovingAverage.feed((l * l) / (1<<30));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_sampleFormat == FormatUSBMono)
|
||||
else if (m_sampleFormat == FormatUSBMono) // Monaural USB
|
||||
{
|
||||
int n_out = UDPFilter->runSSB(ci, &sideband, true);
|
||||
|
||||
@ -226,20 +239,35 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
|
||||
{
|
||||
for (int i = 0; i < n_out; i++)
|
||||
{
|
||||
l = (sideband[i].real() + sideband[i].imag()) * 0.7;
|
||||
l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_gain : 0;
|
||||
m_udpBufferMono->write(l);
|
||||
m_outMovingAverage.feed((l * l) / (1<<30));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_sampleFormat == FormatAMMono)
|
||||
{
|
||||
FixReal demod = (FixReal) (32768.0f * sqrt(inMagSq) * m_gain);
|
||||
FixReal demod = m_squelchOpen ? (FixReal) (32768.0f * sqrt(inMagSq) * m_gain) : 0;
|
||||
m_udpBufferMono->write(demod);
|
||||
m_outMovingAverage.feed((demod * demod) / (1<<30));
|
||||
}
|
||||
else // Raw I/Q samples
|
||||
{
|
||||
m_udpBuffer->write(s);
|
||||
if (m_squelchOpen)
|
||||
{
|
||||
Sample s(ci.real() * m_gain, ci.imag() * m_gain);
|
||||
m_udpBuffer->write(s);
|
||||
m_outMovingAverage.feed((inMagSq*m_gain*m_gain) / (1<<30));
|
||||
}
|
||||
else
|
||||
{
|
||||
Sample s(0, 0);
|
||||
m_udpBuffer->write(s);
|
||||
m_outMovingAverage.feed(0);
|
||||
}
|
||||
}
|
||||
|
||||
m_magsq = m_outMovingAverage.average();
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,13 +348,18 @@ bool UDPSrc::handleMessage(const Message& cmd)
|
||||
m_volume = cfg.getVolume();
|
||||
}
|
||||
|
||||
m_squelch = CalcDb::powerFromdB(cfg.getSquelchDB());
|
||||
m_squelchEnabled = cfg.getSquelchEnabled();
|
||||
|
||||
m_settingsMutex.unlock();
|
||||
|
||||
qDebug() << "UDPSrc::handleMessage: MsgUDPSrcConfigureImmediate: "
|
||||
<< " m_audioActive: " << m_audioActive
|
||||
<< " m_audioStereo: " << m_audioStereo
|
||||
<< " m_gain: " << m_gain
|
||||
<< " m_volume: " << m_volume;
|
||||
<< " m_squelchEnabled: " << m_squelchEnabled
|
||||
<< " m_squelch: " << m_squelch
|
||||
<< " getSquelchDB: " << cfg.getSquelchDB();
|
||||
|
||||
return true;
|
||||
|
||||
@ -384,8 +417,9 @@ bool UDPSrc::handleMessage(const Message& cmd)
|
||||
m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
|
||||
UDPFilter->create_filter(0.0, (m_rfBandwidth / 2.0) / m_outputSampleRate);
|
||||
|
||||
m_inMovingAverage.resize(m_inputSampleRate * 0.01, 1e-10); // 10 ms
|
||||
m_inMovingAverage.resize(m_outputSampleRate * 0.01, 1e-10); // 10 ms
|
||||
m_outMovingAverage.resize(m_outputSampleRate * 0.01, 1e-10); // 10 ms
|
||||
m_squelchThreshold = m_outputSampleRate * 0.05; // 50 ms
|
||||
|
||||
m_settingsMutex.unlock();
|
||||
|
||||
|
@ -78,6 +78,7 @@ public:
|
||||
void setSpectrum(MessageQueue* messageQueue, bool enabled);
|
||||
double getMagSq() const { return m_magsq; }
|
||||
double getInMagSq() const { return m_inMagsq; }
|
||||
bool getSquelchOpen() const { return m_squelchOpen; }
|
||||
|
||||
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
|
||||
virtual void start();
|
||||
@ -161,7 +162,7 @@ protected:
|
||||
static MsgUDPSrcConfigureImmediate* create(
|
||||
bool audioActive,
|
||||
bool audioStereo,
|
||||
int boost,
|
||||
int gain,
|
||||
int volume,
|
||||
Real squelchDB,
|
||||
bool squelchEnabled)
|
||||
@ -169,7 +170,7 @@ protected:
|
||||
return new MsgUDPSrcConfigureImmediate(
|
||||
audioActive,
|
||||
audioStereo,
|
||||
boost,
|
||||
gain,
|
||||
volume,
|
||||
squelchDB,
|
||||
squelchEnabled);
|
||||
@ -269,7 +270,53 @@ protected:
|
||||
|
||||
PhaseDiscriminators m_phaseDiscri;
|
||||
|
||||
Real m_squelch; //!< squared magnitude
|
||||
bool m_squelchEnabled;
|
||||
bool m_squelchOpen;
|
||||
int m_squelchOpenCount;
|
||||
int m_squelchCloseCount;
|
||||
int m_squelchThreshold;
|
||||
|
||||
QMutex m_settingsMutex;
|
||||
|
||||
inline void calculateSquelch(double value)
|
||||
{
|
||||
if ((!m_squelchEnabled) || (value > m_squelch))
|
||||
{
|
||||
if (m_squelchOpenCount < m_squelchThreshold) {
|
||||
m_squelchOpenCount++;
|
||||
} else {
|
||||
m_squelchCloseCount = m_squelchThreshold;
|
||||
m_squelchOpen = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_squelchCloseCount > 0) {
|
||||
m_squelchCloseCount--;
|
||||
} else {
|
||||
m_squelchOpenCount = 0;
|
||||
m_squelchOpen = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void initSquelch(bool open)
|
||||
{
|
||||
if (open)
|
||||
{
|
||||
m_squelchOpen = true;
|
||||
m_squelchOpenCount = m_squelchThreshold;
|
||||
m_squelchCloseCount = m_squelchThreshold;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_squelchOpen = false;
|
||||
m_squelchOpenCount = 0;
|
||||
m_squelchCloseCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // INCLUDE_UDPSRC_H
|
||||
|
@ -172,7 +172,7 @@ bool UDPSrcGUI::deserialize(const QByteArray& data)
|
||||
ui->udpPort->setText(QString("%1").arg(s32tmp));
|
||||
d.readBlob(7, &bytetmp);
|
||||
ui->spectrumGUI->deserialize(bytetmp);
|
||||
d.readS32(16, &s32tmp, 10);
|
||||
d.readS32(8, &s32tmp, 10);
|
||||
ui->gain->setValue(s32tmp);
|
||||
ui->gainText->setText(tr("%1").arg(s32tmp/10.0, 0, 'f', 1));
|
||||
d.readS32(9, &s32tmp, 0);
|
||||
@ -231,6 +231,12 @@ void UDPSrcGUI::tick()
|
||||
ui->inputPower->setText(QString::number(inPowDb, 'f', 1));
|
||||
}
|
||||
|
||||
if (m_udpSrc->getSquelchOpen()) {
|
||||
ui->squelchLabel->setStyleSheet("QLabel { background-color : green; }");
|
||||
} else {
|
||||
ui->squelchLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
|
||||
}
|
||||
|
||||
m_tickCount++;
|
||||
}
|
||||
|
||||
@ -265,6 +271,7 @@ UDPSrcGUI::UDPSrcGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget*
|
||||
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
||||
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
|
||||
ui->squelchLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
|
||||
|
||||
ui->glSpectrum->setCenterFrequency(0);
|
||||
ui->glSpectrum->setSampleRate(ui->sampleRate->text().toInt());
|
||||
|
Loading…
Reference in New Issue
Block a user