diff --git a/plugins/channelrx/udpsrc/udpsrc.cpp b/plugins/channelrx/udpsrc/udpsrc.cpp index 6eb66dd19..0fafbb0b3 100644 --- a/plugins/channelrx/udpsrc/udpsrc.cpp +++ b/plugins/channelrx/udpsrc/udpsrc.cpp @@ -30,17 +30,9 @@ MESSAGE_CLASS_DEFINITION(UDPSrc::MsgUDPSrcConfigureImmediate, Message) MESSAGE_CLASS_DEFINITION(UDPSrc::MsgUDPSrcSpectrum, Message) UDPSrc::UDPSrc(MessageQueue* uiMessageQueue, UDPSrcGUI* udpSrcGUI, BasebandSampleSink* spectrum) : - m_udpPort(9999), - m_gain(1.0), - m_audioActive(false), - m_audioStereo(false), - m_volume(20), - m_fmDeviation(2500), 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), @@ -49,22 +41,17 @@ UDPSrc::UDPSrc(MessageQueue* uiMessageQueue, UDPSrcGUI* udpSrcGUI, BasebandSampl { setObjectName("UDPSrc"); - m_udpBuffer = new UDPSink(this, udpBlockSize, m_udpPort); - m_udpBufferMono = new UDPSink(this, udpBlockSize, m_udpPort); + m_udpBuffer = new UDPSink(this, udpBlockSize, m_config.m_udpPort); + m_udpBufferMono = new UDPSink(this, udpBlockSize, m_config.m_udpPort); m_audioSocket = new QUdpSocket(this); m_udpAudioBuf = new char[m_udpAudioPayloadSize]; m_audioBuffer.resize(1<<9); m_audioBufferFill = 0; - m_inputSampleRate = 96000; - m_sampleFormat = FormatS16LE; - m_outputSampleRate = 48000; - m_rfBandwidth = 32000; - m_audioPort = m_udpPort - 1; - m_nco.setFreq(0, m_inputSampleRate); - m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0); - m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate; + m_nco.setFreq(0, m_config.m_inputSampleRate); + m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.0); + m_sampleDistanceRemain = m_config.m_inputSampleRate / m_config.m_outputSampleRate; m_uiMessageQueue = uiMessageQueue; m_udpSrcGUI = udpSrcGUI; m_spectrum = spectrum; @@ -77,13 +64,13 @@ UDPSrc::UDPSrc(MessageQueue* uiMessageQueue, UDPSrcGUI* udpSrcGUI, BasebandSampl m_scale = 0; m_magsq = 0; m_inMagsq = 0; - UDPFilter = new fftfilt(0.0, (m_rfBandwidth / 2.0) / m_outputSampleRate, udpBlockSize); + UDPFilter = new fftfilt(0.0, (m_config.m_rfBandwidth / 2.0) / m_config.m_outputSampleRate, udpBlockSize); - m_phaseDiscri.setFMScaling((float) m_outputSampleRate / (2.0f * m_fmDeviation)); + m_phaseDiscri.setFMScaling((float) m_config. m_outputSampleRate / (2.0f * m_config.m_fmDeviation)); - if (m_audioSocket->bind(QHostAddress::LocalHost, m_audioPort)) + if (m_audioSocket->bind(QHostAddress::LocalHost, m_config.m_audioPort)) { - qDebug("UDPSrc::UDPSrc: bind audio socket to port %d", m_audioPort); + qDebug("UDPSrc::UDPSrc: bind audio socket to port %d", m_config.m_audioPort); connect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead()), Qt::QueuedConnection); } else @@ -101,9 +88,10 @@ UDPSrc::~UDPSrc() delete m_udpBufferMono; delete[] m_udpAudioBuf; if (UDPFilter) delete UDPFilter; - if (m_audioActive) DSPEngine::instance()->removeAudioSink(&m_audioFifo); + if (m_running.m_audioActive) DSPEngine::instance()->removeAudioSink(&m_audioFifo); } +/** what needs the "apply" button validation */ void UDPSrc::configure(MessageQueue* messageQueue, SampleFormat sampleFormat, Real outputSampleRate, @@ -111,7 +99,8 @@ void UDPSrc::configure(MessageQueue* messageQueue, int fmDeviation, QString& udpAddress, int udpPort, - int audioPort) + int audioPort, + bool force) { Message* cmd = MsgUDPSrcConfigure::create(sampleFormat, outputSampleRate, @@ -119,17 +108,21 @@ void UDPSrc::configure(MessageQueue* messageQueue, fmDeviation, udpAddress, udpPort, - audioPort); + audioPort, + force); messageQueue->push(cmd); } +/** changes applied immediately */ void UDPSrc::configureImmediate(MessageQueue* messageQueue, bool audioActive, bool audioStereo, Real boost, int volume, Real squelchDB, - bool squelchEnabled) + Real squelchGate, + bool squelchEnabled, + bool force) { Message* cmd = MsgUDPSrcConfigureImmediate::create( audioActive, @@ -137,7 +130,9 @@ void UDPSrc::configureImmediate(MessageQueue* messageQueue, boost, volume, squelchDB, - squelchEnabled); + squelchGate, + squelchEnabled, + force); messageQueue->push(cmd); } @@ -171,11 +166,11 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector: Sample ss(ci.real(), ci.imag()); m_sampleBuffer.push_back(ss); - m_sampleDistanceRemain += m_inputSampleRate / m_outputSampleRate; + m_sampleDistanceRemain += m_running.m_inputSampleRate / m_running.m_outputSampleRate; calculateSquelch(m_inMagsq); - if (m_sampleFormat == FormatLSB) // binaural LSB + if (m_running.m_sampleFormat == FormatLSB) // binaural LSB { int n_out = UDPFilter->runSSB(ci, &sideband, false); @@ -183,14 +178,14 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector: { for (int i = 0; i < n_out; i++) { - l = m_squelchOpen ? sideband[i].real() * m_gain : 0; - r = m_squelchOpen ? sideband[i].imag() * m_gain : 0; + l = m_squelchOpen ? sideband[i].real() * m_running.m_gain : 0; + r = m_squelchOpen ? sideband[i].imag() * m_running.m_gain : 0; m_udpBuffer->write(Sample(l, r)); m_outMovingAverage.feed((l*l + r*r) / (1<<30)); } } } - if (m_sampleFormat == FormatUSB) // binaural USB + if (m_running.m_sampleFormat == FormatUSB) // binaural USB { int n_out = UDPFilter->runSSB(ci, &sideband, true); @@ -198,26 +193,26 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector: { for (int i = 0; i < n_out; i++) { - l = m_squelchOpen ? sideband[i].real() * m_gain : 0; - r = m_squelchOpen ? sideband[i].imag() * m_gain : 0; + l = m_squelchOpen ? sideband[i].real() * m_running.m_gain : 0; + r = m_squelchOpen ? sideband[i].imag() * m_running.m_gain : 0; m_udpBuffer->write(Sample(l, r)); m_outMovingAverage.feed((l*l + r*r) / (1<<30)); } } } - else if (m_sampleFormat == FormatNFM) + else if (m_running.m_sampleFormat == FormatNFM) { - double demod = m_squelchOpen ? 32768.0 * m_phaseDiscri.phaseDiscriminator(ci) * m_gain : 0; + double demod = m_squelchOpen ? 32768.0 * m_phaseDiscri.phaseDiscriminator(ci) * m_running.m_gain : 0; m_udpBuffer->write(Sample(demod, demod)); m_outMovingAverage.feed((demod * demod) / (1<<30)); } - else if (m_sampleFormat == FormatNFMMono) + else if (m_running.m_sampleFormat == FormatNFMMono) { - FixReal demod = m_squelchOpen ? (FixReal) (32768.0f * m_phaseDiscri.phaseDiscriminator(ci) * m_gain) : 0; + FixReal demod = m_squelchOpen ? (FixReal) (32768.0f * m_phaseDiscri.phaseDiscriminator(ci) * m_running.m_gain) : 0; m_udpBufferMono->write(demod); m_outMovingAverage.feed((demod * demod) / 1073741824.0); } - else if (m_sampleFormat == FormatLSBMono) // Monaural LSB + else if (m_running.m_sampleFormat == FormatLSBMono) // Monaural LSB { int n_out = UDPFilter->runSSB(ci, &sideband, false); @@ -225,13 +220,13 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector: { for (int i = 0; i < n_out; i++) { - l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_gain : 0; + l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_running.m_gain : 0; m_udpBufferMono->write(l); m_outMovingAverage.feed((l * l) / (1<<30)); } } } - else if (m_sampleFormat == FormatUSBMono) // Monaural USB + else if (m_running.m_sampleFormat == FormatUSBMono) // Monaural USB { int n_out = UDPFilter->runSSB(ci, &sideband, true); @@ -239,15 +234,15 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector: { for (int i = 0; i < n_out; i++) { - l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_gain : 0; + l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_running.m_gain : 0; m_udpBufferMono->write(l); m_outMovingAverage.feed((l * l) / (1<<30)); } } } - else if (m_sampleFormat == FormatAMMono) + else if (m_running.m_sampleFormat == FormatAMMono) { - FixReal demod = m_squelchOpen ? (FixReal) (sqrt(inMagSq) * m_gain) : 0; + FixReal demod = m_squelchOpen ? (FixReal) (sqrt(inMagSq) * m_running.m_gain) : 0; m_udpBufferMono->write(demod); m_outMovingAverage.feed((demod * demod) / (1<<30)); } @@ -255,9 +250,9 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector: { if (m_squelchOpen) { - Sample s(ci.real() * m_gain, ci.imag() * m_gain); + Sample s(ci.real() * m_running.m_gain, ci.imag() * m_running.m_gain); m_udpBuffer->write(s); - m_outMovingAverage.feed((inMagSq*m_gain*m_gain) / (1<<30)); + m_outMovingAverage.feed((inMagSq*m_running.m_gain*m_running.m_gain) / (1<<30)); } else { @@ -298,68 +293,38 @@ bool UDPSrc::handleMessage(const Message& cmd) { DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd; - m_settingsMutex.lock(); + m_config.m_inputSampleRate = notif.getSampleRate(); + m_config.m_inputFrequencyOffset = notif.getFrequencyOffset(); - m_inputSampleRate = notif.getSampleRate(); - m_nco.setFreq(-notif.getFrequencyOffset(), m_inputSampleRate); - m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0); - m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate; + apply(false); - m_settingsMutex.unlock(); + qDebug() << "UDPSrc::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << m_config.m_inputSampleRate + << " frequencyOffset: " << notif.getFrequencyOffset(); - qDebug() << "UDPSrc::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << m_inputSampleRate - << " frequencyOffset: " << notif.getFrequencyOffset(); - - return true; + return true; } else if (MsgUDPSrcConfigureImmediate::match(cmd)) { MsgUDPSrcConfigureImmediate& cfg = (MsgUDPSrcConfigureImmediate&) cmd; - m_settingsMutex.lock(); + m_config.m_audioActive = cfg.getAudioActive(); + m_config.m_audioStereo = cfg.getAudioStereo(); + m_config.m_gain = cfg.getGain(); + m_config.m_volume = cfg.getVolume(); + m_config.m_squelch = CalcDb::powerFromdB(cfg.getSquelchDB()); + m_config.m_squelchGate = cfg.getSquelchGate(); + m_config.m_squelchEnabled = cfg.getSquelchEnabled(); - if (cfg.getAudioActive() != m_audioActive) - { - m_audioActive = cfg.getAudioActive(); - - if (m_audioActive) - { - m_audioBufferFill = 0; - DSPEngine::instance()->addAudioSink(&m_audioFifo); - } - else - { - DSPEngine::instance()->removeAudioSink(&m_audioFifo); - } - } - - if (cfg.getAudioStereo() != m_audioStereo) - { - m_audioStereo = cfg.getAudioStereo(); - } - - if (cfg.getGain() != m_gain) - { - m_gain = cfg.getGain(); - } - - if (cfg.getVolume() != m_volume) - { - m_volume = cfg.getVolume(); - } - - m_squelch = CalcDb::powerFromdB(cfg.getSquelchDB()); - m_squelchEnabled = cfg.getSquelchEnabled(); - - m_settingsMutex.unlock(); + apply(cfg.getForce()); qDebug() << "UDPSrc::handleMessage: MsgUDPSrcConfigureImmediate: " - << " m_audioActive: " << m_audioActive - << " m_audioStereo: " << m_audioStereo - << " m_gain: " << m_gain - << " m_squelchEnabled: " << m_squelchEnabled - << " m_squelch: " << m_squelch - << " getSquelchDB: " << cfg.getSquelchDB(); + << " m_audioActive: " << m_config.m_audioActive + << " m_audioStereo: " << m_config.m_audioStereo + << " m_gain: " << m_config.m_gain + << " m_squelchEnabled: " << m_config.m_squelchEnabled + << " m_squelch: " << m_config.m_squelch + << " getSquelchDB: " << cfg.getSquelchDB() + << " m_squelchGate" << m_config.m_squelchGate; return true; @@ -368,67 +333,22 @@ bool UDPSrc::handleMessage(const Message& cmd) { MsgUDPSrcConfigure& cfg = (MsgUDPSrcConfigure&) cmd; - m_settingsMutex.lock(); + m_config.m_sampleFormat = cfg.getSampleFormat(); + m_config.m_outputSampleRate = cfg.getOutputSampleRate(); + m_config.m_rfBandwidth = cfg.getRFBandwidth(); + m_config.m_udpAddressStr = cfg.getUDPAddress(); + m_config.m_udpPort = cfg.getUDPPort(); + m_config.m_audioPort = cfg.getAudioPort(); + m_config.m_fmDeviation = cfg.getFMDeviation(); - m_sampleFormat = cfg.getSampleFormat(); - m_outputSampleRate = cfg.getOutputSampleRate(); - m_rfBandwidth = cfg.getRFBandwidth(); + apply(cfg.getForce()); - if (cfg.getUDPAddress() != m_udpAddressStr) - { - m_udpAddressStr = cfg.getUDPAddress(); - m_udpBuffer->setAddress(m_udpAddressStr); - m_udpBufferMono->setAddress(m_udpAddressStr); - } - - if (cfg.getUDPPort() != m_udpPort) - { - m_udpPort = cfg.getUDPPort(); - m_udpBuffer->setPort(m_udpPort); - m_udpBufferMono->setPort(m_udpPort); - } - - if (cfg.getAudioPort() != m_audioPort) - { - m_audioPort = cfg.getAudioPort(); - - disconnect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead())); - delete m_audioSocket; - m_audioSocket = new QUdpSocket(this); - - if (m_audioSocket->bind(QHostAddress::LocalHost, m_audioPort)) - { - connect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead()), Qt::QueuedConnection); - qDebug("UDPSrc::handleMessage: audio socket bound to port %d", m_audioPort); - } - else - { - qWarning("UDPSrc::handleMessage: cannot bind audio socket"); - } - } - - if (cfg.getFMDeviation() != m_fmDeviation) - { - m_fmDeviation = cfg.getFMDeviation(); - m_phaseDiscri.setFMScaling((float) m_outputSampleRate / (2.0f * m_fmDeviation)); - } - - m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0); - m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate; - UDPFilter->create_filter(0.0, (m_rfBandwidth / 2.0) / m_outputSampleRate); - - 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(); - - qDebug() << "UDPSrc::handleMessage: MsgUDPSrcConfigure: m_sampleFormat: " << m_sampleFormat - << " m_outputSampleRate: " << m_outputSampleRate - << " m_rfBandwidth: " << m_rfBandwidth - << " m_udpAddressStr: " << m_udpAddressStr - << " m_udpPort: " << m_udpPort - << " m_audioPort: " << m_audioPort; + qDebug() << "UDPSrc::handleMessage: MsgUDPSrcConfigure: m_sampleFormat: " << m_config.m_sampleFormat + << " m_outputSampleRate: " << m_config.m_outputSampleRate + << " m_rfBandwidth: " << m_config.m_rfBandwidth + << " m_udpAddressStr: " << m_config.m_udpAddressStr + << " m_udpPort: " << m_config.m_udpPort + << " m_audioPort: " << m_config.m_audioPort; return true; } @@ -455,6 +375,83 @@ bool UDPSrc::handleMessage(const Message& cmd) } } +void UDPSrc::apply(bool force) +{ + m_settingsMutex.lock(); + + if ((m_config.m_inputSampleRate != m_running.m_inputSampleRate) || + (m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) || + (m_config.m_rfBandwidth != m_running.m_rfBandwidth) || + (m_config.m_outputSampleRate != m_running.m_outputSampleRate) || force) + { + m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate); + m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.0); + m_sampleDistanceRemain = m_config.m_inputSampleRate / m_config.m_outputSampleRate; + + m_squelchThreshold = m_config.m_outputSampleRate * m_config.m_squelchGate; + initSquelch(m_squelchOpen); + + m_inMovingAverage.resize(m_config.m_outputSampleRate * 0.01, 1e-10); // 10 ms + m_outMovingAverage.resize(m_config.m_outputSampleRate * 0.01, 1e-10); // 10 ms + } + + if ((m_config.m_audioActive != m_config.m_audioActive) || force) + { + if (m_config.m_audioActive) + { + m_audioBufferFill = 0; + DSPEngine::instance()->addAudioSink(&m_audioFifo); + } + else + { + DSPEngine::instance()->removeAudioSink(&m_audioFifo); + } + } + + if ((m_config.m_squelchGate != m_running.m_squelchGate) || force) + { + m_squelchThreshold = m_config.m_outputSampleRate * m_config.m_squelchGate; + } + + if ((m_config.m_udpAddressStr != m_running.m_udpAddressStr) || force) + { + m_udpBuffer->setAddress(m_config.m_udpAddressStr); + m_udpBufferMono->setAddress(m_config.m_udpAddressStr); + } + + if ((m_config.m_udpPort != m_running.m_udpPort) || force) + { + m_udpBuffer->setPort(m_config.m_udpPort); + m_udpBufferMono->setPort(m_config.m_udpPort); + } + + if ((m_config.m_audioPort != m_running.m_audioPort) || force) + { + disconnect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead())); + delete m_audioSocket; + m_audioSocket = new QUdpSocket(this); + + if (m_audioSocket->bind(QHostAddress::LocalHost, m_config.m_audioPort)) + { + connect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead()), Qt::QueuedConnection); + qDebug("UDPSrc::handleMessage: audio socket bound to port %d", m_config.m_audioPort); + } + else + { + qWarning("UDPSrc::handleMessage: cannot bind audio socket"); + } + } + + if ((m_config.m_fmDeviation != m_running.m_fmDeviation) || force) + { + m_phaseDiscri.setFMScaling((float) m_config.m_outputSampleRate / (2.0f * m_config.m_fmDeviation)); + } + + m_settingsMutex.unlock(); + + m_running = m_config; +} + void UDPSrc::audioReadyRead() { while (m_audioSocket->hasPendingDatagrams()) @@ -463,16 +460,16 @@ void UDPSrc::audioReadyRead() qint64 udpReadBytes = m_audioSocket->readDatagram(m_udpAudioBuf, pendingDataSize, 0, 0); //qDebug("UDPSrc::audioReadyRead: %lld", udpReadBytes); - if (m_audioActive) + if (m_running.m_audioActive) { - if (m_audioStereo) + if (m_running.m_audioStereo) { for (int i = 0; i < udpReadBytes - 3; i += 4) { qint16 l_sample = (qint16) *(&m_udpAudioBuf[i]); qint16 r_sample = (qint16) *(&m_udpAudioBuf[i+2]); - m_audioBuffer[m_audioBufferFill].l = l_sample * m_volume; - m_audioBuffer[m_audioBufferFill].r = r_sample * m_volume; + m_audioBuffer[m_audioBufferFill].l = l_sample * m_running.m_volume; + m_audioBuffer[m_audioBufferFill].r = r_sample * m_running.m_volume; ++m_audioBufferFill; if (m_audioBufferFill >= m_audioBuffer.size()) @@ -493,8 +490,8 @@ void UDPSrc::audioReadyRead() for (int i = 0; i < udpReadBytes - 1; i += 2) { qint16 sample = (qint16) *(&m_udpAudioBuf[i]); - m_audioBuffer[m_audioBufferFill].l = sample * m_volume; - m_audioBuffer[m_audioBufferFill].r = sample * m_volume; + m_audioBuffer[m_audioBufferFill].l = sample * m_running.m_volume; + m_audioBuffer[m_audioBufferFill].r = sample * m_running.m_volume; ++m_audioBufferFill; if (m_audioBufferFill >= m_audioBuffer.size()) diff --git a/plugins/channelrx/udpsrc/udpsrc.h b/plugins/channelrx/udpsrc/udpsrc.h index b445f30ff..49c5c8bf8 100644 --- a/plugins/channelrx/udpsrc/udpsrc.h +++ b/plugins/channelrx/udpsrc/udpsrc.h @@ -67,14 +67,17 @@ public: int fmDeviation, QString& udpAddress, int udpPort, - int audioPort); + int audioPort, + bool force); void configureImmediate(MessageQueue* messageQueue, bool audioActive, bool audioStereo, Real gain, int volume, Real squelchDB, - bool squelchEnabled); + Real squelchGate, + bool squelchEnabled, + bool force); void setSpectrum(MessageQueue* messageQueue, bool enabled); double getMagSq() const { return m_magsq; } double getInMagSq() const { return m_inMagsq; } @@ -102,6 +105,7 @@ protected: const QString& getUDPAddress() const { return m_udpAddress; } int getUDPPort() const { return m_udpPort; } int getAudioPort() const { return m_audioPort; } + bool getForce() const { return m_force; } static MsgUDPSrcConfigure* create(SampleFormat sampleFormat, @@ -110,7 +114,8 @@ protected: int fmDeviation, QString& udpAddress, int udpPort, - int audioPort) + int audioPort, + bool force) { return new MsgUDPSrcConfigure(sampleFormat, sampleRate, @@ -118,7 +123,8 @@ protected: fmDeviation, udpAddress, udpPort, - audioPort); + audioPort, + force); } private: @@ -129,6 +135,7 @@ protected: QString m_udpAddress; int m_udpPort; int m_audioPort; + bool m_force; MsgUDPSrcConfigure(SampleFormat sampleFormat, Real outputSampleRate, @@ -136,7 +143,8 @@ protected: int fmDeviation, QString& udpAddress, int udpPort, - int audioPort) : + int audioPort, + bool force) : Message(), m_sampleFormat(sampleFormat), m_outputSampleRate(outputSampleRate), @@ -144,7 +152,8 @@ protected: m_fmDeviation(fmDeviation), m_udpAddress(udpAddress), m_udpPort(udpPort), - m_audioPort(audioPort) + m_audioPort(audioPort), + m_force(force) { } }; @@ -157,7 +166,9 @@ protected: bool getAudioActive() const { return m_audioActive; } bool getAudioStereo() const { return m_audioStereo; } Real getSquelchDB() const { return m_squelchDB; } + Real getSquelchGate() const { return m_squelchGate; } bool getSquelchEnabled() const { return m_squelchEnabled; } + bool getForce() const { return m_force; } static MsgUDPSrcConfigureImmediate* create( bool audioActive, @@ -165,7 +176,9 @@ protected: int gain, int volume, Real squelchDB, - bool squelchEnabled) + Real squelchGate, + bool squelchEnabled, + bool force) { return new MsgUDPSrcConfigureImmediate( audioActive, @@ -173,7 +186,9 @@ protected: gain, volume, squelchDB, - squelchEnabled); + squelchGate, + squelchEnabled, + force); } private: @@ -182,7 +197,9 @@ protected: bool m_audioActive; bool m_audioStereo; Real m_squelchDB; + Real m_squelchGate; // seconds bool m_squelchEnabled; + bool m_force; MsgUDPSrcConfigureImmediate( bool audioActive, @@ -190,14 +207,18 @@ protected: Real gain, int volume, Real squelchDB, - bool squelchEnabled) : + Real squelchGate, + bool squelchEnabled, + bool force) : Message(), m_gain(gain), m_volume(volume), m_audioActive(audioActive), m_audioStereo(audioStereo), m_squelchDB(squelchDB), - m_squelchEnabled(squelchEnabled) + m_squelchGate(squelchGate), + m_squelchEnabled(squelchEnabled), + m_force(force) { } }; @@ -221,23 +242,54 @@ protected: { } }; + struct Config { + Real m_outputSampleRate; + SampleFormat m_sampleFormat; + Real m_inputSampleRate; + qint64 m_inputFrequencyOffset; + Real m_rfBandwidth; + int m_fmDeviation; + bool m_channelMute; + Real m_gain; + Real m_squelch; //!< squared magnitude + Real m_squelchGate; //!< seconds + bool m_squelchEnabled; + bool m_audioActive; + bool m_audioStereo; + int m_volume; + + QString m_udpAddressStr; + quint16 m_udpPort; + quint16 m_audioPort; + + Config() : + m_outputSampleRate(48000), + m_sampleFormat(FormatS16LE), + m_inputSampleRate(48000), + m_inputFrequencyOffset(0), + m_rfBandwidth(12500), + m_fmDeviation(2500), + m_channelMute(false), + m_gain(1.0), + m_squelch(1e-6), + m_squelchGate(0.0), + m_squelchEnabled(true), + m_audioActive(false), + m_audioStereo(false), + m_volume(20), + m_udpAddressStr("127.0.0.1"), + m_udpPort(9999), + m_audioPort(9998) + {} + }; + + Config m_config; + Config m_running; + MessageQueue* m_uiMessageQueue; UDPSrcGUI* m_udpSrcGUI; QUdpSocket *m_audioSocket; - int m_inputSampleRate; - - int m_sampleFormat; - Real m_outputSampleRate; - Real m_rfBandwidth; - QString m_udpAddressStr; - quint16 m_udpPort; - quint16 m_audioPort; - Real m_gain; - bool m_audioActive; - bool m_audioStereo; - int m_volume; - int m_fmDeviation; double m_magsq; double m_inMagsq; MovingAverage m_outMovingAverage; @@ -270,34 +322,54 @@ protected: PhaseDiscriminators m_phaseDiscri; - Real m_squelch; //!< squared magnitude - bool m_squelchEnabled; bool m_squelchOpen; int m_squelchOpenCount; int m_squelchCloseCount; - int m_squelchThreshold; + int m_squelchThreshold; //!< number of samples computed from given gate QMutex m_settingsMutex; + void apply(bool force); + inline void calculateSquelch(double value) { - if ((!m_squelchEnabled) || (value > m_squelch)) + if ((!m_running.m_squelchEnabled) || (value > m_running.m_squelch)) { - if (m_squelchOpenCount < m_squelchThreshold) { - m_squelchOpenCount++; - } else { - m_squelchCloseCount = m_squelchThreshold; + if (m_squelchThreshold == 0) + { m_squelchOpen = true; } + else + { + 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; + if (m_squelchThreshold == 0) + { m_squelchOpen = false; } + else + { + if (m_squelchCloseCount > 0) + { + m_squelchCloseCount--; + } + else + { + m_squelchOpenCount = 0; + m_squelchOpen = false; + } + } } } diff --git a/plugins/channelrx/udpsrc/udpsrcgui.cpp b/plugins/channelrx/udpsrc/udpsrcgui.cpp index 4636ba028..caf1f7302 100644 --- a/plugins/channelrx/udpsrc/udpsrcgui.cpp +++ b/plugins/channelrx/udpsrc/udpsrcgui.cpp @@ -197,8 +197,8 @@ bool UDPSrcGUI::deserialize(const QByteArray& data) blockApplySettings(false); m_channelMarker.blockSignals(false); - applySettingsImmediate(); - applySettings(); + applySettingsImmediate(true); + applySettings(true); return true; } else @@ -297,8 +297,8 @@ UDPSrcGUI::UDPSrcGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget* ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum); displaySettings(); - applySettingsImmediate(); - applySettings(); + applySettingsImmediate(true); + applySettings(true); } UDPSrcGUI::~UDPSrcGUI() @@ -323,9 +323,10 @@ void UDPSrcGUI::displaySettings() ui->gainText->setText(tr("%1").arg(ui->gain->value()/10.0, 0, 'f', 1)); ui->volumeText->setText(QString("%1").arg(ui->volume->value())); ui->squelchText->setText(tr("%1").arg(ui->squelch->value()*1.0, 0, 'f', 0)); + ui->squelchGateText->setText(tr("%1").arg(ui->squelchGate->value()*10.0, 0, 'f', 0)); } -void UDPSrcGUI::applySettingsImmediate() +void UDPSrcGUI::applySettingsImmediate(bool force) { if (m_doApplySettings) { @@ -340,12 +341,14 @@ void UDPSrcGUI::applySettingsImmediate() m_gain, m_volume, ui->squelch->value() * 1.0f, - ui->squelch->value() != -100); + ui->squelchGate->value() * 0.01f, + ui->squelch->value() != -100, + force); } } -void UDPSrcGUI::applySettings() +void UDPSrcGUI::applySettings(bool force) { if (m_doApplySettings) { @@ -461,7 +464,8 @@ void UDPSrcGUI::applySettings() fmDeviation, m_udpAddress, udpPort, - audioPort); + audioPort, + force); ui->applyBtn->setEnabled(false); } @@ -554,6 +558,12 @@ void UDPSrcGUI::on_squelch_valueChanged(int value) applySettingsImmediate(); } +void UDPSrcGUI::on_squelchGate_valueChanged(int value) +{ + ui->squelchGateText->setText(tr("%1").arg(value*10.0, 0, 'f', 0)); + applySettingsImmediate(); +} + void UDPSrcGUI::onWidgetRolled(QWidget* widget, bool rollDown) { if ((widget == ui->spectrumBox) && (m_udpSrc != 0)) diff --git a/plugins/channelrx/udpsrc/udpsrcgui.h b/plugins/channelrx/udpsrc/udpsrcgui.h index c7bcc019d..0b10102e5 100644 --- a/plugins/channelrx/udpsrc/udpsrcgui.h +++ b/plugins/channelrx/udpsrc/udpsrcgui.h @@ -75,6 +75,7 @@ private slots: void on_gain_valueChanged(int value); void on_volume_valueChanged(int value); void on_squelch_valueChanged(int value); + void on_squelchGate_valueChanged(int value); void tick(); private: @@ -111,8 +112,8 @@ private: virtual ~UDPSrcGUI(); void blockApplySettings(bool block); - void applySettings(); - void applySettingsImmediate(); + void applySettings(bool force = false); + void applySettingsImmediate(bool force = false); void displaySettings(); void leaveEvent(QEvent*); diff --git a/plugins/channelrx/udpsrc/udpsrcgui.ui b/plugins/channelrx/udpsrc/udpsrcgui.ui index fe1e46618..3d5a59027 100644 --- a/plugins/channelrx/udpsrc/udpsrcgui.ui +++ b/plugins/channelrx/udpsrc/udpsrcgui.ui @@ -236,6 +236,38 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 40 + 0 + + + + Input power (dB) to which squelch applies + + + -100.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + @@ -637,18 +669,40 @@ - + + + + 22 + 22 + + + + Squelch gate (ms) + + + 50 + + + 1 + + + 5 + + + + + - 40 + 24 0 - Input power (dB) to which squelch applies + Squelch gate (ms) - -100.0 + 000 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter