Commit 1287ec34 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Remove unused/duplicate code

parent b0078669
Pipeline #106422 passed with stage
in 5 minutes and 24 seconds
set(kdenlive_SRCS
${kdenlive_SRCS}
audiospectrum/audiographspectrum.cpp
PARENT_SCOPE)
/*
SPDX-FileCopyrightText: 2016 Jean-Baptiste Mardelle <jb@kdenlive.org>
This file is part of Kdenlive. See www.kdenlive.org.
SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "audiographspectrum.h"
#include "../monitor/monitormanager.h"
#include "kdenlivesettings.h"
#include <QAction>
#include <QFontDatabase>
#include <QGridLayout>
#include <QPaintEvent>
#include <QPainter>
#include <QVBoxLayout>
#include "iecscale.h"
#include <mlt++/Mlt.h>
// Code borrowed from Shotcut's audiospectum by Brian Matherly <code@brianmatherly.com> (GPL)
static const int WINDOW_SIZE = 8000; // 6 Hz FFT bins at 48kHz
struct band
{
float low; // Low frequency
float high; // High frequency
const char *label;
};
// Preferred frequencies from ISO R 266-1997 / ANSI S1.6-1984
static const band BAND_TAB[] = {
// Low Preferred High Band
// Freq Center Freq Label Num
{1.12, 1.25, 1.41, "1.25"}, // 1
{1.41, 1.60, 1.78, "1.6"}, // 2
{1.78, 2.00, 2.24, "2.0"}, // 3
{2.24, 2.50, 2.82, "2.5"}, // 4
{2.82, 3.15, 3.55, "3.15"}, // 5
{3.55, 4.00, 4.44, "4.0"}, // 6
{4.44, 5.00, 6.00, "5.0"}, // 7
{6.00, 6.30, 7.00, "6.3"}, // 8
{7.00, 8.00, 9.00, "8.0"}, // 9
{9.00, 10.00, 11.00, "10"}, // 10
{11.00, 12.50, 14.00, "12.5"}, // 11
{14.00, 16.00, 18.00, "16"}, // 12
{18.00, 20.00, 22.00, "20"}, // 13 - First in audible range
{22.00, 25.00, 28.00, "25"}, // 14
{28.00, 31.50, 35.00, "31"}, // 15
{35.00, 40.00, 45.00, "40"}, // 16
{45.00, 50.00, 56.00, "50"}, // 17
{56.00, 63.00, 71.00, "63"}, // 18
{71.00, 80.00, 90.00, "80"}, // 19
{90.00, 100.00, 112.00, "100"}, // 20
{112.00, 125.00, 140.00, "125"}, // 21
{140.00, 160.00, 179.00, "160"}, // 22
{179.00, 200.00, 224.00, "200"}, // 23
{224.00, 250.00, 282.00, "250"}, // 24
{282.00, 315.00, 353.00, "315"}, // 25
{353.00, 400.00, 484.00, "400"}, // 26
{484.00, 500.00, 560.00, "500"}, // 27
{560.00, 630.00, 706.00, "630"}, // 28
{706.00, 800.00, 897.00, "800"}, // 29
{897.00, 1000.00, 1121.00, "1k"}, // 30
{1121.00, 1250.00, 1401.00, "1.3k"}, // 31
{1401.00, 1600.00, 1794.00, "1.6k"}, // 32
{1794.00, 2000.00, 2242.00, "2k"}, // 33
{2242.00, 2500.00, 2803.00, "2.5k"}, // 34
{2803.00, 3150.00, 3531.00, "3.2k"}, // 35
{3531.00, 4000.00, 4484.00, "4k"}, // 36
{4484.00, 5000.00, 5605.00, "5k"}, // 37
{5605.00, 6300.00, 7062.00, "6.3k"}, // 38
{7062.00, 8000.00, 8908.00, "8k"}, // 39
{8908.00, 10000.00, 11210.00, "10k"}, // 40
{11210.00, 12500.00, 14012.00, "13k"}, // 41
{14012.00, 16000.00, 17936.00, "16k"}, // 42
{17936.00, 20000.00, 22421.00, "20k"}, // 43 - Last in audible range
};
static const int FIRST_AUDIBLE_BAND_INDEX = 12;
static const int LAST_AUDIBLE_BAND_INDEX = 42;
static const int AUDIBLE_BAND_COUNT = LAST_AUDIBLE_BAND_INDEX - FIRST_AUDIBLE_BAND_INDEX + 1;
EqualizerWidget::EqualizerWidget(QWidget *parent)
: QWidget(parent)
{
QGridLayout *box = new QGridLayout(this);
QStringList labels;
labels << i18n("Master") << "50Hz"
<< "100Hz"
<< "156Hz"
<< "220Hz"
<< "311Hz"
<< "440Hz"
<< "622Hz"
<< "880Hz"
<< "1.25kHz"
<< "1.75kHz"
<< "2.5kHz"
<< "3.5kHz"
<< "5kHz"
<< "10kHz"
<< "20kHz";
for (int i = 0; i < 16; i++) {
QSlider *sl = new QSlider(Qt::Vertical, this);
sl->setObjectName(QString::number(i));
box->addWidget(sl, 0, i);
QLabel *lab = new QLabel(labels.at(i), this);
box->addWidget(lab, 1, i);
}
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
}
AudioGraphWidget::AudioGraphWidget(QWidget *parent)
: QWidget(parent)
{
m_dbLabels << -50 << -40 << -35 << -30 << -25 << -20 << -15 << -10 << -5 << 0;
for (int i = FIRST_AUDIBLE_BAND_INDEX; i <= LAST_AUDIBLE_BAND_INDEX; i++) {
m_freqLabels << BAND_TAB[i].label;
}
m_maxDb = 0;
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
setMinimumHeight(100);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
}
void AudioGraphWidget::showAudio(const QVector<float> &bands)
{
m_levels = bands;
update();
}
void AudioGraphWidget::drawDbLabels(QPainter &p, const QRect &rect)
{
int dbLabelCount = m_dbLabels.size();
int textHeight = fontMetrics().ascent();
if (dbLabelCount == 0) {
return;
}
int maxWidth = fontMetrics().width(QStringLiteral("-50"));
// dB scale is vertical along the left side
int prevY = height();
QColor textCol = palette().text().color();
QColor lineCol = textCol;
p.setOpacity(0.8);
lineCol.setAlpha(100);
for (int i = 0; i < dbLabelCount; i++) {
int value = m_dbLabels[i];
QString label = QString::number(value);
int x = rect.left() + maxWidth - fontMetrics().width(label);
int yline = rect.bottom() - IEC_ScaleMax(value, m_maxDb) * rect.height();
int y = yline + textHeight / 2;
if (y - textHeight < 0) {
y = textHeight;
}
if (prevY - y >= 2) {
p.setPen(textCol);
p.drawText(x, y, label);
p.setPen(lineCol);
p.drawLine(rect.left() + maxWidth + 2, yline, rect.width(), yline);
prevY = y - textHeight;
}
}
}
void AudioGraphWidget::drawChanLabels(QPainter &p, const QRect &rect, int barWidth)
{
int chanLabelCount = m_freqLabels.size();
int stride = 1;
if (chanLabelCount == 0) {
return;
}
p.setPen(palette().text().color().rgb());
// Channel labels are horizontal along the bottom.
// Find the widest channel label
int chanLabelWidth = 0;
for (int i = 0; i < chanLabelCount; i++) {
int width = fontMetrics().width(m_freqLabels.at(i)) + 2;
chanLabelWidth = width > chanLabelWidth ? width : chanLabelWidth;
}
int length = rect.width();
while (chanLabelWidth * chanLabelCount / stride > length) {
stride++;
}
int prevX = 0;
int y = rect.bottom();
for (int i = 0; i < chanLabelCount; i += stride) {
QString label = m_freqLabels.at(i);
int x = rect.left() + (2 * i) + i * barWidth + barWidth / 2 - fontMetrics().width(label) / 2;
if (x > prevX) {
p.drawText(x, y, label);
prevX = x + fontMetrics().width(label);
}
}
}
void AudioGraphWidget::resizeEvent(QResizeEvent *event)
{
drawBackground();
QWidget::resizeEvent(event);
}
void AudioGraphWidget::drawBackground()
{
QSize size(width(), height());
if (!size.isValid()) {
return;
}
m_pixmap = QPixmap(size);
if (m_pixmap.isNull()) {
return;
}
m_pixmap.fill(palette().base().color());
QPainter p(&m_pixmap);
QRect rect(0, 0, width() - 3, height());
p.setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
drawDbLabels(p, rect);
int offset = fontMetrics().width(QStringLiteral("888")) + 2;
rect.adjust(offset, 0, 0, 0);
int barWidth = (rect.width() - (2 * (AUDIBLE_BAND_COUNT - 1))) / AUDIBLE_BAND_COUNT;
if (barWidth > 0) {
drawChanLabels(p, rect, barWidth);
}
rect.adjust(0, 0, 0, -fontMetrics().height());
m_rect = rect;
}
void AudioGraphWidget::paintEvent(QPaintEvent *pe)
{
QPainter p(this);
p.setClipRect(pe->rect());
p.drawPixmap(0, 0, m_pixmap);
if (m_levels.isEmpty()) {
return;
}
int chanCount = m_levels.size();
int height = m_rect.height();
int barWidth = (m_rect.width() - (2 * (AUDIBLE_BAND_COUNT - 1))) / AUDIBLE_BAND_COUNT;
p.setOpacity(0.6);
for (int i = 0; i < chanCount; i++) {
double level = IEC_ScaleMax(m_levels.at(i), m_maxDb) * height;
p.fillRect(m_rect.left() + i * barWidth + (2 * i), height - level, barWidth, level, Qt::darkGreen);
}
}
AudioGraphSpectrum::AudioGraphSpectrum(MonitorManager *manager, QWidget *parent)
: QWidget(parent)
, m_manager(manager)
, m_filter(0)
, m_graphWidget(0)
{
QVBoxLayout *lay = new QVBoxLayout(this);
m_graphWidget = new AudioGraphWidget(this);
lay->addWidget(m_graphWidget);
Mlt::Profile profile;
m_filter = new Mlt::Filter(profile, "fft");
if (!m_filter->is_valid()) {
KdenliveSettings::setEnableaudiospectrum(false);
KMessageWidget *mw = new KMessageWidget(this);
mw->setCloseButtonVisible(false);
mw->setWordWrap(true);
mw->setMessageType(KMessageWidget::Information);
mw->setText(i18n("MLT must be compiled with libfftw3 to enable Audio Spectrum"));
lay->addWidget(mw);
mw->show();
setEnabled(false);
return;
}
/*m_equalizer = new EqualizerWidget(this);
lay->addWidget(m_equalizer);
lay->setStretchFactor(m_graphWidget, 5);
lay->setStretchFactor(m_equalizer, 3);*/
m_filter->set("window_size", WINDOW_SIZE);
connect(m_manager, &MonitorManager::updateAudioSpectrum, this, &AudioGraphSpectrum::processSpectrum);
QAction *a = new QAction(i18n("Enable Audio Spectrum"), this);
a->setCheckable(true);
a->setChecked(KdenliveSettings::enableaudiospectrum());
connect(a, &QAction::triggered, m_manager, &MonitorManager::activateAudioSpectrum);
addAction(a);
setContextMenuPolicy(Qt::ActionsContextMenu);
}
AudioGraphSpectrum::~AudioGraphSpectrum()
{
delete m_graphWidget;
// delete m_filter;
}
void AudioGraphSpectrum::refreshPixmap()
{
if (m_graphWidget) {
m_graphWidget->drawBackground();
}
}
void AudioGraphSpectrum::processSpectrum(const SharedFrame &frame)
{
if (!isVisible()) {
return;
}
mlt_audio_format format = mlt_audio_s16;
int channels = frame.get_audio_channels();
int frequency = frame.get_audio_frequency();
int samples = frame.get_audio_samples();
Mlt::Frame mFrame = frame.clone(true, false, false);
m_filter->process(mFrame);
mFrame.get_audio(format, frequency, channels, samples);
QVector<double> bands(AUDIBLE_BAND_COUNT);
float *bins = (float *)m_filter->get_data("bins");
int bin_count = m_filter->get_int("bin_count");
double bin_width = m_filter->get_double("bin_width");
int band = 0;
bool firstBandFound = false;
for (int bin = 0; bin < bin_count; bin++) {
// Loop through all the FFT bins and align bin frequencies with
// band frequencies.
double F = bin_width * (double)bin;
if (!firstBandFound) {
// Skip bins that come before the first band.
if (BAND_TAB[band + FIRST_AUDIBLE_BAND_INDEX].low > F) {
continue;
} else {
firstBandFound = true;
bands[band] = bins[bin];
}
} else if (BAND_TAB[band + FIRST_AUDIBLE_BAND_INDEX].high < F) {
// This bin is outside of this band - move to the next band.
band++;
if ((band + FIRST_AUDIBLE_BAND_INDEX) > LAST_AUDIBLE_BAND_INDEX) {
// Skip bins that come after the last band.
break;
}
bands[band] = bins[bin];
} else if (bands[band] < bins[bin]) {
// Pick the highest bin level within this band to represent the
// whole band.
bands[band] = bins[bin];
}
}
// At this point, bands contains the magnitude of the signal for each
// band. Convert to dB.
for (band = 0; band < bands.size(); band++) {
double mag = bands[band];
double dB = mag > 0.0 ? 20 * log10(mag) : -1000.0;
bands[band] = dB;
}
// Update the audio signal widget
QMetaObject::invokeMethod(m_graphWidget, "showAudio", Qt::QueuedConnection, Q_ARG(const QVector<float> &, bands));
}
/*
SPDX-FileCopyrightText: 2016 Jean-Baptiste Mardelle <jb@kdenlive.org>
This file is part of Kdenlive. See www.kdenlive.org.
SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef AUDIOGRAPHSPECTRUM_H
#define AUDIOGRAPHSPECTRUM_H
#include "../monitor/scopes/sharedframe.h"
#include <QPixmap>
#include <QVector>
#include <QWidget>
namespace Mlt {
class Filter;
}
class MonitorManager;
class EqualizerWidget : public QWidget
{
Q_OBJECT
public:
explicit EqualizerWidget(QWidget *parent = nullptr);
};
/** @class AudioGraphWidget
@brief \@todo Describe class AudioGraphWidget
@todo Describe class AudioGraphWidget
*/
class AudioGraphWidget : public QWidget
{
Q_OBJECT
public:
explicit AudioGraphWidget(QWidget *parent = nullptr);
void drawBackground();
public slots:
void showAudio(const QVector<float> &bands);
protected:
void paintEvent(QPaintEvent *pe);
void resizeEvent(QResizeEvent *event);
private:
QVector<double> m_levels;
QVector<int> m_dbLabels;
QStringList m_freqLabels;
QPixmap m_pixmap;
QRect m_rect;
int m_maxDb;
void drawDbLabels(QPainter &p, const QRect &rect);
void drawChanLabels(QPainter &p, const QRect &rect, int barWidth);
};
/** @class AudioGraphSpectrum
@brief An audio spectrum allowing to edit audio level / equalize clips or tracks
@author Jean-Baptiste Mardelle
*/
class AudioGraphSpectrum : public QWidget
{
Q_OBJECT
public:
AudioGraphSpectrum(MonitorManager *manager, QWidget *parent = nullptr);
virtual ~AudioGraphSpectrum();
private:
MonitorManager *m_manager;
Mlt::Filter *m_filter;
AudioGraphWidget *m_graphWidget;
EqualizerWidget *m_equalizer;
public slots:
void processSpectrum(const SharedFrame &frame);
void refreshPixmap();
};
#endif
/*
SPDX-FileCopyrightText: 2015 Meltytech LLC
SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef IECSCALE_H
#define IECSCALE_H
//----------------------------------------------------------------------------
// IEC standard dB scaling -- as borrowed from meterbridge (c) Steve Harris
static inline double IEC_Scale(double dB)
{
double fScale = 1.0f;
if (dB < -70.0f) {
fScale = 0.0f;
} else if (dB < -60.0f) {
fScale = (dB + 70.0f) * 0.0025f;
} else if (dB < -50.0f) {
fScale = (dB + 60.0f) * 0.005f + 0.025f;
} else if (dB < -40.0) {
fScale = (dB + 50.0f) * 0.0075f + 0.075f;
} else if (dB < -30.0f) {
fScale = (dB + 40.0f) * 0.015f + 0.15f;
} else if (dB < -20.0f) {
fScale = (dB + 30.0f) * 0.02f + 0.3f;
} else if (dB < -0.001f || dB > 0.001f) { /* if (dB < 0.0f) */
fScale = (dB + 20.0f) * 0.025f + 0.5f;
}
return fScale;
}
static inline double IEC_ScaleMax(double dB, double max)
{
return IEC_Scale(dB) / IEC_Scale(max);
}
#endif // IECSCALE_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment