mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-06-26 22:15:31 -04:00
FT8 demod: volume meter
This commit is contained in:
parent
809e0bccd4
commit
d6cafa08c5
@ -136,6 +136,9 @@ public:
|
|||||||
SWGSDRangel::SWGChannelSettings& response);
|
SWGSDRangel::SWGChannelSettings& response);
|
||||||
|
|
||||||
uint32_t getNumberOfDeviceStreams() const;
|
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_channelIdURI;
|
||||||
static const char* const m_channelId;
|
static const char* const m_channelId;
|
||||||
|
@ -94,6 +94,11 @@ void FT8DemodBaseband::handleData()
|
|||||||
|
|
||||||
m_sampleFifo.readCommit((unsigned int) count);
|
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()
|
void FT8DemodBaseband::handleInputMessages()
|
||||||
|
@ -75,6 +75,15 @@ public:
|
|||||||
void setFifoLabel(const QString& label) { m_sampleFifo.setLabel(label); }
|
void setFifoLabel(const QString& label) { m_sampleFifo.setLabel(label); }
|
||||||
void setAudioFifoLabel(const QString& label) { m_sink.setAudioFifoLabel(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:
|
private:
|
||||||
SampleSinkFifo m_sampleFifo;
|
SampleSinkFifo m_sampleFifo;
|
||||||
DownChannelizer m_channelizer;
|
DownChannelizer m_channelizer;
|
||||||
|
@ -324,6 +324,7 @@ FT8DemodGUI::FT8DemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban
|
|||||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||||
|
|
||||||
ui->spectrumGUI->setBuddies(m_spectrumVis, ui->glSpectrum);
|
ui->spectrumGUI->setBuddies(m_spectrumVis, ui->glSpectrum);
|
||||||
|
m_ft8Demod->setLevelMeter(ui->volumeMeter);
|
||||||
|
|
||||||
ui->BW->setMaximum(60);
|
ui->BW->setMaximum(60);
|
||||||
ui->BW->setMinimum(10);
|
ui->BW->setMinimum(10);
|
||||||
|
@ -635,24 +635,29 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_2">
|
<widget class="LevelMeterVU" name="volumeMeter" native="true">
|
||||||
<property name="orientation">
|
<property name="sizePolicy">
|
||||||
<enum>Qt::Vertical</enum>
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="minimumSize">
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
<size>
|
||||||
<width>40</width>
|
<width>140</width>
|
||||||
<height>20</height>
|
<height>24</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</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>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
@ -774,6 +779,12 @@
|
|||||||
<extends>QSlider</extends>
|
<extends>QSlider</extends>
|
||||||
<header>gui/tickedslider.h</header>
|
<header>gui/tickedslider.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>LevelMeterVU</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>gui/levelmeter.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../../sdrgui/resources/res.qrc"/>
|
<include location="../../../sdrgui/resources/res.qrc"/>
|
||||||
|
@ -36,13 +36,39 @@
|
|||||||
const int FT8DemodSink::m_ssbFftLen = 1024;
|
const int FT8DemodSink::m_ssbFftLen = 1024;
|
||||||
const int FT8DemodSink::m_agcTarget = 3276; // 32768/10 -10 dB amplitude => -20 dB power: center of normal signal
|
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() :
|
FT8DemodSink::FT8DemodSink() :
|
||||||
m_agc(12000, m_agcTarget, 1e-2),
|
m_agc(12000, m_agcTarget, 1e-2),
|
||||||
m_agcActive(false),
|
m_agcActive(false),
|
||||||
m_audioActive(false),
|
m_audioActive(false),
|
||||||
m_spectrumSink(nullptr),
|
m_spectrumSink(nullptr),
|
||||||
m_audioFifo(24000),
|
m_audioFifo(24000),
|
||||||
m_ft8SampleRate(12000)
|
m_ft8SampleRate(12000),
|
||||||
|
m_levelInNbSamples(1200) // 100 ms
|
||||||
{
|
{
|
||||||
m_Bandwidth = 5000;
|
m_Bandwidth = 5000;
|
||||||
m_LowCutoff = 300;
|
m_LowCutoff = 300;
|
||||||
@ -155,6 +181,7 @@ void FT8DemodSink::processOneSample(Complex &ci)
|
|||||||
m_audioBuffer[m_audioBufferFill].l = sample;
|
m_audioBuffer[m_audioBufferFill].l = sample;
|
||||||
m_audioBuffer[m_audioBufferFill].r = sample;
|
m_audioBuffer[m_audioBufferFill].r = sample;
|
||||||
m_demodBuffer[m_demodBufferFill++] = sample;
|
m_demodBuffer[m_demodBufferFill++] = sample;
|
||||||
|
calculateLevel(sample);
|
||||||
|
|
||||||
if (m_demodBufferFill >= m_demodBuffer.size())
|
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||||
{
|
{
|
||||||
@ -241,6 +268,7 @@ void FT8DemodSink::applyFT8SampleRate(int sampleRate)
|
|||||||
|
|
||||||
m_audioFifo.setSize(sampleRate);
|
m_audioFifo.setSize(sampleRate);
|
||||||
m_ft8SampleRate = sampleRate;
|
m_ft8SampleRate = sampleRate;
|
||||||
|
m_levelInNbSamples = m_ft8SampleRate / 10; // 100 ms
|
||||||
|
|
||||||
QList<ObjectPipe*> pipes;
|
QList<ObjectPipe*> pipes;
|
||||||
MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes);
|
MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes);
|
||||||
@ -324,3 +352,14 @@ void FT8DemodSink::applySettings(const FT8DemodSettings& settings, bool force)
|
|||||||
m_settings = settings;
|
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;
|
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:
|
private:
|
||||||
struct MagSqLevelsStore
|
struct MagSqLevelsStore
|
||||||
{
|
{
|
||||||
@ -80,6 +93,17 @@ private:
|
|||||||
double m_magsqPeak;
|
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;
|
FT8DemodSettings m_settings;
|
||||||
ChannelAPI *m_channel;
|
ChannelAPI *m_channel;
|
||||||
|
|
||||||
@ -118,10 +142,16 @@ private:
|
|||||||
QVector<qint16> m_demodBuffer;
|
QVector<qint16> m_demodBuffer;
|
||||||
int m_demodBufferFill;
|
int m_demodBufferFill;
|
||||||
|
|
||||||
|
LevelRMS m_levelIn;
|
||||||
|
int m_levelInNbSamples;
|
||||||
|
Real m_rmsLevel;
|
||||||
|
Real m_peakLevel;
|
||||||
|
|
||||||
static const int m_ssbFftLen;
|
static const int m_ssbFftLen;
|
||||||
static const int m_agcTarget;
|
static const int m_agcTarget;
|
||||||
|
|
||||||
void processOneSample(Complex &ci);
|
void processOneSample(Complex &ci);
|
||||||
|
void calculateLevel(int16_t& sample);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_FT8DEMODSINK_H
|
#endif // INCLUDE_FT8DEMODSINK_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user