diff --git a/obs/volume-control.cpp b/obs/volume-control.cpp index 0c17d47f3..bc4da2bc6 100644 --- a/obs/volume-control.cpp +++ b/obs/volume-control.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -13,6 +14,12 @@ using namespace std; #define VOL_MIN -96.0f #define VOL_MAX 0.0f +/* + VOL_MIN_LOG = DBToLog(VOL_MIN) + VOL_MAX_LOG = DBToLog(VOL_MAX) + ... just in case someone wants to use a smaller scale + */ + #define VOL_MIN_LOG -2.0086001717619175 #define VOL_MAX_LOG -0.77815125038364363 @@ -40,18 +47,14 @@ void VolControl::OBSVolumeChanged(void *data, calldata_t calldata) void VolControl::OBSVolumeLevel(void *data, calldata_t calldata) { VolControl *volControl = static_cast(data); - float level = calldata_float(calldata, "level"); - float mag = calldata_float(calldata, "magnitude"); - - /* - * TODO: an actual volume control that can process level, mag, peak. - * - * for the time being, just average level and magnitude. - */ - float result = (level + mag) * 0.5f; + float peak = calldata_float(calldata, "level"); + float mag = calldata_float(calldata, "magnitude"); + float peakHold = calldata_float(calldata, "peak"); QMetaObject::invokeMethod(volControl, "VolumeLevel", - Q_ARG(float, result)); + Q_ARG(float, mag), + Q_ARG(float, peak), + Q_ARG(float, peakHold)); } void VolControl::VolumeChanged(int vol) @@ -61,22 +64,20 @@ void VolControl::VolumeChanged(int vol) signalChanged = true; } -void VolControl::VolumeLevel(float level) +void VolControl::VolumeLevel(float mag, float peak, float peakHold) { uint64_t curMeterTime = os_gettime_ns() / 1000000; - levelTotal += level; - levelCount += 1.0f; + /* + Add again peak averaging? + */ /* only update after a certain amount of time */ if ((curMeterTime - lastMeterTime) > UPDATE_INTERVAL_MS) { lastMeterTime = curMeterTime; - - float finalLevel = levelTotal / levelCount; - volMeter->setValue(int(DBToLinear(finalLevel) * 10000.0f)); - - levelTotal = 0.0f; - levelCount = 0.0f; + volMeter->setLevels(DBToLinear(mag), + DBToLinear(peak), + DBToLinear(peakHold)); } } @@ -118,7 +119,7 @@ VolControl::VolControl(OBSSource source_) nameLabel = new QLabel(); volLabel = new QLabel(); - volMeter = new QProgressBar(); + volMeter = new VolumeMeter(); slider = new QSlider(Qt::Horizontal); QFont font = nameLabel->font(); @@ -133,18 +134,6 @@ VolControl::VolControl(OBSSource source_) slider->setValue(vol); // slider->setMaximumHeight(13); - volMeter->setMaximumHeight(1); - volMeter->setMinimum(0); - volMeter->setMaximum(10000); - volMeter->setTextVisible(false); - - /* [Danni] Temporary color. */ - QString testColor = "QProgressBar " - "{border: 0px} " - "QProgressBar::chunk " - "{width: 1px; background-color: #AA0000;}"; - volMeter->setStyleSheet(testColor); - textLayout->setContentsMargins(0, 0, 0, 0); textLayout->addWidget(nameLabel); textLayout->addWidget(volLabel); @@ -177,3 +166,69 @@ VolControl::~VolControl() signal_handler_disconnect(obs_source_signalhandler(source), "volume_level", OBSVolumeLevel, this); } + +VolumeMeter::VolumeMeter(QWidget *parent) + : QWidget(parent) +{ + setMinimumSize(1, 3); + + bkColor.setRgb(0xDD, 0xDD, 0xDD); + magColor.setRgb(0x20, 0x7D, 0x17); + peakColor.setRgb(0x3E, 0xF1, 0x2B); + peakHoldColor.setRgb(0x00, 0x00, 0x00); + + + setLevels(0.0f, 0.0f, 0.0f); +} + +void VolumeMeter::setLevels(float nmag, float npeak, float npeakHold) +{ + mag = nmag; + peak = npeak; + peakHold = npeakHold; + update(); +} + +void VolumeMeter::paintEvent(QPaintEvent *event) +{ + UNUSED_PARAMETER(event); + + QPainter painter(this); + QLinearGradient gradient; + + int width = size().width(); + int height = size().height(); + + int scaledMag = int((float)width * mag); + int scaledPeak = int((float)width * peak); + int scaledPeakHold = int((float)width * peakHold); + + gradient.setStart(qreal(scaledMag), 0); + gradient.setFinalStop(qreal(scaledPeak), 0); + gradient.setColorAt(0, magColor); + gradient.setColorAt(1, peakColor); + + // RMS + painter.fillRect(0, 0, + scaledMag, height, + magColor); + + // RMS - Peak gradient + painter.fillRect(scaledMag, 0, + scaledPeak - scaledMag + 1, height, + QBrush(gradient)); + + // Background + painter.fillRect(scaledPeak, 0, + width - scaledPeak, height, + bkColor); + + // Peak hold + if(peakHold == 1.0f) + scaledPeakHold--; + + painter.setPen(peakHoldColor); + painter.drawLine(scaledPeakHold, 0, + scaledPeakHold, height); + +} diff --git a/obs/volume-control.hpp b/obs/volume-control.hpp index e89181b2f..132c16d6e 100644 --- a/obs/volume-control.hpp +++ b/obs/volume-control.hpp @@ -2,9 +2,19 @@ #include #include -#include -/* TODO: Make a real volume control that isn't terrible */ +class VolumeMeter : public QWidget +{ + Q_OBJECT +private: + float mag, peak, peakHold; + QColor bkColor, magColor, peakColor, peakHoldColor; +public: + explicit VolumeMeter(QWidget *parent = 0); + void setLevels(float nmag, float npeak, float npeakHold); +protected: + void paintEvent(QPaintEvent *event); +}; class QLabel; class QSlider; @@ -16,7 +26,7 @@ private: OBSSource source; QLabel *nameLabel; QLabel *volLabel; - QProgressBar *volMeter; + VolumeMeter *volMeter; QSlider *slider; bool signalChanged; uint64_t lastMeterTime; @@ -28,7 +38,7 @@ private: private slots: void VolumeChanged(int vol); - void VolumeLevel(float level); + void VolumeLevel(float mag, float peak, float peakHold); void SliderChanged(int vol); public: