mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-14 04:11:48 -05:00
NFM Modulator: basic input volume gauge
This commit is contained in:
parent
ab60cac358
commit
7a07b56b01
@ -144,6 +144,7 @@ set(sdrbase_SOURCES
|
||||
sdrbase/gui/glspectrum.cpp
|
||||
sdrbase/gui/glspectrumgui.cpp
|
||||
sdrbase/gui/indicator.cpp
|
||||
sdrbase/gui/levelmeter.cpp
|
||||
sdrbase/gui/mypositiondialog.cpp
|
||||
sdrbase/gui/pluginsdialog.cpp
|
||||
sdrbase/gui/audiodialog.cpp
|
||||
@ -249,6 +250,7 @@ set(sdrbase_HEADERS
|
||||
sdrbase/gui/glspectrum.h
|
||||
sdrbase/gui/glspectrumgui.h
|
||||
sdrbase/gui/indicator.h
|
||||
sdrbase/gui/levelmeter.h
|
||||
sdrbase/gui/mypositiondialog.h
|
||||
sdrbase/gui/physicalunit.h
|
||||
sdrbase/gui/pluginsdialog.h
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <QMutexLocker>
|
||||
#include <stdio.h>
|
||||
#include <complex.h>
|
||||
#include <algorithm>
|
||||
#include <dsp/upchannelizer.h>
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/pidcontroller.h"
|
||||
@ -32,6 +33,7 @@ MESSAGE_CLASS_DEFINITION(NFMMod::MsgConfigureFileSourceStreamTiming, Message)
|
||||
MESSAGE_CLASS_DEFINITION(NFMMod::MsgReportFileSourceStreamData, Message)
|
||||
MESSAGE_CLASS_DEFINITION(NFMMod::MsgReportFileSourceStreamTiming, Message)
|
||||
|
||||
const int NFMMod::m_levelNbSamples = 480; // every 10ms
|
||||
|
||||
NFMMod::NFMMod() :
|
||||
m_modPhasor(0.0f),
|
||||
@ -40,7 +42,10 @@ NFMMod::NFMMod() :
|
||||
m_fileSize(0),
|
||||
m_recordLength(0),
|
||||
m_sampleRate(48000),
|
||||
m_afInput(NFMModInputNone)
|
||||
m_afInput(NFMModInputNone),
|
||||
m_levelCalcCount(0),
|
||||
m_peakLevel(0.0f),
|
||||
m_levelSum(0.0f)
|
||||
{
|
||||
setObjectName("NFMod");
|
||||
|
||||
@ -127,6 +132,7 @@ void NFMMod::modulateSample()
|
||||
Real t;
|
||||
|
||||
pullAF(t);
|
||||
calculateLevel(t);
|
||||
|
||||
m_modPhasor += (m_running.m_fmDeviation / (float) m_running.m_audioSampleRate) * m_bandpass.filter(t) * (M_PI / 1208.0f);
|
||||
m_modSample.real(cos(m_modPhasor) * 32678.0f);
|
||||
@ -173,7 +179,7 @@ void NFMMod::pullAF(Real& sample)
|
||||
break;
|
||||
case NFMModInputAudio:
|
||||
m_audioFifo.read(reinterpret_cast<quint8*>(audioSample), 1, 10);
|
||||
sample = ((audioSample[0] + audioSample[1]) / 131072.0f) * m_running.m_volumeFactor;
|
||||
sample = ((audioSample[0] + audioSample[1]) / 65536.0f) * m_running.m_volumeFactor;
|
||||
break;
|
||||
case NFMModInputNone:
|
||||
default:
|
||||
@ -182,6 +188,25 @@ void NFMMod::pullAF(Real& sample)
|
||||
}
|
||||
}
|
||||
|
||||
void NFMMod::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 NFMMod::start()
|
||||
{
|
||||
qDebug() << "NFMMod::start: m_outputSampleRate: " << m_config.m_outputSampleRate
|
||||
|
@ -191,6 +191,16 @@ public:
|
||||
|
||||
Real getMagSq() const { return m_magsq; }
|
||||
|
||||
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 MsgConfigureNFMMod : public Message
|
||||
{
|
||||
@ -304,9 +314,14 @@ private:
|
||||
int m_sampleRate;
|
||||
|
||||
NFMModInputAF m_afInput;
|
||||
quint32 m_levelCalcCount;
|
||||
Real m_peakLevel;
|
||||
Real m_levelSum;
|
||||
static const int m_levelNbSamples;
|
||||
|
||||
void apply();
|
||||
void pullAF(Real& sample);
|
||||
void calculateLevel(Real& sample);
|
||||
void modulateSample();
|
||||
void openFileStream();
|
||||
void seekFileStream(int seekPercentage);
|
||||
|
@ -78,7 +78,7 @@ void NFMModGUI::resetToDefaults()
|
||||
ui->afBW->setValue(3);
|
||||
ui->fmDev->setValue(50);
|
||||
ui->toneFrequency->setValue(100);
|
||||
ui->micVolume->setValue(10);
|
||||
ui->volume->setValue(10);
|
||||
ui->deltaFrequency->setValue(0);
|
||||
|
||||
blockApplySettings(false);
|
||||
@ -94,7 +94,7 @@ QByteArray NFMModGUI::serialize() const
|
||||
s.writeS32(4, ui->fmDev->value());
|
||||
s.writeU32(5, m_channelMarker.getColor().rgb());
|
||||
s.writeS32(6, ui->toneFrequency->value());
|
||||
s.writeS32(7, ui->micVolume->value());
|
||||
s.writeS32(7, ui->volume->value());
|
||||
return s.final();
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ bool NFMModGUI::deserialize(const QByteArray& data)
|
||||
d.readS32(6, &tmp, 100);
|
||||
ui->toneFrequency->setValue(tmp);
|
||||
d.readS32(7, &tmp, 10);
|
||||
ui->micVolume->setValue(tmp);
|
||||
ui->volume->setValue(tmp);
|
||||
|
||||
blockApplySettings(false);
|
||||
m_channelMarker.blockSignals(false);
|
||||
@ -227,9 +227,9 @@ void NFMModGUI::on_fmDev_valueChanged(int value)
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void NFMModGUI::on_micVolume_valueChanged(int value)
|
||||
void NFMModGUI::on_volume_valueChanged(int value)
|
||||
{
|
||||
ui->micVolumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
||||
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -386,6 +386,7 @@ NFMModGUI::NFMModGUI(PluginAPI* pluginAPI, DeviceSinkAPI *deviceAPI, QWidget* pa
|
||||
applySettings();
|
||||
|
||||
connect(m_nfmMod->getOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
connect(m_nfmMod, SIGNAL(levelChanged(qreal, qreal, int)), ui->volumeMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
}
|
||||
|
||||
NFMModGUI::~NFMModGUI()
|
||||
@ -422,7 +423,7 @@ void NFMModGUI::applySettings()
|
||||
ui->afBW->value() * 1000.0,
|
||||
ui->fmDev->value() * 100.0f, // value is in '100 Hz
|
||||
ui->toneFrequency->value() * 10.0f,
|
||||
ui->micVolume->value() / 10.0f,
|
||||
ui->volume->value() / 10.0f,
|
||||
ui->audioMute->isChecked(),
|
||||
ui->playLoop->isChecked());
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ private slots:
|
||||
void on_afBW_valueChanged(int value);
|
||||
void on_fmDev_valueChanged(int value);
|
||||
void on_toneFrequency_valueChanged(int value);
|
||||
void on_micVolume_valueChanged(int value);
|
||||
void on_volume_valueChanged(int value);
|
||||
void on_audioMute_toggled(bool checked);
|
||||
void on_tone_toggled(bool checked);
|
||||
void on_mic_toggled(bool checked);
|
||||
|
@ -50,16 +50,7 @@
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<property name="margin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -329,6 +320,78 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="volumeLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="volLabel">
|
||||
<property name="text">
|
||||
<string>Vol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="volume">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio input volume</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="volumeText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio input volume level</string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LevelMeter" name="volumeMeter" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="recordFileSelectLayout">
|
||||
<item>
|
||||
@ -426,66 +489,15 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="volLabel">
|
||||
<property name="text">
|
||||
<string>Vol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="micVolume">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio input volume</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="micVolumeText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio input volume level</string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="fileNameLayout">
|
||||
<item>
|
||||
@ -670,6 +682,12 @@
|
||||
<extends>QToolButton</extends>
|
||||
<header>gui/buttonswitch.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LevelMeter</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/levelmeter.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../../sdrbase/resources/res.qrc"/>
|
||||
|
174
sdrbase/gui/levelmeter.cpp
Normal file
174
sdrbase/gui/levelmeter.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016 Edouard Griffiths, F4EXB
|
||||
* Modifications made to:
|
||||
* - use the widget horizontally
|
||||
* - differentiate each area with a different color
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "gui/levelmeter.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
|
||||
// Constants
|
||||
const int RedrawInterval = 100; // ms
|
||||
const qreal PeakDecayRate = 0.001;
|
||||
const int PeakHoldLevelDuration = 2000; // ms
|
||||
|
||||
LevelMeter::LevelMeter(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_rmsLevel(0.0)
|
||||
, m_peakLevel(0.0)
|
||||
, m_decayedPeakLevel(0.0)
|
||||
, m_peakDecayRate(PeakDecayRate)
|
||||
, m_peakHoldLevel(0.0)
|
||||
, m_redrawTimer(new QTimer(this))
|
||||
, m_rmsColor(Qt::green) // m_rmsColor(Qt::red)
|
||||
, m_decayedPeakColor(Qt::yellow)
|
||||
, m_peakColor(255, 0, 0, 255) // m_peakColor(255, 200, 200, 255)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||
setMinimumWidth(30);
|
||||
|
||||
connect(m_redrawTimer, SIGNAL(timeout()), this, SLOT(redrawTimerExpired()));
|
||||
m_redrawTimer->start(RedrawInterval);
|
||||
}
|
||||
|
||||
LevelMeter::~LevelMeter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LevelMeter::reset()
|
||||
{
|
||||
m_rmsLevel = 0.0;
|
||||
m_peakLevel = 0.0;
|
||||
update();
|
||||
}
|
||||
|
||||
void LevelMeter::levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples)
|
||||
{
|
||||
// Smooth the RMS signal
|
||||
const qreal smooth = pow(qreal(0.9), static_cast<qreal>(numSamples) / 256); // TODO: remove this magic number
|
||||
m_rmsLevel = (m_rmsLevel * smooth) + (rmsLevel * (1.0 - smooth));
|
||||
|
||||
if (peakLevel > m_decayedPeakLevel) {
|
||||
m_peakLevel = peakLevel;
|
||||
m_decayedPeakLevel = peakLevel;
|
||||
m_peakLevelChanged.start();
|
||||
}
|
||||
|
||||
if (peakLevel > m_peakHoldLevel) {
|
||||
m_peakHoldLevel = peakLevel;
|
||||
m_peakHoldLevelChanged.start();
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void LevelMeter::redrawTimerExpired()
|
||||
{
|
||||
// Decay the peak signal
|
||||
const int elapsedMs = m_peakLevelChanged.elapsed();
|
||||
const qreal decayAmount = m_peakDecayRate * elapsedMs;
|
||||
if (decayAmount < m_peakLevel)
|
||||
m_decayedPeakLevel = m_peakLevel - decayAmount;
|
||||
else
|
||||
m_decayedPeakLevel = 0.0;
|
||||
|
||||
// Check whether to clear the peak hold level
|
||||
if (m_peakHoldLevelChanged.elapsed() > PeakHoldLevelDuration)
|
||||
m_peakHoldLevel = 0.0;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void LevelMeter::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
||||
QPainter painter(this);
|
||||
painter.fillRect(rect(), Qt::black);
|
||||
|
||||
QRect bar = rect();
|
||||
|
||||
// old
|
||||
|
||||
// bar.setTop(rect().top() + (1.0 - m_peakHoldLevel) * rect().height());
|
||||
// bar.setBottom(bar.top() + 5);
|
||||
// painter.fillRect(bar, m_rmsColor);
|
||||
// bar.setBottom(rect().bottom());
|
||||
//
|
||||
// bar.setTop(rect().top() + (1.0 - m_decayedPeakLevel) * rect().height());
|
||||
// painter.fillRect(bar, m_peakColor);
|
||||
//
|
||||
// bar.setTop(rect().top() + (1.0 - m_rmsLevel) * rect().height());
|
||||
// painter.fillRect(bar, m_rmsColor);
|
||||
|
||||
// old v.2
|
||||
|
||||
// bar.setTop(rect().top() + (1.0 - m_peakHoldLevel) * rect().height());
|
||||
// bar.setBottom(bar.top() + 5);
|
||||
// painter.fillRect(bar, m_peakColor);
|
||||
// bar.setBottom(rect().bottom());
|
||||
//
|
||||
// bar.setTop(rect().top() + (1.0 - m_decayedPeakLevel) * rect().height());
|
||||
// painter.fillRect(bar, m_decayedPeakColor);
|
||||
//
|
||||
// bar.setTop(rect().top() + (1.0 - m_rmsLevel) * rect().height());
|
||||
// painter.fillRect(bar, m_rmsColor);
|
||||
|
||||
// new
|
||||
|
||||
bar.setRight(rect().right() - (1.0 - m_peakHoldLevel) * rect().width());
|
||||
bar.setLeft(bar.right() - 5);
|
||||
painter.fillRect(bar, m_peakColor);
|
||||
bar.setLeft(rect().left());
|
||||
|
||||
bar.setRight(rect().right() - (1.0 - m_decayedPeakLevel) * rect().width());
|
||||
painter.fillRect(bar, m_decayedPeakColor);
|
||||
|
||||
bar.setRight(rect().right() - (1.0 - m_rmsLevel) * rect().width());
|
||||
painter.fillRect(bar, m_rmsColor);
|
||||
|
||||
}
|
124
sdrbase/gui/levelmeter.h
Normal file
124
sdrbase/gui/levelmeter.h
Normal file
@ -0,0 +1,124 @@
|
||||
/****************************************************************************
|
||||
* Copyright (C) 2016 Edouard Griffiths, F4EXB
|
||||
* Modifications made to:
|
||||
* - use the widget horizontally
|
||||
* - differentiate each area with a different color
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef SDRBASE_GUI_LEVELMETER_H_
|
||||
#define SDRBASE_GUI_LEVELMETER_H_
|
||||
|
||||
#include <QTime>
|
||||
#include <QWidget>
|
||||
#include <dsp/dsptypes.h>
|
||||
|
||||
/**
|
||||
* Widget which displays a vertical audio level meter, indicating the
|
||||
* RMS and peak levels of the window of audio samples most recently analyzed
|
||||
* by the Engine.
|
||||
*/
|
||||
class LevelMeter : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LevelMeter(QWidget *parent = 0);
|
||||
~LevelMeter();
|
||||
|
||||
void paintEvent(QPaintEvent *event);
|
||||
|
||||
public slots:
|
||||
void reset();
|
||||
void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples);
|
||||
|
||||
private slots:
|
||||
void redrawTimerExpired();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Height of RMS level bar.
|
||||
* Range 0.0 - 1.0.
|
||||
*/
|
||||
qreal m_rmsLevel;
|
||||
|
||||
/**
|
||||
* Most recent peak level.
|
||||
* Range 0.0 - 1.0.
|
||||
*/
|
||||
qreal m_peakLevel;
|
||||
|
||||
/**
|
||||
* Height of peak level bar.
|
||||
* This is calculated by decaying m_peakLevel depending on the
|
||||
* elapsed time since m_peakLevelChanged, and the value of m_decayRate.
|
||||
*/
|
||||
qreal m_decayedPeakLevel;
|
||||
|
||||
/**
|
||||
* Time at which m_peakLevel was last changed.
|
||||
*/
|
||||
QTime m_peakLevelChanged;
|
||||
|
||||
/**
|
||||
* Rate at which peak level bar decays.
|
||||
* Expressed in level units / millisecond.
|
||||
*/
|
||||
qreal m_peakDecayRate;
|
||||
|
||||
/**
|
||||
* High watermark of peak level.
|
||||
* Range 0.0 - 1.0.
|
||||
*/
|
||||
qreal m_peakHoldLevel;
|
||||
|
||||
/**
|
||||
* Time at which m_peakHoldLevel was last changed.
|
||||
*/
|
||||
QTime m_peakHoldLevelChanged;
|
||||
|
||||
QTimer *m_redrawTimer;
|
||||
|
||||
QColor m_rmsColor;
|
||||
QColor m_peakColor;
|
||||
QColor m_decayedPeakColor;
|
||||
|
||||
};
|
||||
|
||||
#endif /* SDRBASE_GUI_LEVELMETER_H_ */
|
Loading…
Reference in New Issue
Block a user