summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorm0dB <79429057+m0dB@users.noreply.github.com>2023-04-15 18:45:41 +0200
committerm0dB <79429057+m0dB@users.noreply.github.com>2023-05-27 01:28:24 +0200
commitfafa14f4619036ab95ff701df5036566790c0489 (patch)
treef5363092bf144f7b0b78fee74d648e77a5dddf79
parent4f6a056e331bb421de09cd0a5480237285872aa7 (diff)
added simple qopengl waveform renderer
-rw-r--r--CMakeLists.txt4
-rw-r--r--src/waveform/renderers/qopengl/waveformrendererfiltered.cpp23
-rw-r--r--src/waveform/renderers/qopengl/waveformrendererfiltered.h2
-rw-r--r--src/waveform/renderers/qopengl/waveformrendererlrrgb.cpp5
-rw-r--r--src/waveform/renderers/qopengl/waveformrendererrgb.cpp5
-rw-r--r--src/waveform/renderers/qopengl/waveformrenderersimple.cpp181
-rw-r--r--src/waveform/renderers/qopengl/waveformrenderersimple.h28
-rw-r--r--src/waveform/waveformwidgetfactory.cpp11
-rw-r--r--src/waveform/widgets/qopengl/simplewaveformwidget.cpp36
-rw-r--r--src/waveform/widgets/qopengl/simplewaveformwidget.h46
-rw-r--r--src/waveform/widgets/waveformwidgettype.h1
11 files changed, 328 insertions, 14 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 74dfbc55ca..13811ec83a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1182,13 +1182,13 @@ else()
)
if(QOPENGL)
target_sources(mixxx-lib PRIVATE
+ src/waveform/renderers/qopengl/calculatematrix.cpp
src/waveform/renderers/qopengl/shaders/colorshader.cpp
src/waveform/renderers/qopengl/shaders/endoftrackshader.cpp
src/waveform/renderers/qopengl/shaders/gradientshader.cpp
src/waveform/renderers/qopengl/shaders/shader.cpp
src/waveform/renderers/qopengl/shaders/textureshader.cpp
src/waveform/renderers/qopengl/shaders/unicolorshader.cpp
- src/waveform/renderers/qopengl/calculatematrix.cpp
src/waveform/renderers/qopengl/waveformrenderbackground.cpp
src/waveform/renderers/qopengl/waveformrenderbeat.cpp
src/waveform/renderers/qopengl/waveformrenderer.cpp
@@ -1198,11 +1198,13 @@ else()
src/waveform/renderers/qopengl/waveformrendererpreroll.cpp
src/waveform/renderers/qopengl/waveformrendererrgb.cpp
src/waveform/renderers/qopengl/waveformrenderersignalbase.cpp
+ src/waveform/renderers/qopengl/waveformrenderersimple.cpp
src/waveform/renderers/qopengl/waveformrendermark.cpp
src/waveform/renderers/qopengl/waveformrendermarkrange.cpp
src/waveform/widgets/qopengl/filteredwaveformwidget.cpp
src/waveform/widgets/qopengl/lrrgbwaveformwidget.cpp
src/waveform/widgets/qopengl/rgbwaveformwidget.cpp
+ src/waveform/widgets/qopengl/simplewaveformwidget.cpp
src/waveform/widgets/qopengl/waveformwidget.cpp
src/widget/openglwindow.cpp
src/widget/qopengl/wspinny.cpp
diff --git a/src/waveform/renderers/qopengl/waveformrendererfiltered.cpp b/src/waveform/renderers/qopengl/waveformrendererfiltered.cpp
index f411026688..42458d179e 100644
--- a/src/waveform/renderers/qopengl/waveformrendererfiltered.cpp
+++ b/src/waveform/renderers/qopengl/waveformrendererfiltered.cpp
@@ -81,17 +81,17 @@ void WaveformRendererFiltered::renderGL() {
int reserved[4];
// low, mid, high
for (int bandIndex = 0; bandIndex < 3; bandIndex++) {
- m_verticesForGroup[bandIndex].clear();
+ m_vertices[bandIndex].clear();
reserved[bandIndex] = numVerticesPerLine * length;
- m_verticesForGroup[bandIndex].reserve(reserved[bandIndex]);
+ m_vertices[bandIndex].reserve(reserved[bandIndex]);
}
// the horizontal line
reserved[3] = numVerticesPerLine;
- m_verticesForGroup[3].clear();
- m_verticesForGroup[3].reserve(reserved[3]);
+ m_vertices[3].clear();
+ m_vertices[3].reserve(reserved[3]);
- m_verticesForGroup[3].addRectangle(
+ m_vertices[3].addRectangle(
0.f,
halfBreadth - 0.5f * devicePixelRatio,
static_cast<float>(length),
@@ -148,7 +148,7 @@ void WaveformRendererFiltered::renderGL() {
max[bandIndex][1] *= bandGain[bandIndex];
// lines are thin rectangles
- m_verticesForGroup[bandIndex].addRectangle(
+ m_vertices[bandIndex].addRectangle(
fpos - 0.5f,
halfBreadth - heightFactor * max[bandIndex][0],
fpos + 0.5f,
@@ -179,17 +179,20 @@ void WaveformRendererFiltered::renderGL() {
colors[2].setRgbF(static_cast<float>(m_rgbHighColor_r),
static_cast<float>(m_rgbHighColor_g),
static_cast<float>(m_rgbHighColor_b));
- colors[3].setRgbF(1.f, 1.f, 1.f);
+ colors[4].setRgbF(static_cast<float>(m_axesColor_r),
+ static_cast<float>(m_axesColor_g),
+ static_cast<float>(m_axesColor_b),
+ static_cast<float>(m_axesColor_a));
// 3 bands + 1 extra for the horizontal line
for (int i = 0; i < 4; i++) {
- DEBUG_ASSERT(reserved[i] == m_verticesForGroup[i].size());
+ DEBUG_ASSERT(reserved[i] == m_vertices[i].size());
m_shader.setUniformValue(colorLocation, colors[i]);
m_shader.setAttributeArray(
- positionLocation, GL_FLOAT, m_verticesForGroup[i].constData(), 2);
+ positionLocation, GL_FLOAT, m_vertices[i].constData(), 2);
- glDrawArrays(GL_TRIANGLES, 0, m_verticesForGroup[i].size());
+ glDrawArrays(GL_TRIANGLES, 0, m_vertices[i].size());
}
m_shader.disableAttributeArray(positionLocation);
diff --git a/src/waveform/renderers/qopengl/waveformrendererfiltered.h b/src/waveform/renderers/qopengl/waveformrendererfiltered.h
index 74fc5c211f..6b8c8b6690 100644
--- a/src/waveform/renderers/qopengl/waveformrendererfiltered.h
+++ b/src/waveform/renderers/qopengl/waveformrendererfiltered.h
@@ -22,7 +22,7 @@ class qopengl::WaveformRendererFiltered final : public qopengl::WaveformRenderer
private:
UnicolorShader m_shader;
- VertexData m_verticesForGroup[4];
+ VertexData m_vertices[4];
DISALLOW_COPY_AND_ASSIGN(WaveformRendererFiltered);
};
diff --git a/src/waveform/renderers/qopengl/waveformrendererlrrgb.cpp b/src/waveform/renderers/qopengl/waveformrendererlrrgb.cpp
index 465432ce88..24ac9fd19b 100644
--- a/src/waveform/renderers/qopengl/waveformrendererlrrgb.cpp
+++ b/src/waveform/renderers/qopengl/waveformrendererlrrgb.cpp
@@ -106,7 +106,10 @@ void WaveformRendererLRRGB::renderGL() {
halfBreadth - 0.5f * devicePixelRatio,
static_cast<float>(length),
halfBreadth + 0.5f * devicePixelRatio);
- m_colors.addForRectangle(1.f, 1.f, 1.f);
+ m_colors.addForRectangle(
+ static_cast<float>(m_axesColor_r),
+ static_cast<float>(m_axesColor_g),
+ static_cast<float>(m_axesColor_b));
for (int pos = 0; pos < length; ++pos) {
// Our current pixel (x) corresponds to a number of visual samples
diff --git a/src/waveform/renderers/qopengl/waveformrendererrgb.cpp b/src/waveform/renderers/qopengl/waveformrendererrgb.cpp
index 9dc98f7477..2646bb106d 100644
--- a/src/waveform/renderers/qopengl/waveformrendererrgb.cpp
+++ b/src/waveform/renderers/qopengl/waveformrendererrgb.cpp
@@ -104,7 +104,10 @@ void WaveformRendererRGB::renderGL() {
halfBreadth - 0.5f * devicePixelRatio,
static_cast<float>(length),
halfBreadth + 0.5f * devicePixelRatio);
- m_colors.addForRectangle(1.f, 1.f, 1.f);
+ m_colors.addForRectangle(
+ static_cast<float>(m_axesColor_r),
+ static_cast<float>(m_axesColor_g),
+ static_cast<float>(m_axesColor_b));
for (int pos = 0; pos < length; ++pos) {
// Our current pixel (x) corresponds to a number of visual samples
diff --git a/src/waveform/renderers/qopengl/waveformrenderersimple.cpp b/src/waveform/renderers/qopengl/waveformrenderersimple.cpp
new file mode 100644
index 0000000000..17ad3f440d
--- /dev/null
+++ b/src/waveform/renderers/qopengl/waveformrenderersimple.cpp
@@ -0,0 +1,181 @@
+#include "waveform/renderers/qopengl/waveformrenderersimple.h"
+
+#include "track/track.h"
+#include "util/math.h"
+#include "waveform/renderers/qopengl/calculatematrix.h"
+#include "waveform/waveform.h"
+#include "waveform/waveformwidgetfactory.h"
+#include "waveform/widgets/qopengl/waveformwidget.h"
+#include "widget/wskincolor.h"
+#include "widget/wwidget.h"
+
+using namespace qopengl;
+
+WaveformRendererSimple::WaveformRendererSimple(
+ WaveformWidgetRenderer* waveformWidget)
+ : WaveformRendererSignalBase(waveformWidget) {
+}
+
+WaveformRendererSimple::~WaveformRendererSimple() {
+}
+
+void WaveformRendererSimple::onSetup(const QDomNode& node) {
+ Q_UNUSED(node);
+}
+
+void WaveformRendererSimple::initializeGL() {
+ m_shader.init();
+}
+
+void WaveformRendererSimple::renderGL() {
+ TrackPointer pTrack = m_waveformRenderer->getTrackInfo();
+ if (!pTrack) {
+ return;
+ }
+
+ ConstWaveformPointer waveform = pTrack->getWaveform();
+ if (waveform.isNull()) {
+ return;
+ }
+
+ const int dataSize = waveform->getDataSize();
+ if (dataSize <= 1) {
+ return;
+ }
+
+ const WaveformData* data = waveform->data();
+ if (data == nullptr) {
+ return;
+ }
+
+ const float devicePixelRatio = m_waveformRenderer->getDevicePixelRatio();
+ const int length = static_cast<int>(m_waveformRenderer->getLength() * devicePixelRatio);
+
+ // Not multiplying with devicePixelRatio will also work. In that case, on
+ // High-DPI-Display the lines will be devicePixelRatio pixels wide (which is
+ // also what is used for the beat grid and the markers), or in other words
+ // each block of samples is represented by devicePixelRatio pixels (width).
+
+ const double firstVisualIndex = m_waveformRenderer->getFirstDisplayedPosition() * dataSize;
+ const double lastVisualIndex = m_waveformRenderer->getLastDisplayedPosition() * dataSize;
+
+ // Represents the # of waveform data points per horizontal pixel.
+ const double visualIncrementPerPixel =
+ (lastVisualIndex - firstVisualIndex) / static_cast<double>(length);
+
+ // Per-band gain from the EQ knobs.
+ float allGain{1.0};
+ float bandGain[3] = {1.0, 1.0, 1.0};
+ getGains(&allGain, &bandGain[0], &bandGain[1], &bandGain[2]);
+
+ const float breadth = static_cast<float>(m_waveformRenderer->getBreadth()) * devicePixelRatio;
+ const float halfBreadth = breadth / 2.0f;
+
+ const float heightFactor = allGain * halfBreadth / 255.f;
+
+ // Effective visual index of x
+ double xVisualSampleIndex = firstVisualIndex;
+
+ const int numVerticesPerLine = 6; // 2 triangles
+
+ int reserved[2];
+
+ reserved[0] = numVerticesPerLine * length;
+ m_vertices[0].clear();
+ m_vertices[0].reserve(reserved[0]);
+
+ // the horizontal line
+ reserved[1] = numVerticesPerLine;
+ m_vertices[1].clear();
+ m_vertices[1].reserve(reserved[1]);
+
+ m_vertices[1].addRectangle(
+ 0.f,
+ halfBreadth - 0.5f * devicePixelRatio,
+ static_cast<float>(length),
+ halfBreadth + 0.5f * devicePixelRatio);
+
+ for (int pos = 0; pos < length; ++pos) {
+ // Our current pixel (x) corresponds to a number of visual samples
+ // (visualSamplerPerPixel) in our waveform object. We take the max of
+ // all the data points on either side of xVisualSampleIndex within a
+ // window of 'maxSamplingRange' visual samples to measure the maximum
+ // data point contained by this pixel.
+ double maxSamplingRange = visualIncrementPerPixel / 2.0;
+
+ // Since xVisualSampleIndex is in visual-samples (e.g. R,L,R,L) we want
+ // to check +/- maxSamplingRange frames, not samples. To do this, divide
+ // xVisualSampleIndex by 2. Since frames indices are integers, we round
+ // to the nearest integer by adding 0.5 before casting to int.
+ int visualFrameStart = int(xVisualSampleIndex / 2.0 - maxSamplingRange + 0.5);
+ int visualFrameStop = int(xVisualSampleIndex / 2.0 + maxSamplingRange + 0.5);
+ const int lastVisualFrame = dataSize / 2 - 1;
+
+ // We now know that some subset of [visualFrameStart, visualFrameStop]
+ // lies within the valid range of visual frames. Clamp
+ // visualFrameStart/Stop to within [0, lastVisualFrame].
+ visualFrameStart = math_clamp(visualFrameStart, 0, lastVisualFrame);
+ visualFrameStop = math_clamp(visualFrameStop, 0, lastVisualFrame);
+
+ int visualIndexStart = visualFrameStart * 2;
+ int visualIndexStop = visualFrameStop * 2;
+
+ visualIndexStart = std::max(visualIndexStart, 0);
+ visualIndexStop = std::min(visualIndexStop, dataSize);
+
+ // 2 channels
+ float max[2]{};
+
+ for (int i = visualIndexStart; i < visualIndexStop; i += 2) {
+ for (int chn = 0; chn < 2; chn++) {
+ const WaveformData& waveformData = data[i + chn];
+ const float filteredAll = static_cast<float>(waveformData.filtered.all);
+
+ max[chn] = math_max(max[chn], filteredAll);
+ }
+ }
+
+ const float fpos = static_cast<float>(pos);
+
+ // lines are thin rectangles
+ m_vertices[0].addRectangle(
+ fpos - 0.5f,
+ halfBreadth - heightFactor * max[0],
+ fpos + 0.5f,
+ halfBreadth + heightFactor * max[1]);
+
+ xVisualSampleIndex += visualIncrementPerPixel;
+ }
+
+ const QMatrix4x4 matrix = calculateMatrix(m_waveformRenderer, true);
+
+ const int matrixLocation = m_shader.uniformLocation("matrix");
+ const int colorLocation = m_shader.uniformLocation("color");
+ const int positionLocation = m_shader.attributeLocation("position");
+
+ m_shader.bind();
+ m_shader.enableAttributeArray(positionLocation);
+
+ m_shader.setUniformValue(matrixLocation, matrix);
+
+ QColor colors[2];
+ colors[0].setRgbF(static_cast<float>(m_signalColor_r),
+ static_cast<float>(m_signalColor_g),
+ static_cast<float>(m_signalColor_b));
+ colors[1].setRgbF(static_cast<float>(m_axesColor_r),
+ static_cast<float>(m_axesColor_g),
+ static_cast<float>(m_axesColor_b),
+ static_cast<float>(m_axesColor_a));
+
+ for (int i = 0; i < 2; i++) {
+ DEBUG_ASSERT(reserved[i] == m_vertices[i].size());
+ m_shader.setUniformValue(colorLocation, colors[i]);
+ m_shader.setAttributeArray(
+ positionLocation, GL_FLOAT, m_vertices[i].constData(), 2);
+
+ glDrawArrays(GL_TRIANGLES, 0, m_vertices[i].size());
+ }
+
+ m_shader.disableAttributeArray(positionLocation);
+ m_shader.release();
+}
diff --git a/src/waveform/renderers/qopengl/waveformrenderersimple.h b/src/waveform/renderers/qopengl/waveformrenderersimple.h
new file mode 100644
index 0000000000..e63e7f6dba
--- /dev/null
+++ b/src/waveform/renderers/qopengl/waveformrenderersimple.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "util/class.h"
+#include "waveform/renderers/qopengl/shaders/unicolorshader.h"
+#include "waveform/renderers/qopengl/vertexdata.h"
+#include "waveform/renderers/qopengl/waveformrenderersignalbase.h"
+
+namespace qopengl {
+class WaveformRendererSimple;
+}
+
+class qopengl::WaveformRendererSimple final : public qopengl::WaveformRendererSignalBase {
+ public:
+ explicit WaveformRendererSimple(WaveformWidgetRenderer* waveformWidget);
+ ~WaveformRendererSimple() override;
+
+ // override ::WaveformRendererSignalBase
+ void onSetup(const QDomNode& node) override;
+
+ void initializeGL() override;
+ void renderGL() override;
+
+ private:
+ UnicolorShader m_shader;
+ VertexData m_vertices[2];
+
+ DISALLOW_COPY_AND_ASSIGN(WaveformRendererSimple);
+};
diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp
index 2ad7b2e15b..6ad520e86f 100644
--- a/src/waveform/waveformwidgetfactory.cpp
+++ b/src/waveform/waveformwidgetfactory.cpp
@@ -45,6 +45,7 @@
#include "waveform/widgets/qopengl/filteredwaveformwidget.h"
#include "waveform/widgets/qopengl/lrrgbwaveformwidget.h"
#include "waveform/widgets/qopengl/rgbwaveformwidget.h"
+#include "waveform/widgets/qopengl/simplewaveformwidget.h"
#endif
#include "widget/wvumeter.h"
#include "widget/wvumetergl.h"
@@ -968,6 +969,13 @@ void WaveformWidgetFactory::evaluateWidgets() {
useOpenGLShaders = qopengl::FilteredWaveformWidget::useOpenGLShaders();
developerOnly = qopengl::FilteredWaveformWidget::developerOnly();
break;
+ case WaveformWidgetType::QOpenGLSimpleWaveform:
+ widgetName = qopengl::SimpleWaveformWidget::getWaveformWidgetName();
+ useOpenGl = qopengl::SimpleWaveformWidget::useOpenGl();
+ useOpenGles = qopengl::SimpleWaveformWidget::useOpenGles();
+ useOpenGLShaders = qopengl::SimpleWaveformWidget::useOpenGLShaders();
+ developerOnly = qopengl::SimpleWaveformWidget::developerOnly();
+ break;
#endif
default:
DEBUG_ASSERT(!"Unexpected WaveformWidgetType");
@@ -1085,6 +1093,9 @@ WaveformWidgetAbstract* WaveformWidgetFactory::createWaveformWidget(
case WaveformWidgetType::QOpenGLFilteredWaveform:
widget = new qopengl::FilteredWaveformWidget(viewer->getGroup(), viewer);
break;
+ case WaveformWidgetType::QOpenGLSimpleWaveform:
+ widget = new qopengl::SimpleWaveformWidget(viewer->getGroup(), viewer);
+ break;
#endif
default:
//case WaveformWidgetType::SoftwareSimpleWaveform: TODO: (vrince)
diff --git a/src/waveform/widgets/qopengl/simplewaveformwidget.cpp b/src/waveform/widgets/qopengl/simplewaveformwidget.cpp
new file mode 100644
index 0000000000..6e2a98b511
--- /dev/null
+++ b/src/waveform/widgets/qopengl/simplewaveformwidget.cpp
@@ -0,0 +1,36 @@
+#include "waveform/widgets/qopengl/simplewaveformwidget.h"
+
+#include "waveform/renderers/qopengl/waveformrenderbackground.h"
+#include "waveform/renderers/qopengl/waveformrenderbeat.h"
+#include "waveform/renderers/qopengl/waveformrendererendoftrack.h"
+#include "waveform/renderers/qopengl/waveformrendererpreroll.h"
+#include "waveform/renderers/qopengl/waveformrenderersimple.h"
+#include "waveform/renderers/qopengl/waveformrendermark.h"
+#include "waveform/renderers/qopengl/waveformrendermarkrange.h"
+#include "waveform/widgets/qopengl/moc_simplewaveformwidget.cpp"
+
+using namespace qopengl;
+
+SimpleWaveformWidget::SimpleWaveformWidget(const QString& group, QWidget* parent)
+ : WaveformWidget(group, parent) {
+ addRenderer<WaveformRenderBackground>();
+ addRenderer<WaveformRendererEndOfTrack>();
+ addRenderer<WaveformRendererPreroll>();
+ addRenderer<WaveformRenderMarkRange>();
+ addRenderer<WaveformRendererSimple>();
+ addRenderer<WaveformRenderBeat>();
+ addRenderer<WaveformRenderMark>();
+
+ m_initSuccess = init();
+}
+
+SimpleWaveformWidget::~SimpleWaveformWidget() {
+}
+
+void SimpleWaveformWidget::castToQWidget() {
+ m_widget = this;
+}
+
+void SimpleWaveformWidget::paintEvent(QPaintEvent* event) {
+ Q_UNUSED(event);
+}
diff --git a/src/waveform/widgets/qopengl/simplewaveformwidget.h b/src/waveform/widgets/qopengl/simplewaveformwidget.h
new file mode 100644
index 0000000000..9dd3cf1ddb
--- /dev/null
+++ b/src/waveform/widgets/qopengl/simplewaveformwidget.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "util/class.h"
+#include "waveform/widgets/qopengl/waveformwidget.h"
+
+class WaveformWidgetFactory;
+
+namespace qopengl {
+class SimpleWaveformWidget;
+}
+
+class qopengl::SimpleWaveformWidget final : public qopengl::WaveformWidget {
+ Q_OBJECT
+ public:
+ ~SimpleWaveformWidget() override;
+
+ WaveformWidgetType::Type getType() const override {
+ return WaveformWidgetType::QOpenGLSimpleWaveform;
+ }
+
+ static inline QString getWaveformWidgetName() {
+ return tr("Simple (QOpenGL)");
+ }
+ static inline bool useOpenGl() {
+ return true;
+ }
+ static inline bool useOpenGles() {
+ return false;
+ }
+ static inline bool useOpenGLShaders() {
+ return true;
+ }
+ static inline bool developerOnly() {
+ return false;
+ }
+
+ protected:
+ void castToQWidget() override;
+ void paintEvent(QPaintEvent* event) override;
+
+ private:
+ SimpleWaveformWidget(const QString& group, QWidget* parent);
+ friend class ::WaveformWidgetFactory;
+
+ DISALLOW_COPY_AND_ASSIGN(SimpleWaveformWidget);
+};
diff --git a/src/waveform/widgets/waveformwidgettype.h b/src/waveform/widgets/waveformwidgettype.h
index 956a20ab3d..16823ee88c 100644
--- a/src/waveform/widgets/waveformwidgettype.h
+++ b/src/waveform/widgets/waveformwidgettype.h
@@ -26,6 +26,7 @@ class WaveformWidgetType {
QOpenGLRGBWaveform, // 17 RGB (QOpenGL)
QOpenGLLRRGBWaveform, // 18 RGB (QOpenGL)
QOpenGLFilteredWaveform, // 19 Filtered (QOpenGL)
+ QOpenGLSimpleWaveform, // 20 Simple (QOpenGL)
#endif
Count_WaveformwidgetType // Also used as invalid value
};