Skip to content

Commit

Permalink
Merge pull request #12466 from m0dB/waveform-tweaks
Browse files Browse the repository at this point in the history
Waveform tweaks
  • Loading branch information
Swiftb0y authored Jan 2, 2024
2 parents 79d240c + 3fb504e commit 77c175c
Show file tree
Hide file tree
Showing 17 changed files with 82 additions and 23 deletions.
10 changes: 10 additions & 0 deletions src/analyzer/analyzerwaveform.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ inline CSAMPLE scaleSignal(CSAMPLE invalue, FilterIndex index = FilterCount) {
} else {
return std::pow(invalue, 2.0f * 0.316f);
}

// According to this discussion
// https://github.com/mixxxdj/mixxx/issues/6352
// it looks like this scaling is done to accentuate
// low level information.

// This scaling can be undone with a function in
// waveform/renderers/waveformrenderersignalbase.h
// but arguable it would be better not to do this scaling here at all
// and do it (or not) at the waveform renderer side.
}

struct WaveformStride {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void WaveformRendererFiltered::paintGL() {
// 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]);
getGains(&allGain, true, &bandGain[0], &bandGain[1], &bandGain[2]);

const float breadth = static_cast<float>(m_waveformRenderer->getBreadth()) * devicePixelRatio;
const float halfBreadth = breadth / 2.0f;
Expand Down
4 changes: 3 additions & 1 deletion src/waveform/renderers/allshader/waveformrendererhsv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void WaveformRendererHSV::paintGL() {
(lastVisualFrame - firstVisualFrame) / static_cast<double>(length);

float allGain(1.0);
getGains(&allGain, nullptr, nullptr, nullptr);
getGains(&allGain, false, nullptr, nullptr, nullptr);

// Get base color of waveform in the HSV format (s and v isn't use)
float h, s, v;
Expand Down Expand Up @@ -130,6 +130,8 @@ void WaveformRendererHSV::paintGL() {
maxMid[chn] = static_cast<float>(u8maxMid);
maxHigh[chn] = static_cast<float>(u8maxHigh);
maxAll[chn] = static_cast<float>(u8maxAll);
// Uncomment to undo scaling with pow(value, 2.0f * 0.316f) done in analyzerwaveform.h
// maxAll[chn] = unscale(u8maxAll);
}

float total{};
Expand Down
5 changes: 4 additions & 1 deletion src/waveform/renderers/allshader/waveformrendererlrrgb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ void WaveformRendererLRRGB::paintGL() {

// Per-band gain from the EQ knobs.
float allGain(1.0), lowGain(1.0), midGain(1.0), highGain(1.0);
getGains(&allGain, &lowGain, &midGain, &highGain);
// applyCompensation = false, as we scale to match filtered.all
getGains(&allGain, false, &lowGain, &midGain, &highGain);

const float breadth = static_cast<float>(m_waveformRenderer->getBreadth()) * devicePixelRatio;
const float halfBreadth = breadth / 2.0f;
Expand Down Expand Up @@ -137,6 +138,8 @@ void WaveformRendererLRRGB::paintGL() {
float maxMid = static_cast<float>(u8maxMid);
float maxHigh = static_cast<float>(u8maxHigh);
float maxAll = static_cast<float>(u8maxAll);
// Uncomment to undo scaling with pow(value, 2.0f * 0.316f) done in analyzerwaveform.h
// float maxAll = unscale(u8maxAll);

// Calculate the squared magnitude of the maxLow, maxMid and maxHigh values.
// We take the square root to get the magnitude below.
Expand Down
5 changes: 4 additions & 1 deletion src/waveform/renderers/allshader/waveformrendererrgb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ void WaveformRendererRGB::paintGL() {

// Per-band gain from the EQ knobs.
float allGain(1.0), lowGain(1.0), midGain(1.0), highGain(1.0);
getGains(&allGain, &lowGain, &midGain, &highGain);
// applyCompensation = false, as we scale to match filtered.all
getGains(&allGain, false, &lowGain, &midGain, &highGain);

const float breadth = static_cast<float>(m_waveformRenderer->getBreadth()) * devicePixelRatio;
const float halfBreadth = breadth / 2.0f;
Expand Down Expand Up @@ -139,6 +140,8 @@ void WaveformRendererRGB::paintGL() {
float maxMid = static_cast<float>(u8maxMid);
float maxHigh = static_cast<float>(u8maxHigh);
float maxAllChn[2]{static_cast<float>(u8maxAllChn[0]), static_cast<float>(u8maxAllChn[1])};
// Uncomment to undo scaling with pow(value, 2.0f * 0.316f) done in analyzerwaveform.h
// float maxAllChn[2]{unscale(u8maxAllChn[0]), unscale(u8maxAllChn[1])};

// Calculate the squared magnitude of the maxLow, maxMid and maxHigh values.
// We take the square root to get the magnitude below.
Expand Down
5 changes: 4 additions & 1 deletion src/waveform/renderers/allshader/waveformrenderersimple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void WaveformRendererSimple::paintGL() {
// 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]);
getGains(&allGain, false, &bandGain[0], &bandGain[1], &bandGain[2]);

const float breadth = static_cast<float>(m_waveformRenderer->getBreadth()) * devicePixelRatio;
const float halfBreadth = breadth / 2.0f;
Expand Down Expand Up @@ -120,6 +120,9 @@ void WaveformRendererSimple::paintGL() {
for (int i = visualIndexStart + chn; i < visualIndexStop + chn; i += 2) {
const WaveformData& waveformData = data[i];
const float filteredAll = static_cast<float>(waveformData.filtered.all);
// Uncomment to undo scaling with pow(value, 2.0f * 0.316f) done
// in analyzerwaveform.h const float filteredAll =
// unscale(waveformData.filtered.all);

max[chn] = math_max(max[chn], filteredAll);
}
Expand Down
2 changes: 1 addition & 1 deletion src/waveform/renderers/glslwaveformrenderersignal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ void GLSLWaveformRendererSignal::draw(QPainter* painter, QPaintEvent* /*event*/)

// Per-band gain from the EQ knobs.
float lowGain(1.0), midGain(1.0), highGain(1.0), allGain(1.0);
getGains(&allGain, &lowGain, &midGain, &highGain);
getGains(&allGain, true, &lowGain, &midGain, &highGain);

const auto firstVisualIndex = static_cast<GLfloat>(
m_waveformRenderer->getFirstDisplayedPosition() * trackSamples /
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void GLWaveformRendererFilteredSignal::draw(QPainter* painter, QPaintEvent* /*ev

// Per-band gain from the EQ knobs.
float allGain(1.0), lowGain(1.0), midGain(1.0), highGain(1.0);
getGains(&allGain, &lowGain, &midGain, &highGain);
getGains(&allGain, true, &lowGain, &midGain, &highGain);

if (m_alignment == Qt::AlignCenter) {
glMatrixMode(GL_PROJECTION);
Expand Down
2 changes: 1 addition & 1 deletion src/waveform/renderers/glwaveformrendererrgb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void GLWaveformRendererRGB::draw(QPainter* painter, QPaintEvent* /*event*/) {

// Per-band gain from the EQ knobs.
float allGain(1.0), lowGain(1.0), midGain(1.0), highGain(1.0);
getGains(&allGain, &lowGain, &midGain, &highGain);
getGains(&allGain, true, &lowGain, &midGain, &highGain);

if (m_alignment == Qt::AlignCenter) {
glMatrixMode(GL_PROJECTION);
Expand Down
2 changes: 1 addition & 1 deletion src/waveform/renderers/glwaveformrenderersimplesignal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void GLWaveformRendererSimpleSignal::draw(QPainter* painter, QPaintEvent* /*even
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

float allGain(1.0);
getGains(&allGain, nullptr, nullptr, nullptr);
getGains(&allGain, false, nullptr, nullptr, nullptr);

if (m_alignment == Qt::AlignCenter) {
glMatrixMode(GL_PROJECTION);
Expand Down
2 changes: 1 addition & 1 deletion src/waveform/renderers/waveformrendererfilteredsignal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ void WaveformRendererFilteredSignal::draw(QPainter* painter,

// Per-band gain from the EQ knobs.
float allGain(1.0), lowGain(1.0), midGain(1.0), highGain(1.0);
getGains(&allGain, &lowGain, &midGain, &highGain);
getGains(&allGain, true, &lowGain, &midGain, &highGain);

const float breadth = m_waveformRenderer->getBreadth();
const float halfBreadth = breadth / 2.0f;
Expand Down
2 changes: 1 addition & 1 deletion src/waveform/renderers/waveformrendererhsv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ void WaveformRendererHSV::draw(
(double)m_waveformRenderer->getLength();

float allGain(1.0);
getGains(&allGain, nullptr, nullptr, nullptr);
getGains(&allGain, false, nullptr, nullptr, nullptr);

// Get base color of waveform in the HSV format (s and v isn't use)
float h, s, v;
Expand Down
2 changes: 1 addition & 1 deletion src/waveform/renderers/waveformrendererrgb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void WaveformRendererRGB::draw(

// Per-band gain from the EQ knobs.
float allGain(1.0), lowGain(1.0), midGain(1.0), highGain(1.0);
getGains(&allGain, &lowGain, &midGain, &highGain);
getGains(&allGain, true, &lowGain, &midGain, &highGain);

QColor color;

Expand Down
19 changes: 16 additions & 3 deletions src/waveform/renderers/waveformrenderersignalbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,14 @@ void WaveformRendererSignalBase::setup(const QDomNode& node,
onSetup(node);
}

void WaveformRendererSignalBase::getGains(float* pAllGain, float* pLowGain,
float* pMidGain, float* pHighGain) {
void WaveformRendererSignalBase::getGains(float* pAllGain,
bool applyCompensation,
float* pLowGain,
float* pMidGain,
float* pHighGain) {
WaveformWidgetFactory* factory = WaveformWidgetFactory::instance();
if (pAllGain) {
*pAllGain = static_cast<CSAMPLE_GAIN>(m_waveformRenderer->getGain()) *
*pAllGain = static_cast<CSAMPLE_GAIN>(m_waveformRenderer->getGain(applyCompensation)) *
static_cast<CSAMPLE_GAIN>(factory->getVisualGain(WaveformWidgetFactory::All));
;
}
Expand Down Expand Up @@ -223,3 +226,13 @@ void WaveformRendererSignalBase::getGains(float* pAllGain, float* pLowGain,
}
}
}

std::span<float, 256> WaveformRendererSignalBase::unscaleTable() {
// Table to undo the scaling std::pow(invalue, 2.0f * 0.316f);
// done in scaleSignal in analyzerwaveform.h
static std::array<float, 256> result;
for (int i = 0; i < 256; i++) {
result[i] = 255.f * std::pow(static_cast<float>(i) / 255.f, 1.f / 0.632f);
}
return result;
}
20 changes: 17 additions & 3 deletions src/waveform/renderers/waveformrenderersignalbase.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include "waveformrendererabstract.h"
#include <span>

#include "skin/legacy/skincontext.h"
#include "waveformrendererabstract.h"

class ControlProxy;
class WaveformSignalColors;
Expand All @@ -20,8 +22,20 @@ class WaveformRendererSignalBase : public WaveformRendererAbstract {
protected:
void deleteControls();

void getGains(float* pAllGain, float* pLowGain, float* pMidGain,
float* highGain);
void getGains(float* pAllGain,
bool applyCompensation,
float* pLowGain,
float* pMidGain,
float* highGain);

static std::span<float, 256> unscaleTable();
inline float unscale(unsigned char value) {
// The all and hi components of the waveform data are scaled with pow(value, 2.0f * 0.316f)
// (see analyzerwaveform.h). This function can be used to undo that scaling,
// but apparently it is intentional.
static const auto table = unscaleTable();
return table[value];
}

protected:
ControlProxy* m_pEQEnabled;
Expand Down
4 changes: 1 addition & 3 deletions src/waveform/renderers/waveformwidgetrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,7 @@ void WaveformWidgetRenderer::onPreRender(VSyncThread* vsyncThread) {
//Fetch parameters before rendering in order the display all sub-renderers with the same values
double rateRatio = m_pRateRatioCO->get();

// This gain adjustment compensates for an arbitrary /2 gain chop in
// EnginePregain. See the comment there.
m_gain = m_pGainControlObject->get() * 2;
m_gain = m_pGainControlObject->get();

// Compute visual sample to pixel ratio
// Allow waveform to spread one visual sample across a hundred pixels
Expand Down
17 changes: 15 additions & 2 deletions src/waveform/renderers/waveformwidgetrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,21 @@ class WaveformWidgetRenderer {
double getZoomFactor() const {
return m_zoomFactor;
}
double getGain() const {
return m_gain;
double getGain(bool applyCompensation) const {
// m_gain was always multiplied by 2.0, according to a comment:
//
// "This gain adjustment compensates for an arbitrary /2 gain chop in
// EnginePregain. See the comment there."
//
// However, no comment there seems to explain this, and it resulted
// in renderers that use the filtered.all data for the amplitude, to
// be twice the expected value.
// But without this compensation, renderers that use the combined
// lo, mid, hi values became much lower than expected. By making this
// optional we move the decision to each renderer whether to apply the
// compensation or not, in order to have a more similar amplitude across
// waveform renderers
return applyCompensation ? m_gain * 2.f : m_gain;
}
double getTrackSamples() const {
return m_trackSamples;
Expand Down

0 comments on commit 77c175c

Please sign in to comment.