From 24e4026778bfd87612d5bedce1bfa51455853bc3 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Thu, 29 Oct 2015 00:48:08 +0100 Subject: [PATCH] Add the beginnings of a very simple VU meter, based on libebur128. --- Makefile | 6 +++--- glwidget.cpp | 5 +++++ mainwindow.cpp | 2 ++ mixer.cpp | 11 +++++++++++ mixer.h | 10 ++++++++++ ui_mainwindow.ui | 24 ++++++++++++++++++++---- vumeter.cpp | 33 +++++++++++++++++++++++++++++++++ vumeter.h | 31 +++++++++++++++++++++++++++++++ 8 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 vumeter.cpp create mode 100644 vumeter.h diff --git a/Makefile b/Makefile index d056084..2355194 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ CXX=g++ PKG_MODULES = Qt5Core Qt5Gui Qt5Widgets Qt5OpenGLExtensions Qt5OpenGL libusb-1.0 movit lua5.2 libmicrohttpd CXXFLAGS := -O2 -march=native -g -std=gnu++11 -Wall -Wno-deprecated-declarations -Werror -fPIC $(shell pkg-config --cflags $(PKG_MODULES)) -pthread -DMOVIT_SHADER_DIR=\"$(shell pkg-config --variable=shaderdir movit)\" -LDFLAGS=$(shell pkg-config --libs $(PKG_MODULES)) -lEGL -lGL -pthread -lva -lva-drm -lva-x11 -lX11 -lavformat -lavcodec -lavutil -lzita-resampler +LDFLAGS=$(shell pkg-config --libs $(PKG_MODULES)) -lEGL -lGL -pthread -lva -lva-drm -lva-x11 -lX11 -lavformat -lavcodec -lavutil -lzita-resampler -lebur128 # Qt objects -OBJS=glwidget.o main.o mainwindow.o window.o -OBJS += glwidget.moc.o mainwindow.moc.o window.moc.o +OBJS=glwidget.o main.o mainwindow.o window.o vumeter.o +OBJS += glwidget.moc.o mainwindow.moc.o window.moc.o vumeter.moc.o # Mixer objects OBJS += h264encode.o mixer.o bmusb/bmusb.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o resampler.o httpd.o diff --git a/glwidget.cpp b/glwidget.cpp index 3482a13..2118ffe 100644 --- a/glwidget.cpp +++ b/glwidget.cpp @@ -3,6 +3,7 @@ #include // Needs to come before egl.h. #include // Needs to come before egl.h. #include // Needs to come before egl.h. +#include // Needs to come before egl.h. #include #include #include @@ -17,6 +18,7 @@ #include "context.h" #include "mixer.h" #include "ref_counted_gl_sync.h" +#include "vumeter.h" class MainWindow; class QSurface; @@ -46,6 +48,9 @@ void GLWidget::initializeGL() static std::once_flag flag; std::call_once(flag, [this]{ global_mixer = new Mixer(QGLFormat::toSurfaceFormat(format())); + global_mixer->set_audio_level_callback([this](float level){ + global_vu_meter->set_level(level); + }); global_mixer->start(); }); global_mixer->set_frame_ready_callback(output, [this]{ diff --git a/mainwindow.cpp b/mainwindow.cpp index 3ccc893..29a863b 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -79,6 +79,8 @@ MainWindow::MainWindow() qRegisterMetaType>("std::vector"); connect(ui->preview1, SIGNAL(transition_names_updated(std::vector)), this, SLOT(set_transition_names(std::vector))); + + global_vu_meter = ui->vu_meter; // global_mixer does not exist yet, so need to delay the hookup. } void MainWindow::resizeEvent(QResizeEvent* event) diff --git a/mixer.cpp b/mixer.cpp index 59f520a..226d57f 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -146,6 +146,8 @@ Mixer::Mixer(const QSurfaceFormat &format) " gl_FragColor = texture2D(cbcr_tex, tc0); \n" "} \n"; cbcr_program_num = resource_pool->compile_glsl_program(cbcr_vert_shader, cbcr_frag_shader); + + r128_state = ebur128_init(2, 48000, EBUR128_MODE_SAMPLE_PEAK | EBUR128_MODE_M | EBUR128_MODE_S | EBUR128_MODE_I | EBUR128_MODE_LRA); } Mixer::~Mixer() @@ -161,6 +163,8 @@ Mixer::~Mixer() } cards[card_index].usb->stop_dequeue_thread(); } + + ebur128_destroy(&r128_state); } namespace { @@ -352,6 +356,7 @@ void Mixer::thread_func() } } if (card_index == 0) { + ebur128_add_frames_float(r128_state, samples_out.data(), samples_out.size() / 2); h264_encoder->add_audio(pts_int, move(samples_out)); } } @@ -362,6 +367,12 @@ void Mixer::thread_func() } } + if (audio_level_callback != nullptr) { + double loudness_s; + ebur128_loudness_shortterm(r128_state, &loudness_s); + audio_level_callback(loudness_s); + } + // If the first card is reporting a corrupted or otherwise dropped frame, // just increase the pts (skipping over this frame) and don't try to compute anything new. if (card_copy[0].new_frame->len == 0) { diff --git a/mixer.h b/mixer.h index a177854..5b82b4e 100644 --- a/mixer.h +++ b/mixer.h @@ -7,6 +7,7 @@ #undef Success #include #include +#include #include #include "bmusb/bmusb.h" @@ -80,6 +81,12 @@ public: output_channel[output].set_frame_ready_callback(callback); } + typedef std::function audio_level_callback_t; + void set_audio_level_callback(audio_level_callback_t callback) + { + audio_level_callback = callback; + } + std::vector get_transition_names() { return theme->get_transition_names(pts()); @@ -155,6 +162,9 @@ private: std::thread mixer_thread; bool should_quit = false; + + audio_level_callback_t audio_level_callback = nullptr; + ebur128_state *r128_state = nullptr; }; extern Mixer *global_mixer; diff --git a/ui_mainwindow.ui b/ui_mainwindow.ui index 90663b0..12e3864 100644 --- a/ui_mainwindow.ui +++ b/ui_mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 902 - 590 + 1089 + 664 @@ -27,7 +27,7 @@ - + @@ -137,6 +137,16 @@ + + + + + 30 + 0 + + + + @@ -221,7 +231,7 @@ 0 0 - 902 + 1089 19 @@ -251,6 +261,12 @@ QWidget
qglwidget.h
+ + VUMeter + QWidget +
vumeter.h
+ 1 +
diff --git a/vumeter.cpp b/vumeter.cpp new file mode 100644 index 0000000..03a93e7 --- /dev/null +++ b/vumeter.cpp @@ -0,0 +1,33 @@ +#include + +#include "vumeter.h" + +using namespace std; + +VUMeter *global_vu_meter = nullptr; + +VUMeter::VUMeter(QWidget *parent) + : QWidget(parent) +{ +} + +void VUMeter::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + + painter.fillRect(0, 0, width(), height(), Qt::black); + + float level; + { + unique_lock lock(level_mutex); + level = this->level; + } + + const float min_level = 0.0f; // y=0 is top of screen, so “min” is the loudest level. + const float max_level = -60.0f; + int y = lrintf(height() * (level - min_level) / (max_level - min_level)); + if (y >= 0 && y < height()) { + painter.setPen(Qt::white); + painter.drawLine(0, y, width(), y); + } +} diff --git a/vumeter.h b/vumeter.h new file mode 100644 index 0000000..de27529 --- /dev/null +++ b/vumeter.h @@ -0,0 +1,31 @@ +#ifndef VUMETER_H +#define VUMETER_H + +#include +#include + +#include + +class VUMeter : public QWidget +{ + Q_OBJECT + +public: + VUMeter(QWidget *parent); + + void set_level(float level) { + std::unique_lock lock(level_mutex); + this->level = level; + update(); + } + +private: + void paintEvent(QPaintEvent *event) override; + + std::mutex level_mutex; + float level = -HUGE_VAL; +}; + +extern VUMeter *global_vu_meter; + +#endif -- 2.39.2