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:
parent
809e0bccd4
commit
d6cafa08c5
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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"/>
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user