audiomonitor: implemented hardware acceleration
Drawing is much smoother this way.
This commit is contained in:
@@ -65,6 +65,8 @@ bool AudioManager::IsRefreshingInputs()
|
||||
void AudioManager::PushToOutput(const QByteArray &samples)
|
||||
{
|
||||
output_manager_.Push(samples);
|
||||
|
||||
emit OutputPushed(samples);
|
||||
}
|
||||
|
||||
void AudioManager::StartOutput(const QString &filename, qint64 offset, int playback_speed)
|
||||
|
||||
@@ -90,6 +90,8 @@ signals:
|
||||
|
||||
void AudioParamsChanged(const AudioRenderingParams& params);
|
||||
|
||||
void OutputPushed(const QByteArray& data);
|
||||
|
||||
void Stopped();
|
||||
|
||||
private:
|
||||
|
||||
@@ -31,19 +31,16 @@ OLIVE_NAMESPACE_ENTER
|
||||
|
||||
const int kDecibelStep = 6;
|
||||
const int kDecibelMinimum = -200;
|
||||
const int kMaximumSmoothness = 4;
|
||||
const int kMaximumSmoothness = 8;
|
||||
|
||||
AudioMonitor::AudioMonitor(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
QOpenGLWidget(parent),
|
||||
cached_channels_(0)
|
||||
{
|
||||
update_timer_.setInterval(1000 / 60); // Hardcoded to 60 FPS
|
||||
connect(&update_timer_, &QTimer::timeout, this, static_cast<void(AudioMonitor::*)()>(&AudioMonitor::update));
|
||||
update_timer_.start();
|
||||
|
||||
values_.resize(kMaximumSmoothness);
|
||||
|
||||
connect(AudioManager::instance(), &AudioManager::OutputDeviceStarted, this, &AudioMonitor::OutputDeviceSet);
|
||||
connect(AudioManager::instance(), &AudioManager::OutputPushed, this, &AudioMonitor::OutputPushed);
|
||||
connect(AudioManager::instance(), &AudioManager::AudioParamsChanged, this, &AudioMonitor::SetParams);
|
||||
connect(AudioManager::instance(), &AudioManager::Stopped, this, &AudioMonitor::Stop);
|
||||
}
|
||||
@@ -81,10 +78,9 @@ void AudioMonitor::OutputDeviceSet(const QString &filename, qint64 offset, int p
|
||||
|
||||
playback_speed_ = playback_speed;
|
||||
|
||||
update_timer_.start();
|
||||
last_time_ = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
update();
|
||||
SetUpdateLoop(true);
|
||||
}
|
||||
|
||||
void AudioMonitor::Stop()
|
||||
@@ -94,6 +90,28 @@ void AudioMonitor::Stop()
|
||||
}
|
||||
}
|
||||
|
||||
void AudioMonitor::OutputPushed(const QByteArray &data)
|
||||
{
|
||||
QVector<double> v(params_.channel_count(), 0);
|
||||
|
||||
BytesToSampleSummary(data, v);
|
||||
|
||||
PushValue(v);
|
||||
|
||||
SetUpdateLoop(true);
|
||||
}
|
||||
|
||||
void AudioMonitor::SetUpdateLoop(bool e)
|
||||
{
|
||||
if (e) {
|
||||
connect(this, &AudioMonitor::frameSwapped, this, static_cast<void(AudioMonitor::*)()>(&AudioMonitor::update));
|
||||
|
||||
update();
|
||||
} else {
|
||||
disconnect(this, &AudioMonitor::frameSwapped, this, static_cast<void(AudioMonitor::*)()>(&AudioMonitor::update));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void AudioMonitor::SetValues(QVector<double> values)
|
||||
{
|
||||
@@ -111,13 +129,15 @@ void AudioMonitor::SetValues(QVector<double> values)
|
||||
}
|
||||
*/
|
||||
|
||||
void AudioMonitor::paintEvent(QPaintEvent *)
|
||||
void AudioMonitor::paintGL()
|
||||
{
|
||||
QPainter p(this);
|
||||
p.fillRect(rect(), palette().window().color());
|
||||
|
||||
if (!params_.channel_count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QPainter p(this);
|
||||
QFontMetrics fm = p.fontMetrics();
|
||||
|
||||
int peaks_y = 0;
|
||||
@@ -223,6 +243,8 @@ void AudioMonitor::paintEvent(QPaintEvent *)
|
||||
p.setBrush(QColor(0, 0, 0, 128));
|
||||
p.setPen(Qt::NoPen);
|
||||
|
||||
bool all_zeroes = true;
|
||||
|
||||
for (int i=0;i<params_.channel_count();i++) {
|
||||
int channel_x = full_meter_rect.x() + channel_width * i;
|
||||
|
||||
@@ -238,6 +260,10 @@ void AudioMonitor::paintEvent(QPaintEvent *)
|
||||
peaked_[i] = true;
|
||||
}
|
||||
|
||||
if (all_zeroes && !qIsNull(vol)) {
|
||||
all_zeroes = false;
|
||||
}
|
||||
|
||||
// Convert val to logarithmic scale
|
||||
vol = QAudio::convertVolume(vol, QAudio::LinearVolumeScale, QAudio::LogarithmicVolumeScale);
|
||||
|
||||
@@ -248,6 +274,11 @@ void AudioMonitor::paintEvent(QPaintEvent *)
|
||||
p.drawRect(peaks_rect);
|
||||
}
|
||||
}
|
||||
|
||||
if (all_zeroes && !file_.isOpen()) {
|
||||
// Optimize by disabling the update loop
|
||||
SetUpdateLoop(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioMonitor::mousePressEvent(QMouseEvent *)
|
||||
@@ -265,8 +296,21 @@ void AudioMonitor::UpdateValuesFromFile(QVector<double>& v)
|
||||
// Determine how many bytes this is
|
||||
int bytes_to_read = params_.time_to_bytes(static_cast<double>(time_passed) * 0.001);
|
||||
|
||||
QByteArray b = file_.read(bytes_to_read);
|
||||
QByteArray b = file_.read(bytes_to_read);;
|
||||
|
||||
BytesToSampleSummary(b, v);
|
||||
|
||||
last_time_ = current_time;
|
||||
}
|
||||
|
||||
void AudioMonitor::PushValue(const QVector<double> &v)
|
||||
{
|
||||
values_.removeFirst();
|
||||
values_.append(v);
|
||||
}
|
||||
|
||||
void AudioMonitor::BytesToSampleSummary(const QByteArray &b, QVector<double> &v)
|
||||
{
|
||||
const float* samples = reinterpret_cast<const float*>(b.constData());
|
||||
int nb_samples = b.size() / sizeof(float);
|
||||
|
||||
@@ -279,14 +323,6 @@ void AudioMonitor::UpdateValuesFromFile(QVector<double>& v)
|
||||
v.replace(channel, abs_sample);
|
||||
}
|
||||
}
|
||||
|
||||
last_time_ = current_time;
|
||||
}
|
||||
|
||||
void AudioMonitor::PushValue(const QVector<double> &v)
|
||||
{
|
||||
values_.removeFirst();
|
||||
values_.append(v);
|
||||
}
|
||||
|
||||
QVector<double> AudioMonitor::GetAverages() const
|
||||
|
||||
@@ -22,15 +22,15 @@
|
||||
#define AUDIOMONITORWIDGET_H
|
||||
|
||||
#include <QFile>
|
||||
#include <QOpenGLWidget>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "render/audioparams.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class AudioMonitor : public QWidget
|
||||
class AudioMonitor : public QOpenGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -45,15 +45,23 @@ public slots:
|
||||
|
||||
void Stop();
|
||||
|
||||
void OutputPushed(const QByteArray& data);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
//virtual void paintEvent(QPaintEvent* event) override;
|
||||
virtual void paintGL() override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||
|
||||
private:
|
||||
void SetUpdateLoop(bool e);
|
||||
|
||||
void UpdateValuesFromFile(QVector<double> &v);
|
||||
|
||||
void PushValue(const QVector<double>& v);
|
||||
|
||||
void BytesToSampleSummary(const QByteArray& bytes, QVector<double>& v);
|
||||
|
||||
QVector<double> GetAverages() const;
|
||||
|
||||
AudioRenderingParams params_;
|
||||
@@ -69,8 +77,6 @@ private:
|
||||
QPixmap cached_background_;
|
||||
int cached_channels_;
|
||||
|
||||
QTimer update_timer_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Reference in New Issue
Block a user