diff --git a/plugins/channeltx/udpsink/udpsink.cpp b/plugins/channeltx/udpsink/udpsink.cpp index dbe8eed92..d16125e9a 100644 --- a/plugins/channeltx/udpsink/udpsink.cpp +++ b/plugins/channeltx/udpsink/udpsink.cpp @@ -28,12 +28,16 @@ UDPSink::UDPSink(MessageQueue* uiMessageQueue, UDPSinkGUI* udpSinkGUI, BasebandS m_udpSinkGUI(udpSinkGUI), m_spectrum(spectrum), m_spectrumEnabled(false), - m_spectrumChunkSize(2400), + m_spectrumChunkSize(2160), m_spectrumChunkCounter(0), m_magsq(1e-10), m_movingAverage(16, 0), m_sampleRateSum(0), m_sampleRateAvgCounter(0), + m_levelCalcCount(0), + m_peakLevel(0.0f), + m_levelSum(0.0f), + m_levelNbSamples(480), m_settingsMutex(QMutex::Recursive) { setObjectName("UDPSink"); @@ -110,11 +114,13 @@ void UDPSink::modulateSample() m_udpHandler.readSample(s); m_modSample.real(s.m_real); m_modSample.imag(s.m_imag); + calculateLevel(m_modSample); } else { m_modSample.real(0.0f); m_modSample.imag(0.0f); + calculateLevel(1e-10); } if (m_spectrum && m_spectrumEnabled && (m_spectrumChunkCounter < m_spectrumChunkSize - 1)) @@ -133,6 +139,45 @@ void UDPSink::modulateSample() } } +void UDPSink::calculateLevel(Real sample) +{ + if (m_levelCalcCount < m_levelNbSamples) + { + m_peakLevel = std::max(std::fabs(m_peakLevel), sample); + m_levelSum += sample * sample; + m_levelCalcCount++; + } + else + { + qreal rmsLevel = sqrt(m_levelSum / m_levelNbSamples); + //qDebug("NFMMod::calculateLevel: %f %f", rmsLevel, m_peakLevel); + emit levelChanged(rmsLevel, m_peakLevel, m_levelNbSamples); + m_peakLevel = 0.0f; + m_levelSum = 0.0f; + m_levelCalcCount = 0; + } +} + +void UDPSink::calculateLevel(Complex sample) +{ + Real t = std::abs(sample); + + if (m_levelCalcCount < m_levelNbSamples) + { + m_peakLevel = std::max(std::fabs(m_peakLevel), t); + m_levelSum += (t * t); + m_levelCalcCount++; + } + else + { + qreal rmsLevel = sqrt((m_levelSum/(1<<30)) / m_levelNbSamples); + emit levelChanged(rmsLevel, m_peakLevel / 32768.0, m_levelNbSamples); + m_peakLevel = 0.0f; + m_levelSum = 0.0f; + m_levelCalcCount = 0; + } +} + bool UDPSink::handleMessage(const Message& cmd) { if (UpChannelizer::MsgChannelizerNotification::match(cmd)) @@ -303,6 +348,10 @@ void UDPSink::apply(bool force) m_sampleRateAvgCounter = 0; m_spectrumChunkSize = m_config.m_inputSampleRate * 0.05; // 50 ms chunk m_spectrumChunkCounter = 0; + m_levelNbSamples = m_config.m_inputSampleRate * 0.01; // every 10 ms + m_levelCalcCount = 0; + m_peakLevel = 0.0f; + m_levelSum = 0.0f; m_settingsMutex.unlock(); } diff --git a/plugins/channeltx/udpsink/udpsink.h b/plugins/channeltx/udpsink/udpsink.h index 85c114be1..102a0e00b 100644 --- a/plugins/channeltx/udpsink/udpsink.h +++ b/plugins/channeltx/udpsink/udpsink.h @@ -68,6 +68,15 @@ public: bool force = false); void setSpectrum(MessageQueue* messageQueue, bool enabled); +signals: + /** + * Level changed + * \param rmsLevel RMS level in range 0.0 - 1.0 + * \param peakLevel Peak level in range 0.0 - 1.0 + * \param numSamples Number of audio samples analyzed + */ + void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples); + private: class MsgUDPSinkConfigure : public Message { MESSAGE_CLASS_DECLARATION @@ -206,12 +215,19 @@ private: double m_sampleRateSum; int m_sampleRateAvgCounter; + int m_levelCalcCount; + Real m_peakLevel; + double m_levelSum; + int m_levelNbSamples; + QMutex m_settingsMutex; static const int m_sampleRateAverageItems = 17; void apply(bool force); void modulateSample(); + void calculateLevel(Real sample); + void calculateLevel(Complex sample); }; diff --git a/plugins/channeltx/udpsink/udpsinkgui.cpp b/plugins/channeltx/udpsink/udpsinkgui.cpp index 10a0b5622..baa660018 100644 --- a/plugins/channeltx/udpsink/udpsinkgui.cpp +++ b/plugins/channeltx/udpsink/udpsinkgui.cpp @@ -260,6 +260,7 @@ UDPSinkGUI::UDPSinkGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* applySettings(true); connect(m_udpSink->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages())); + connect(m_udpSink, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int))); } UDPSinkGUI::~UDPSinkGUI()