1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-02-03 09:44:01 -05:00

FT8 demod: volume meter

This commit is contained in:
f4exb 2023-01-16 21:51:26 +01:00
parent 809e0bccd4
commit d6cafa08c5
8 changed files with 114 additions and 16 deletions

View File

@ -746,5 +746,5 @@ void FT8Demod::handleIndexInDeviceSetChanged(int index)
.arg(m_deviceAPI->getDeviceSetIndex())
.arg(index);
m_basebandSink->setFifoLabel(fifoLabel);
m_basebandSink->setAudioFifoLabel(fifoLabel);
m_basebandSink->setAudioFifoLabel(fifoLabel);
}

View File

@ -136,6 +136,9 @@ public:
SWGSDRangel::SWGChannelSettings& response);
uint32_t getNumberOfDeviceStreams() const;
void setLevelMeter(QObject *levelMeter) {
connect(m_basebandSink, SIGNAL(levelChanged(qreal, qreal, int)), levelMeter, SLOT(levelChanged(qreal, qreal, int)));
}
static const char* const m_channelIdURI;
static const char* const m_channelId;

View File

@ -94,6 +94,11 @@ void FT8DemodBaseband::handleData()
m_sampleFifo.readCommit((unsigned int) count);
}
qreal rmsLevel, peakLevel;
int numSamples;
m_sink.getLevels(rmsLevel, peakLevel, numSamples);
emit levelChanged(rmsLevel, peakLevel, numSamples);
}
void FT8DemodBaseband::handleInputMessages()

View File

@ -75,6 +75,15 @@ public:
void setFifoLabel(const QString& label) { m_sampleFifo.setLabel(label); }
void setAudioFifoLabel(const QString& label) { m_sink.setAudioFifoLabel(label); }
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 samples analyzed
*/
void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples);
private:
SampleSinkFifo m_sampleFifo;
DownChannelizer m_channelizer;

View File

@ -324,6 +324,7 @@ FT8DemodGUI::FT8DemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
ui->spectrumGUI->setBuddies(m_spectrumVis, ui->glSpectrum);
m_ft8Demod->setLevelMeter(ui->volumeMeter);
ui->BW->setMaximum(60);
ui->BW->setMinimum(10);

View File

@ -635,24 +635,29 @@
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<widget class="LevelMeterVU" name="volumeMeter" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="minimumSize">
<size>
<width>40</width>
<height>20</height>
<width>140</width>
<height>24</height>
</size>
</property>
</spacer>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>8</pointsize>
</font>
</property>
<property name="toolTip">
<string>Modem input volume</string>
</property>
</widget>
</item>
</layout>
</item>
@ -774,6 +779,12 @@
<extends>QSlider</extends>
<header>gui/tickedslider.h</header>
</customwidget>
<customwidget>
<class>LevelMeterVU</class>
<extends>QWidget</extends>
<header>gui/levelmeter.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>

View File

@ -36,13 +36,39 @@
const int FT8DemodSink::m_ssbFftLen = 1024;
const int FT8DemodSink::m_agcTarget = 3276; // 32768/10 -10 dB amplitude => -20 dB power: center of normal signal
FT8DemodSink::LevelRMS::LevelRMS()
{
m_sum = 0.0f;
m_peak = 0.0f;
m_n = 0;
m_reset = true;
}
void FT8DemodSink::LevelRMS::accumulate(float level)
{
if (m_reset)
{
m_sum = level * level;
m_peak = std::fabs(level);
m_n = 1;
m_reset = false;
}
else
{
m_sum += level * level;
m_peak = std::max(m_peak, std::fabs(level));
m_n++;
}
}
FT8DemodSink::FT8DemodSink() :
m_agc(12000, m_agcTarget, 1e-2),
m_agcActive(false),
m_audioActive(false),
m_spectrumSink(nullptr),
m_audioFifo(24000),
m_ft8SampleRate(12000)
m_ft8SampleRate(12000),
m_levelInNbSamples(1200) // 100 ms
{
m_Bandwidth = 5000;
m_LowCutoff = 300;
@ -155,6 +181,7 @@ void FT8DemodSink::processOneSample(Complex &ci)
m_audioBuffer[m_audioBufferFill].l = sample;
m_audioBuffer[m_audioBufferFill].r = sample;
m_demodBuffer[m_demodBufferFill++] = sample;
calculateLevel(sample);
if (m_demodBufferFill >= m_demodBuffer.size())
{
@ -241,6 +268,7 @@ void FT8DemodSink::applyFT8SampleRate(int sampleRate)
m_audioFifo.setSize(sampleRate);
m_ft8SampleRate = sampleRate;
m_levelInNbSamples = m_ft8SampleRate / 10; // 100 ms
QList<ObjectPipe*> pipes;
MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes);
@ -324,3 +352,14 @@ void FT8DemodSink::applySettings(const FT8DemodSettings& settings, bool force)
m_settings = settings;
}
void FT8DemodSink::calculateLevel(int16_t& sample)
{
if (m_levelIn.m_n >= m_levelInNbSamples)
{
m_rmsLevel = sqrt(m_levelIn.m_sum / m_levelInNbSamples);
m_peakLevel = m_levelIn.m_peak;
m_levelIn.m_reset = true;
}
m_levelIn.accumulate(sample/29491.2f); // scale on 90% (0.9 * 32768.0)
}

View File

@ -69,6 +69,19 @@ public:
m_magsqCount = 0;
}
/**
* 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 samples analyzed
*/
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples)
{
rmsLevel = m_rmsLevel;
peakLevel = m_peakLevel;
numSamples = m_levelInNbSamples;
}
private:
struct MagSqLevelsStore
{
@ -80,6 +93,17 @@ private:
double m_magsqPeak;
};
struct LevelRMS
{
LevelRMS();
void accumulate(float fsample);
double m_sum;
float m_peak;
int m_n;
bool m_reset;
};
FT8DemodSettings m_settings;
ChannelAPI *m_channel;
@ -118,10 +142,16 @@ private:
QVector<qint16> m_demodBuffer;
int m_demodBufferFill;
LevelRMS m_levelIn;
int m_levelInNbSamples;
Real m_rmsLevel;
Real m_peakLevel;
static const int m_ssbFftLen;
static const int m_agcTarget;
void processOneSample(Complex &ci);
void calculateLevel(int16_t& sample);
};
#endif // INCLUDE_FT8DEMODSINK_H