diff --git a/Benchmark/Benchmark.vcxproj.filters b/Benchmark/Benchmark.vcxproj.filters
index 9eead87..d4a0a88 100644
--- a/Benchmark/Benchmark.vcxproj.filters
+++ b/Benchmark/Benchmark.vcxproj.filters
@@ -13,12 +13,12 @@
helpers
-
-
- {8c70f87a-7d86-4826-bfa1-7a4c4ec5efec}
+
+
+
\ No newline at end of file
diff --git a/Common.vcxproj b/Common.vcxproj
index 0e43989..d5daff0 100644
--- a/Common.vcxproj
+++ b/Common.vcxproj
@@ -158,6 +158,10 @@
+
+
+
+
@@ -208,6 +212,9 @@
+
+
+
@@ -234,6 +241,9 @@
Create
+
+
+
diff --git a/Common.vcxproj.filters b/Common.vcxproj.filters
index 1d29d20..690105f 100644
--- a/Common.vcxproj.filters
+++ b/Common.vcxproj.filters
@@ -129,6 +129,18 @@
+
+ filters\loudnessCorrection
+
+
+ filters\loudnessCorrection
+
+
+ filters\loudnessCorrection
+
+
+ filters\loudnessCorrection
+
@@ -246,6 +258,15 @@
+
+ filters\loudnessCorrection
+
+
+ filters\loudnessCorrection
+
+
+ filters\loudnessCorrection
+
@@ -260,5 +281,11 @@
{4a6738bc-7359-4b18-bdb4-1f443f41e528}
+
+ {c473f978-6002-42aa-adf5-3b5f10868d2d}
+
+
+
+
\ No newline at end of file
diff --git a/Editor/Editor.pro b/Editor/Editor.pro
index 8f58c3f..0f76788 100644
--- a/Editor/Editor.pro
+++ b/Editor/Editor.pro
@@ -124,7 +124,14 @@ SOURCES += main.cpp\
guis/VSTPluginFilterGUIDialog.cpp \
../filters/VSTPluginFilter.cpp \
../filters/VSTPluginFilterFactory.cpp \
- ../helpers/VSTPluginInstance.cpp
+ ../helpers/VSTPluginInstance.cpp \
+ guis/LoudnessCorrectionFilterGUI.cpp \
+ guis/LoudnessCorrectionFilterGUIFactory.cpp \
+ ../filters/loudnessCorrection/LoudnessCorrectionFilter.cpp \
+ ../filters/loudnessCorrection/LoudnessCorrectionFilterFactory.cpp \
+ ../filters/loudnessCorrection/VolumeController.cpp \
+ guis/LoudnessCorrectionFilterGUIDialog.cpp \
+ helpers/QtSndfileHandle.cpp
HEADERS += \
../helpers/LogHelper.h \
@@ -237,7 +244,15 @@ HEADERS += \
guis/VSTPluginFilterGUIDialog.h \
../filters/VSTPluginFilter.h \
../filters/VSTPluginFilterFactory.h \
- ../helpers/VSTPluginInstance.h
+ ../helpers/VSTPluginInstance.h \
+ guis/LoudnessCorrectionFilterGUI.h \
+ guis/LoudnessCorrectionFilterGUIFactory.h \
+ ../filters/loudnessCorrection/LoudnessCorrectionFilter.h \
+ ../filters/loudnessCorrection/LoudnessCorrectionFilterFactory.h \
+ ../filters/loudnessCorrection/ParameterArchive.h \
+ ../filters/loudnessCorrection/VolumeController.h \
+ guis/LoudnessCorrectionFilterGUIDialog.h \
+ helpers/QtSndfileHandle.h
FORMS += \
guis/PreampFilterGUI.ui \
@@ -257,10 +272,12 @@ FORMS += \
MainWindow.ui \
guis/StageFilterGUI.ui \
guis/VSTPluginFilterGUI.ui \
- guis/VSTPluginFilterGUIDialog.ui
+ guis/VSTPluginFilterGUIDialog.ui \
+ guis/LoudnessCorrectionFilterGUI.ui \
+ guis/LoudnessCorrectionFilterGUIDialog.ui
INCLUDEPATH += $$PWD/.. "C:/Program Files/libsndfile/include" "C:/Program Files/fftw3" "C:/Program Files/muparserx_v3_0_1/parser"
-LIBS += user32.lib advapi32.lib version.lib ole32.lib Shlwapi.lib authz.lib crypt32.lib dbghelp.lib libsndfile-1.lib libfftw3f-3.lib
+LIBS += user32.lib advapi32.lib version.lib ole32.lib Shlwapi.lib authz.lib crypt32.lib dbghelp.lib winmm.lib libsndfile-1.lib libfftw3f-3.lib
build_pass:CONFIG(debug, debug|release) {
LIBS += muparserxd.lib
diff --git a/Editor/Editor.qrc b/Editor/Editor.qrc
index b8f9f64..1229442 100644
--- a/Editor/Editor.qrc
+++ b/Editor/Editor.qrc
@@ -23,5 +23,6 @@
icons/normalize_response.icoicons/reset_response.icoicons/resize_corner.ico
+ sounds/pinkNoise.flac
diff --git a/Editor/FilterTable.cpp b/Editor/FilterTable.cpp
index 7e1065f..eace1f3 100644
--- a/Editor/FilterTable.cpp
+++ b/Editor/FilterTable.cpp
@@ -49,6 +49,7 @@
#include "guis/GraphicEQFilterGUIFactory.h"
#include "guis/ConvolutionFilterGUIFactory.h"
#include "guis/VSTPluginFilterGUIFactory.h"
+#include "guis/LoudnessCorrectionFilterGUIFactory.h"
#include "Editor/helpers/DPIHelper.h"
#include "helpers/StringHelper.h"
#include "helpers/LogHelper.h"
@@ -81,6 +82,7 @@ FilterTable::FilterTable(MainWindow* mainWindow, QWidget* parent)
factories.append(new GraphicEQFilterGUIFactory);
factories.append(new ConvolutionFilterGUIFactory);
factories.append(new VSTPluginFilterGUIFactory);
+ factories.append(new LoudnessCorrectionFilterGUIFactory);
QApplication::instance()->installEventFilter(this);
}
@@ -594,6 +596,12 @@ void FilterTable::setScrollOffsets(int x, int y)
presetScrollY = y;
}
+void FilterTable::updateAnalysis()
+{
+ if (isVisible())
+ mainWindow->startAnalysis();
+}
+
void FilterTable::mousePressEvent(QMouseEvent* event)
{
if (event->buttons() & Qt::LeftButton)
diff --git a/Editor/FilterTable.h b/Editor/FilterTable.h
index d214ce6..e130c99 100644
--- a/Editor/FilterTable.h
+++ b/Editor/FilterTable.h
@@ -93,6 +93,8 @@ public:
void savePreferences();
void setScrollOffsets(int x, int y);
+ void updateAnalysis();
+
signals:
void linesChanged();
diff --git a/Editor/MainWindow.h b/Editor/MainWindow.h
index f93b9fc..75d7ba7 100644
--- a/Editor/MainWindow.h
+++ b/Editor/MainWindow.h
@@ -52,6 +52,7 @@ public:
void save(FilterTable* filterTable, QString path);
bool isEmpty();
bool shouldRestart();
+ void startAnalysis();
protected:
void closeEvent(QCloseEvent* event) override;
@@ -93,7 +94,6 @@ private:
FilterTable* addTab(QString title, QString tooltip, QString configPath, QList lines);
void getDeviceAndChannelMask(std::shared_ptr* selectedDevice, int* channelMask);
bool askForClose(int tabIndex);
- void startAnalysis();
void loadPreferences();
void savePreferences();
void updateRecentFiles();
diff --git a/Editor/guis/LoudnessCorrectionFilterGUI.cpp b/Editor/guis/LoudnessCorrectionFilterGUI.cpp
new file mode 100644
index 0000000..90fc7bd
--- /dev/null
+++ b/Editor/guis/LoudnessCorrectionFilterGUI.cpp
@@ -0,0 +1,110 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Jonas Thedering
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "Editor/helpers/DPIHelper.h"
+#include "LoudnessCorrectionFilterGUIDialog.h"
+#include "LoudnessCorrectionFilterGUI.h"
+#include "ui_LoudnessCorrectionFilterGUI.h"
+
+LoudnessCorrectionFilterGUI::LoudnessCorrectionFilterGUI(float refLevel, float refOffset, float att)
+ : IFilterGUI(),
+ ui(new Ui::LoudnessCorrectionFilterGUI)
+{
+ ui->setupUi(this);
+
+ ui->refLevelDial->setFixedSize(DPIHelper::scale(QSize(100, 66)));
+ ui->refOffsetDial->setFixedSize(DPIHelper::scale(QSize(100, 66)));
+ ui->attDial->setFixedSize(DPIHelper::scale(QSize(100, 66)));
+
+ ui->refLevelSpinBox->setValue((int)refLevel);
+ ui->refOffsetSpinBox->setValue((int)refOffset);
+ ui->attSpinBox->setValue(att);
+
+ connect(&timer, SIGNAL(timeout()), this, SLOT(updateVolume()));
+ timer.start(10);
+}
+
+LoudnessCorrectionFilterGUI::~LoudnessCorrectionFilterGUI()
+{
+ delete ui;
+}
+
+void LoudnessCorrectionFilterGUI::store(QString& command, QString& parameters)
+{
+ command = "LoudnessCorrection";
+ parameters = QString("State %0 ReferenceLevel %1 ReferenceOffset %2 Attenuation ").arg(state ? 1 : 0).arg(ui->refLevelSpinBox->value()).arg(ui->refOffsetSpinBox->value());
+ double att = ui->attSpinBox->value();
+ if (att == 0.0 || att == 1.0)
+ parameters += QString("%0").arg(att, 0, 'f', 1);
+ else
+ parameters += QString("%0").arg(att);
+}
+
+void LoudnessCorrectionFilterGUI::on_refLevelSpinBox_valueChanged(int value)
+{
+ emit updateModel();
+}
+
+void LoudnessCorrectionFilterGUI::on_refOffsetSpinBox_valueChanged(int value)
+{
+ emit updateModel();
+}
+
+void LoudnessCorrectionFilterGUI::on_attDial_valueChanged(int value)
+{
+ ui->attSpinBox->setValue(value / 100.0);
+}
+
+void LoudnessCorrectionFilterGUI::on_attSpinBox_valueChanged(double value)
+{
+ bool previousValue = ui->attDial->blockSignals(true);
+ ui->attDial->setValue(round(value * 100.0));
+ ui->attDial->blockSignals(previousValue);
+
+ emit updateModel();
+}
+
+void LoudnessCorrectionFilterGUI::on_calibrateButton_clicked()
+{
+ state = false;
+ emit updateModel();
+
+ LoudnessCorrectionFilterGUIDialog dialog;
+ if (dialog.exec() == QDialog::Accepted)
+ {
+ updateVolume();
+ double refLevel = 75.0 - dialog.getMeasuredLevel() + lastVolume;
+ ui->refLevelSpinBox->setValue(refLevel);
+ }
+
+ state = true;
+ emit updateModel();
+}
+
+void LoudnessCorrectionFilterGUI::updateVolume()
+{
+ float volume;
+ HRESULT res = volumeController.getVolume(volume);
+
+ if (SUCCEEDED(res) && volume != lastVolume)
+ {
+ ui->volumeSpinBox->setValue(volume);
+ lastVolume = volume;
+ }
+}
diff --git a/Editor/guis/LoudnessCorrectionFilterGUI.h b/Editor/guis/LoudnessCorrectionFilterGUI.h
new file mode 100644
index 0000000..601467b
--- /dev/null
+++ b/Editor/guis/LoudnessCorrectionFilterGUI.h
@@ -0,0 +1,55 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Jonas Thedering
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#include
+
+#include "Editor/IFilterGUI.h"
+#include "filters/loudnessCorrection/VolumeController.h"
+
+namespace Ui {
+class LoudnessCorrectionFilterGUI;
+}
+
+class LoudnessCorrectionFilterGUI : public IFilterGUI
+{
+ Q_OBJECT
+
+public:
+ explicit LoudnessCorrectionFilterGUI(float refLevel, float refOffset, float att);
+ ~LoudnessCorrectionFilterGUI();
+
+ void store(QString& command, QString& parameters) override;
+
+private slots:
+ void on_refLevelSpinBox_valueChanged(int arg1);
+ void on_refOffsetSpinBox_valueChanged(int arg1);
+ void on_attDial_valueChanged(int value);
+ void on_attSpinBox_valueChanged(double arg1);
+ void on_calibrateButton_clicked();
+ void updateVolume();
+
+private:
+ Ui::LoudnessCorrectionFilterGUI* ui;
+ bool state = true;
+ QTimer timer;
+ VolumeController volumeController;
+ float lastVolume = -1;
+};
diff --git a/Editor/guis/LoudnessCorrectionFilterGUI.ui b/Editor/guis/LoudnessCorrectionFilterGUI.ui
new file mode 100644
index 0000000..2a83bab
--- /dev/null
+++ b/Editor/guis/LoudnessCorrectionFilterGUI.ui
@@ -0,0 +1,401 @@
+
+
+ LoudnessCorrectionFilterGUI
+
+
+
+ 0
+ 0
+ 1048
+ 66
+
+
+
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ false
+
+
+ QAbstractSpinBox::NoButtons
+
+
+ dB
+
+
+ -99.989999999999995
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 10
+ 20
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Reference level:
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+ 0
+ 20
+
+
+
+
+
+
+
+ Master volume:
+
+
+
+
+
+
+
+ 6
+ true
+
+
+
+ contributed by
+Alexander Walch
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 30
+ 20
+
+
+
+
+
+
+
+
+ 0
+ 66
+
+
+
+
+ 16777215
+ 66
+
+
+
+ -99
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Attenuation:
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 10
+ 20
+
+
+
+
+
+
+
+ dB
+
+
+ -999
+
+
+ 999
+
+
+
+
+
+
+
+ 0
+ 66
+
+
+
+
+ 16777215
+ 66
+
+
+
+ 0
+
+
+ 100
+
+
+ 100
+
+
+
+
+
+
+ 1.000000000000000
+
+
+ 0.010000000000000
+
+
+ 1.000000000000000
+
+
+
+
+
+
+ dB
+
+
+ -999
+
+
+ 999
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Reference offset:
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 10
+ 20
+
+
+
+
+
+
+
+
+ 0
+ 66
+
+
+
+
+ 16777215
+ 66
+
+
+
+ -99
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Loudness correction:
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+ Calibrate
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 30
+ 20
+
+
+
+
+
+
+
+
+
+ refLevelDial
+ valueChanged(int)
+ refLevelSpinBox
+ setValue(int)
+
+
+ 189
+ 43
+
+
+ 278
+ 64
+
+
+
+
+ refLevelSpinBox
+ valueChanged(int)
+ refLevelDial
+ setValue(int)
+
+
+ 278
+ 64
+
+
+ 189
+ 43
+
+
+
+
+ refOffsetDial
+ valueChanged(int)
+ refOffsetSpinBox
+ setValue(int)
+
+
+ 384
+ 43
+
+
+ 476
+ 64
+
+
+
+
+ refOffsetSpinBox
+ valueChanged(int)
+ refOffsetDial
+ setValue(int)
+
+
+ 476
+ 64
+
+
+ 384
+ 43
+
+
+
+
+
+ updateModel()
+
+
diff --git a/Editor/guis/LoudnessCorrectionFilterGUIDialog.cpp b/Editor/guis/LoudnessCorrectionFilterGUIDialog.cpp
new file mode 100644
index 0000000..2508a3b
--- /dev/null
+++ b/Editor/guis/LoudnessCorrectionFilterGUIDialog.cpp
@@ -0,0 +1,106 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Jonas Thedering
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+#include "Editor/helpers/QtSndfileHandle.h"
+
+#include "LoudnessCorrectionFilterGUIDialog.h"
+#include "ui_LoudnessCorrectionFilterGUIDialog.h"
+
+LoudnessCorrectionFilterGUIDialog::LoudnessCorrectionFilterGUIDialog(QWidget* parent)
+ : QDialog(parent),
+ ui(new Ui::LoudnessCorrectionFilterGUIDialog)
+{
+ ui->setupUi(this);
+}
+
+LoudnessCorrectionFilterGUIDialog::~LoudnessCorrectionFilterGUIDialog()
+{
+ on_stopButton_clicked();
+ delete ui;
+}
+
+int LoudnessCorrectionFilterGUIDialog::getMeasuredLevel()
+{
+ return ui->levelSpinBox->value();
+}
+
+void LoudnessCorrectionFilterGUIDialog::on_playButton_clicked()
+{
+ if (buffer.size() > 0)
+ on_stopButton_clicked();
+
+ QFile file(":/sounds/pinkNoise.flac");
+ file.open(QIODevice::ReadOnly);
+ QtSndfileHandle fileHandle(file, SFM_READ);
+
+ buffer.open(QIODevice::WriteOnly);
+ {
+ QtSndfileHandle bufferHandle(buffer, SFM_WRITE, SF_FORMAT_WAV | SF_FORMAT_PCM_24, 2, fileHandle.samplerate());
+
+ bool leftEnabled = ui->leftRadioButton->isChecked() || ui->bothRadioButton->isChecked();
+ bool rightEnabled = ui->rightRadioButton->isChecked() || ui->bothRadioButton->isChecked();
+
+ int buf[1024];
+ int buf2[2 * ARRAYSIZE(buf)];
+ int samplesRead;
+ while ((samplesRead = fileHandle.read(buf, ARRAYSIZE(buf))) > 0)
+ {
+ for (int i = 0; i < samplesRead; i++)
+ {
+ buf2[2 * i] = leftEnabled ? buf[i] : 0;
+ buf2[2 * i + 1] = rightEnabled ? buf[i] : 0;
+ }
+ bufferHandle.write(buf2, 2 * samplesRead);
+ }
+ }
+ buffer.close();
+
+ PlaySoundA(buffer.data().data(), NULL, SND_MEMORY | SND_ASYNC | SND_LOOP);
+}
+
+void LoudnessCorrectionFilterGUIDialog::on_stopButton_clicked()
+{
+ if (buffer.size() == 0)
+ return;
+
+ PlaySoundA(NULL, NULL, 0);
+ buffer.buffer().clear();
+}
+
+void LoudnessCorrectionFilterGUIDialog::on_leftRadioButton_toggled(bool checked)
+{
+ if (checked && buffer.size() > 0)
+ on_playButton_clicked();
+}
+
+void LoudnessCorrectionFilterGUIDialog::on_rightRadioButton_toggled(bool checked)
+{
+ if (checked && buffer.size() > 0)
+ on_playButton_clicked();
+}
+
+void LoudnessCorrectionFilterGUIDialog::on_bothRadioButton_toggled(bool checked)
+{
+ if (checked && buffer.size() > 0)
+ on_playButton_clicked();
+}
diff --git a/Editor/guis/LoudnessCorrectionFilterGUIDialog.h b/Editor/guis/LoudnessCorrectionFilterGUIDialog.h
new file mode 100644
index 0000000..8b71aea
--- /dev/null
+++ b/Editor/guis/LoudnessCorrectionFilterGUIDialog.h
@@ -0,0 +1,50 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Jonas Thedering
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#include
+#include
+
+namespace Ui {
+class LoudnessCorrectionFilterGUIDialog;
+}
+
+class LoudnessCorrectionFilterGUIDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit LoudnessCorrectionFilterGUIDialog(QWidget* parent = 0);
+ ~LoudnessCorrectionFilterGUIDialog();
+
+ int getMeasuredLevel();
+
+private slots:
+ void on_playButton_clicked();
+ void on_stopButton_clicked();
+
+ void on_leftRadioButton_toggled(bool checked);
+ void on_rightRadioButton_toggled(bool checked);
+ void on_bothRadioButton_toggled(bool checked);
+
+private:
+ Ui::LoudnessCorrectionFilterGUIDialog* ui;
+ QBuffer buffer;
+};
diff --git a/Editor/guis/LoudnessCorrectionFilterGUIDialog.ui b/Editor/guis/LoudnessCorrectionFilterGUIDialog.ui
new file mode 100644
index 0000000..cfcb92d
--- /dev/null
+++ b/Editor/guis/LoudnessCorrectionFilterGUIDialog.ui
@@ -0,0 +1,274 @@
+
+
+ LoudnessCorrectionFilterGUIDialog
+
+
+
+ 0
+ 0
+ 486
+ 495
+
+
+
+ Calibration
+
+
+
+
+
+ <html><head/><body><p>For a correct calibration, a sound level meter is required.<br/>These are the steps for calibration of a stereo system:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Disable loudness correction during measurement<br/>(done automatically while this dialog is open)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enable only one speaker (e.g. select left or right channel below)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Play pink noise at full application volume:</li></ul></body></html>
+
+
+ Qt::RichText
+
+
+ true
+
+
+
+
+
+
+ 0
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Channel
+
+
+
+
+
+ Left
+
+
+ true
+
+
+
+
+
+
+ Right
+
+
+
+
+
+
+ Both
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Stop
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ Play
+
+
+
+
+
+
+
+
+ <html><head/><body><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Adjust volume via Windows volume control or external volume control (amplifier, etc.) so that the sound level meter shows 75 dB at listening position. If that volume can not be reached, please adjust the following setting:</li></ul></body></html>
+
+
+ Qt::RichText
+
+
+ true
+
+
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+ 1
+ 20
+
+
+
+
+
+
+
+ Level at listening position:
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+ dB
+
+
+
+
+
+ 75
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+ 1
+ 20
+
+
+
+
+
+
+
+
+
+ <html><head/><body><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The reference level will be set to the Windows volume for which the level at the listening position is 75 dB.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">After calibration, volume should only be adjusted via Windows volume control</li></ul></body></html>
+
+
+ Qt::RichText
+
+
+ true
+
+
+
+
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Save
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ LoudnessCorrectionFilterGUIDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ LoudnessCorrectionFilterGUIDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/Editor/guis/LoudnessCorrectionFilterGUIFactory.cpp b/Editor/guis/LoudnessCorrectionFilterGUIFactory.cpp
new file mode 100644
index 0000000..3c2d1f8
--- /dev/null
+++ b/Editor/guis/LoudnessCorrectionFilterGUIFactory.cpp
@@ -0,0 +1,93 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Jonas Thedering
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "filters/loudnessCorrection/LoudnessCorrectionFilter.h"
+#include "LoudnessCorrectionFilterGUI.h"
+#include "LoudnessCorrectionFilterGUIFactory.h"
+
+LoudnessCorrectionFilterGUIFactory::LoudnessCorrectionFilterGUIFactory()
+{
+}
+
+LoudnessCorrectionFilterGUIFactory::~LoudnessCorrectionFilterGUIFactory()
+{
+ if (timer != NULL)
+ timer->stop();
+
+ if (volumeController != NULL)
+ {
+ delete volumeController;
+ volumeController = NULL;
+ }
+}
+
+void LoudnessCorrectionFilterGUIFactory::initialize(FilterTable* filterTable)
+{
+ this->filterTable = filterTable;
+}
+
+QList LoudnessCorrectionFilterGUIFactory::createFilterTemplates()
+{
+ QList list;
+ list.append(FilterTemplate(tr("Loudness correction"), "LoudnessCorrection: State 1 ReferenceLevel 0 ReferenceOffset 0 Attenuation 1.0", QStringList(tr("Advanced filters"))));
+ return list;
+}
+
+IFilterGUI* LoudnessCorrectionFilterGUIFactory::createFilterGUI(QString& command, QString& parameters)
+{
+ LoudnessCorrectionFilterGUI* result = NULL;
+
+ if (command == "LoudnessCorrection")
+ {
+ LoudnessCorrectionFilter::FilterParameters params;
+ if (!params.deSerialize(parameters.toStdWString()))
+ {
+ result = new LoudnessCorrectionFilterGUI(params.referenceLevel, params.referenceOffset, params.attenuation);
+
+ if (timer == NULL)
+ {
+ timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(checkVolume()));
+ timer->start(10);
+ }
+ }
+ }
+
+ return result;
+}
+
+void LoudnessCorrectionFilterGUIFactory::checkVolume()
+{
+ if (volumeController == NULL)
+ {
+ volumeController = new VolumeController();
+ volumeController->getVolume(lastVolume);
+ }
+ else
+ {
+ float volume;
+ HRESULT res = volumeController->getVolume(volume);
+
+ if (SUCCEEDED(res) && volume != lastVolume)
+ {
+ filterTable->updateAnalysis();
+ lastVolume = volume;
+ }
+ }
+}
diff --git a/Editor/guis/LoudnessCorrectionFilterGUIFactory.h b/Editor/guis/LoudnessCorrectionFilterGUIFactory.h
new file mode 100644
index 0000000..e664e5b
--- /dev/null
+++ b/Editor/guis/LoudnessCorrectionFilterGUIFactory.h
@@ -0,0 +1,47 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Jonas Thedering
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#include
+#include "Editor/IFilterGUIFactory.h"
+#include "Editor/FilterTable.h"
+#include "filters/loudnessCorrection/VolumeController.h"
+
+class LoudnessCorrectionFilterGUIFactory : public IFilterGUIFactory
+{
+ Q_OBJECT
+
+public:
+ explicit LoudnessCorrectionFilterGUIFactory();
+ ~LoudnessCorrectionFilterGUIFactory();
+
+ void initialize(FilterTable* filterTable) override;
+ QList createFilterTemplates() override;
+ IFilterGUI* createFilterGUI(QString& command, QString& parameters) override;
+
+private slots:
+ void checkVolume();
+
+private:
+ FilterTable* filterTable;
+ QTimer* timer = NULL;
+ VolumeController* volumeController = NULL;
+ float lastVolume = -1;
+};
diff --git a/Editor/helpers/QtSndfileHandle.cpp b/Editor/helpers/QtSndfileHandle.cpp
new file mode 100644
index 0000000..c3aabbc
--- /dev/null
+++ b/Editor/helpers/QtSndfileHandle.cpp
@@ -0,0 +1,66 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Jonas Thedering
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "QtSndfileHandle.h"
+
+sf_count_t getFileLenDevice(void* user_data)
+{
+ QIODevice* device = (QIODevice*)user_data;
+ return device->size();
+}
+
+sf_count_t seekDevice(sf_count_t offset, int whence, void* user_data)
+{
+ QIODevice* device = (QIODevice*)user_data;
+ qint64 pos;
+ if (whence == SF_SEEK_SET)
+ pos = 0;
+ else if (whence == SF_SEEK_CUR)
+ pos = device->pos();
+ else // whence == SF_SEEK_END
+ pos = device->size();
+ if (!device->seek(pos + offset))
+ return -1;
+ return device->pos();
+}
+
+sf_count_t readDevice(void* ptr, sf_count_t count, void* user_data)
+{
+ QIODevice* device = (QIODevice*)user_data;
+ return device->read((char*)ptr, count);
+}
+
+sf_count_t writeDevice(const void* ptr, sf_count_t count, void* user_data)
+{
+ QIODevice* device = (QIODevice*)user_data;
+ return device->write((const char*)ptr, count);
+}
+
+sf_count_t tellDevice(void* user_data)
+{
+ QIODevice* device = (QIODevice*)user_data;
+ return device->pos();
+}
+
+SF_VIRTUAL_IO g_deviceIo = {getFileLenDevice, seekDevice, readDevice, writeDevice, tellDevice};
+
+QtSndfileHandle::QtSndfileHandle(QIODevice& device, int mode, int format, int channels, int samplerate)
+ : SndfileHandle(g_deviceIo, &device, mode, format, channels, samplerate)
+{
+}
diff --git a/Editor/helpers/QtSndfileHandle.h b/Editor/helpers/QtSndfileHandle.h
new file mode 100644
index 0000000..15503f5
--- /dev/null
+++ b/Editor/helpers/QtSndfileHandle.h
@@ -0,0 +1,31 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Jonas Thedering
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
+#include
+#include
+
+class QtSndfileHandle : public SndfileHandle
+{
+public:
+ QtSndfileHandle(QIODevice& device, int mode = SFM_READ,
+ int format = 0, int channels = 0, int samplerate = 0);
+};
diff --git a/Editor/sounds/pinkNoise.flac b/Editor/sounds/pinkNoise.flac
new file mode 100644
index 0000000..81c8309
Binary files /dev/null and b/Editor/sounds/pinkNoise.flac differ
diff --git a/Editor/translations/Editor_de.qm b/Editor/translations/Editor_de.qm
index 44bc679..fd62ab3 100644
Binary files a/Editor/translations/Editor_de.qm and b/Editor/translations/Editor_de.qm differ
diff --git a/Editor/translations/Editor_de.ts b/Editor/translations/Editor_de.ts
index e0de7e0..99da11d 100644
--- a/Editor/translations/Editor_de.ts
+++ b/Editor/translations/Editor_de.ts
@@ -661,7 +661,7 @@ Wählen Sie eine andere Datei oder ändern Sie die Konfiguration des Geräts.
FilterTable
-
+ Add filterFilter hinzufügen
@@ -897,6 +897,130 @@ Change the file permissions or copy the file to the config directory.
Include (Konfigurationsdatei einbinden)
+
+ LoudnessCorrectionFilterGUI
+
+
+ Attenuation:
+ Abschwächung:
+
+
+
+ Reference offset:
+ Referenzversatz:
+
+
+
+ Reference level:
+ Referenzpegel:
+
+
+ dB
+ dB
+
+
+
+ Master volume:
+ Gesamtlautstärke:
+
+
+
+ contributed by
+Alexander Walch
+ beigetragen durch
+Alexander Walch
+
+
+
+ Loudness correction:
+ Lautheitskorrektur:
+
+
+
+ Calibrate
+ Kalibrieren
+
+
+
+ LoudnessCorrectionFilterGUIDialog
+
+
+ Calibration
+ Kalibrierung
+
+
+ <html><head/><body><p>For a correct calibration, a sound level meter is required.<br/>These are the steps for calibration of a stereo system:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Disable loudness equalization during measurement<br/>(done automatically while this dialog is open)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enable only one speaker (e.g. select left or right channel below)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Play pink noise at full application volume:</li></ul></body></html>
+ <html><head/><body><p>Für eine korrekte Kalibrierung wird ein Schallpegelmesser benötigt.<br/>Dies sind die Schritte für die Kalibrierung eines Stereosystems:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lautheitskorrektur während der Messung deaktivieren<br/>(geschieht automatisch, während dieser Dialog geöffnet ist)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nur einen Lautsprecher aktivieren (z.B. linken oder rechten Kanal unten wählen)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rosa Rauschen bei voller Anwendungslautstärke abspielen:</li></ul></body></html>
+
+
+
+ <html><head/><body><p>For a correct calibration, a sound level meter is required.<br/>These are the steps for calibration of a stereo system:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Disable loudness correction during measurement<br/>(done automatically while this dialog is open)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enable only one speaker (e.g. select left or right channel below)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Play pink noise at full application volume:</li></ul></body></html>
+ <html><head/><body><p>Für eine korrekte Kalibrierung wird ein Schallpegelmesser benötigt.<br/>Dies sind die Schritte für die Kalibrierung eines Stereosystems:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lautheitskorrektur während der Messung deaktivieren<br/>(geschieht automatisch, während dieser Dialog geöffnet ist)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nur einen Lautsprecher aktivieren (z.B. linken oder rechten Kanal unten wählen)</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Rosa Rauschen bei voller Anwendungslautstärke abspielen:</li></ul></body></html>
+
+
+
+ Channel
+ Kanal
+
+
+
+ Left
+ Links
+
+
+
+ Right
+ Rechts
+
+
+
+ Both
+ Beide
+
+
+
+ Stop
+ Stopp
+
+
+
+ Play
+ Abspielen
+
+
+
+ <html><head/><body><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Adjust volume via Windows volume control or external volume control (amplifier, etc.) so that the sound level meter shows 75 dB at listening position. If that volume can not be reached, please adjust the following setting:</li></ul></body></html>
+ <html><head/><body><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Lautstärke über die Windows-Lautstärkeregelung oder externe Lautstärkeregelung (Verstärker, usw.) anpassen, sodass der Schallpegelmesser am Hörplatz 75 dB anzeigt. Wenn diese Lautstärke nicht erreicht werden kann, bitte die folgende Einstellung anpassen:</li></ul></body></html>
+
+
+
+ Level at listening position:
+ Pegel am Hörplatz:
+
+
+
+ dB
+ dB
+
+
+
+ <html><head/><body><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The reference level will be set to the Windows volume for which the level at the listening position is 75 dB.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">After calibration, volume should only be adjusted via Windows volume control</li></ul></body></html>
+ <html><head/><body><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Der Referenzpegel wird auf die Windows-Lautstärke gesetzt, bei der der Pegel am Hörplatz 75 dB beträgt.</li><li style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nach der Kalibrierung sollte die Lautstärke nur noch über die Windows-Lautstärkeregelung verändert werden</li></ul></body></html>
+
+
+
+ LoudnessCorrectionFilterGUIFactory
+
+
+ Loudness correction
+ Lautheitskorrektur
+
+
+
+ Advanced filters
+ Fortgeschrittene Filter
+
+MainWindow
diff --git a/EqualizerAPO/EqualizerAPO.vcxproj b/EqualizerAPO/EqualizerAPO.vcxproj
index c825c76..a8e5532 100644
--- a/EqualizerAPO/EqualizerAPO.vcxproj
+++ b/EqualizerAPO/EqualizerAPO.vcxproj
@@ -182,8 +182,8 @@
+
-
diff --git a/EqualizerAPO/EqualizerAPO.vcxproj.filters b/EqualizerAPO/EqualizerAPO.vcxproj.filters
index a53bfdd..d5eeee4 100644
--- a/EqualizerAPO/EqualizerAPO.vcxproj.filters
+++ b/EqualizerAPO/EqualizerAPO.vcxproj.filters
@@ -25,7 +25,7 @@
-
+
diff --git a/FilterEngine.cpp b/FilterEngine.cpp
index 7bb7c58..0d32eb0 100644
--- a/FilterEngine.cpp
+++ b/FilterEngine.cpp
@@ -55,6 +55,7 @@
#include "filters/ConvolutionFilterFactory.h"
#include "filters/GraphicEQFilterFactory.h"
#include "filters/VSTPluginFilterFactory.h"
+#include "filters/loudnessCorrection/LoudnessCorrectionFilterFactory.h"
using namespace std;
using namespace mup;
@@ -91,6 +92,7 @@ FilterEngine::FilterEngine()
factories.push_back(new ConvolutionFilterFactory());
factories.push_back(new GraphicEQFilterFactory());
factories.push_back(new VSTPluginFilterFactory());
+ factories.push_back(new LoudnessCorrectionFilterFactory());
}
FilterEngine::~FilterEngine()
diff --git a/VoicemeeterClient/VoicemeeterClient.vcxproj.filters b/VoicemeeterClient/VoicemeeterClient.vcxproj.filters
index 30f52c3..3f7d590 100644
--- a/VoicemeeterClient/VoicemeeterClient.vcxproj.filters
+++ b/VoicemeeterClient/VoicemeeterClient.vcxproj.filters
@@ -19,12 +19,12 @@
-
-
- {eb32c27d-e4c2-4cad-a72d-b798d4514714}
+
+
+
\ No newline at end of file
diff --git a/filters/BiQuad.h b/filters/BiQuad.h
index a3a960e..e6a208a 100644
--- a/filters/BiQuad.h
+++ b/filters/BiQuad.h
@@ -65,6 +65,14 @@ public:
return result;
}
+ __forceinline
+ void setCoefficients(double ain[], const double& a0in)
+ {
+ for (int i = 0; i < 4; i++)
+ a[i] = ain[i];
+ a0 = a0in;
+ }
+
double gainAt(double freq, double srate);
private:
diff --git a/filters/loudnessCorrection/LoudnessCorrectionFilter.cpp b/filters/loudnessCorrection/LoudnessCorrectionFilter.cpp
new file mode 100644
index 0000000..22661fe
--- /dev/null
+++ b/filters/loudnessCorrection/LoudnessCorrectionFilter.cpp
@@ -0,0 +1,243 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Alexander Walch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "stdafx.h"
+#include "LoudnessCorrectionFilter.h"
+#include "helpers/MemoryHelper.h"
+
+#include "VolumeController.h"
+
+#ifndef _USE_MATH_DEFINES
+#define _USE_MATH_DEFINES
+#endif
+#include
+
+LoudnessCorrectionFilter::LoudnessCorrectionFilter(const FilterParameters& fParameters)
+{
+ _parameters = fParameters;
+ if (_parameters.attenuation > 1.0)
+ {
+ _parameters.attenuation = 1.0;
+ }
+ if (_parameters.attenuation < 0.0)
+ {
+ _parameters.attenuation = 0.0;
+ }
+ InitializeCriticalSection(&_parameterUpdateSection);
+}
+
+LoudnessCorrectionFilter::~LoudnessCorrectionFilter()
+{
+ if (_stopParameterUpdateThreadEvent)
+ {
+ SetEvent(_stopParameterUpdateThreadEvent);
+ }
+ WaitForSingleObject(_parameterUpdateThreadHandle, INFINITE);
+ DeleteCriticalSection(&_parameterUpdateSection);
+ CloseHandle(_stopParameterUpdateThreadEvent);
+ CloseHandle(_parameterUpdateThreadHandle);
+ CloseHandle(_parameterchangedEvent);
+}
+
+std::vector LoudnessCorrectionFilter::initialize(float sampleRate, unsigned maxFrameCount, std::vector channelNames)
+{
+ this->_channelCount = channelNames.size();
+ _lowShelfBiquads.resize(_channelCount);
+ _highShelfBiquads.resize(_channelCount);
+ _sampleRate = sampleRate;
+ _attFactor = 1.0;
+ for (unsigned i = 0; i < _channelCount; i++)
+ {
+ _lowShelfBiquads[i] = BiQuad(BiQuad::LOW_SHELF, 0, 75, _sampleRate, 1, false);
+ _highShelfBiquads[i] = BiQuad(BiQuad::HIGH_SHELF, 0, 10000, _sampleRate, 1, false);
+ }
+ _stopParameterUpdateThreadEvent = CreateEvent(NULL, true, false, NULL);
+ _parameterchangedEvent = CreateEvent(NULL, true, false, NULL);
+ _parameterUpdateThreadHandle = CreateThread(NULL, 0, ¶meterUpdateThread, this, 0, NULL);
+
+ return channelNames;
+}
+
+void LoudnessCorrectionFilter::getLShelfParamter(const float& volume, double& frequence, double& q, double& gain, double& preAmp)
+{
+ frequence = 75;
+ q = 0.52;
+ float volDiff = _parameters.referenceLevel - _parameters.referenceOffset - volume;
+ if (volDiff > 0)
+ {
+ // old: gain=volDiff*0.55*_parameters.attenuation;
+ gain = volDiff * 0.55 / (1 - 0.55) * _parameters.attenuation;
+ preAmp = -gain;
+ }
+ else if (volDiff < 0)
+ {
+ preAmp = 0.0;
+ gain = volDiff * 0.55 * exp(volDiff / 90.0) * _parameters.attenuation;
+ }
+ else
+ {
+ gain = 0;
+ }
+}
+void LoudnessCorrectionFilter::getHShelfParamter(const float& volume, double& frequence, double& q, double& gain)
+{
+ frequence = 10000;
+ q = 0.9;
+ float volDiff = _parameters.referenceLevel - _parameters.referenceOffset - volume;
+ if (volDiff > 0)
+ {
+ gain = volDiff * 0.225 * exp(-volDiff / 100.0) * _parameters.attenuation;
+ }
+ else if (volDiff < 0)
+ {
+ gain = volDiff * 0.175 * exp(volDiff / 80.0) * _parameters.attenuation;
+ }
+ else
+ {
+ gain = 0;
+ }
+}
+
+unsigned long __stdcall LoudnessCorrectionFilter::parameterUpdateThread(void* parameter)
+{
+ LoudnessCorrectionFilter* lCorrection = (LoudnessCorrectionFilter*)parameter;
+ VolumeController VolumeController;
+ float volOld(lCorrection->_parameters.referenceLevel);
+ float vol(lCorrection->_parameters.referenceLevel);
+ double freqLS, qLS, gainLS, preAmp;
+ double freqHS, qHS, gainHS;
+ HRESULT res;
+ while (WaitForSingleObject(lCorrection->_stopParameterUpdateThreadEvent, 0) == WAIT_TIMEOUT)
+ {
+ if (WaitForSingleObject(lCorrection->_parameterchangedEvent, 0) == WAIT_TIMEOUT)
+ {
+ res = VolumeController.getVolume(vol);
+ if (res == S_OK)
+ {
+ if (vol != volOld)
+ {
+ lCorrection->getLShelfParamter(vol, freqLS, qLS, gainLS, preAmp);
+ lCorrection->_attFactor = exp(preAmp / 6 * log(2));
+ lCorrection->getHShelfParamter(vol + (float)preAmp, freqHS, qHS, gainHS);
+ lCorrection->upDateBiquadCoefficients(freqHS, qHS, gainHS, true);
+ lCorrection->upDateBiquadCoefficients(freqLS, qLS, gainLS, false);
+ volOld = vol;
+
+ lCorrection->_neutralUpDate = std::max(std::abs(gainLS), std::abs(gainHS)) < 0.2 ? true : false;
+
+ SetEvent(lCorrection->_parameterchangedEvent);
+ }
+ }
+ }
+ Sleep(10);
+ // ==========================
+ }
+ return 0;
+}
+
+bool LoudnessCorrectionFilter::upDateNeutral()
+{
+ return _neutralUpDate;
+}
+
+#pragma AVRT_CODE_BEGIN
+void LoudnessCorrectionFilter::process(float** output, float** input, unsigned frameCount)
+{
+ if (_parameters.state == false)
+ {
+ for (unsigned int j = 0; j < frameCount; j++)
+ {
+ for (unsigned i = 0; i < _channelCount; i++)
+ {
+ output[i][j] = input[i][j];
+ }
+ }
+ output = input;
+ return;
+ }
+ if (WaitForSingleObject(_parameterchangedEvent, 0) == WAIT_OBJECT_0)
+ {
+ for (unsigned i = 0; i < _channelCount; i++)
+ {
+ _lowShelfBiquads[i].setCoefficients(_aLS, _a0LS);
+ _highShelfBiquads[i].setCoefficients(_aHS, _a0HS);
+ }
+ _neutral = upDateNeutral();
+ ResetEvent(_parameterchangedEvent);
+ }
+ for (unsigned i = 0; i < _channelCount; i++)
+ {
+ float* inputChannel = input[i];
+ float* outputChannel = output[i];
+ for (unsigned j = 0; j < frameCount; j++)
+ {
+ _tempResult = _lowShelfBiquads[i].process(inputChannel[j]);
+ _lowShelfBiquads[i].removeDenormals();
+ _tempResult *= _attFactor;
+ outputChannel[j] = (float)_highShelfBiquads[i].process(_tempResult);
+ _highShelfBiquads[i].removeDenormals();
+
+ // if there is nearly no loudness correction necessary => set output=input to achive best quality
+ if (_neutral)
+ {
+ outputChannel[j] = inputChannel[j];
+ }
+ }
+ }
+}
+
+void LoudnessCorrectionFilter::upDateBiquadCoefficients(const double& freq, const double& bandwidthOrQOrS, const double& dbGain, bool highshelf)
+{
+ double A;
+ A = pow(10, dbGain / 40);
+
+ double omega = 2 * M_PI * freq / _sampleRate;
+ double sn = sin(omega);
+ double cs = cos(omega);
+ double alpha;
+ double beta = -1;
+
+ alpha = sn / 2 * sqrt((A + 1 / A) * (1 / bandwidthOrQOrS - 1) + 2);
+ beta = 2 * sqrt(A) * alpha;
+
+ double a0;
+ TryEnterCriticalSection(&_parameterUpdateSection);
+ if (highshelf)
+ {
+ a0 = (A + 1) - (A - 1) * cs + beta;
+ _a0HS = (float)((A * ((A + 1) + (A - 1) * cs + beta)) / a0);
+ _aHS[0] = (float)((-2 * A * ((A - 1) + (A + 1) * cs)) / a0);
+ _aHS[1] = (float)((A * ((A + 1) + (A - 1) * cs - beta)) / a0);
+
+ _aHS[2] = (float)((2 * ((A - 1) - (A + 1) * cs)) / a0);
+ _aHS[3] = (float)(((A + 1) - (A - 1) * cs - beta) / a0);
+ }
+ else
+ {
+ a0 = (A + 1) + (A - 1) * cs + beta;
+ _a0LS = (float)((A * ((A + 1) - (A - 1) * cs + beta)) / a0);
+ _aLS[0] = (float)((2 * A * ((A - 1) - (A + 1) * cs)) / a0);
+ _aLS[1] = (float)((A * ((A + 1) - (A - 1) * cs - beta)) / a0);
+
+ _aLS[2] = (float)((-2 * ((A - 1) + (A + 1) * cs)) / a0);
+ _aLS[3] = (float)(((A + 1) + (A - 1) * cs - beta) / a0);
+ }
+ LeaveCriticalSection(&_parameterUpdateSection);
+}
+#pragma AVRT_CODE_END
diff --git a/filters/loudnessCorrection/LoudnessCorrectionFilter.h b/filters/loudnessCorrection/LoudnessCorrectionFilter.h
new file mode 100644
index 0000000..6429491
--- /dev/null
+++ b/filters/loudnessCorrection/LoudnessCorrectionFilter.h
@@ -0,0 +1,110 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Alexander Walch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#include "ParameterArchive.h"
+#include
+#include
+
+#include
+#include
+
+#pragma AVRT_VTABLES_BEGIN
+class LoudnessCorrectionFilter : public IFilter
+{
+public:
+ struct FilterParameters
+ {
+ bool state;
+ float referenceLevel;
+ float referenceOffset;
+ float attenuation;
+ std::vector serialize()
+ {
+ ParameterArchive archive; // possibility to get string from name of variable: std::string name=NAME(on);
+ archive.add(state, L"State");
+ archive.add(referenceLevel, L"ReferenceLevel");
+ archive.add(referenceOffset, L"ReferenceOffset");
+ archive.add(attenuation, L"Attenuation");
+ return archive.getSerializedParameters();
+ }
+ template bool deSerialize(const T& parameters)
+ {
+ ParameterArchive archive(parameters);
+ int error(0);
+ error += archive.get(state, std::wregex(L"\\s*State\\s+(0|1)"));
+ error += archive.get(referenceLevel, std::wregex(L"\\s*ReferenceLevel\\s+([-+0-9]+)"));
+ error += archive.get(referenceOffset, std::wregex(L"\\s*ReferenceOffset\\s+([-+0-9]+)"));
+ // attenuation is only an optional parameter
+ int errorAtt = archive.get(attenuation, std::wregex(L"\\s*Attenuation\\s+((1((\\.|,)0+)?)|(0((\\.|,)[0-9]+)?))"));
+ if (errorAtt > 0)
+ {
+ attenuation = 1.0;
+ }
+ return error == 0 ? false : true;
+ }
+ FilterParameters()
+ : _isInitialized(false) {};
+ template FilterParameters(T input)
+ {
+ _isInitialized = !deSerialize(input);
+ }
+ bool isInitialized()
+ {
+ return _isInitialized;
+ }
+private:
+ bool _isInitialized;
+ };
+
+ LoudnessCorrectionFilter(const FilterParameters& fParameters);
+ virtual ~LoudnessCorrectionFilter();
+ virtual bool getInPlace() {return true;}
+ virtual std::vector initialize(float sampleRate, unsigned maxFrameCount, std::vector channelNames);
+ virtual void process(float** output, float** input, unsigned frameCount);
+
+private:
+ void getLShelfParamter(const float& volume, double& frequence, double& q, double& gain, double& preAmp);
+ void getHShelfParamter(const float& volume, double& frequence, double& q, double& gain);
+ void upDateBiquadCoefficients(const double& freq, const double& bandwidthOrQOrS, const double& dbGain, bool highshelf);
+ bool upDateNeutral();
+
+ void* _parameterUpdateThreadHandle;
+ static unsigned long __stdcall parameterUpdateThread(void* parameter);
+ void* _stopParameterUpdateThreadEvent;
+ void* _parameterchangedEvent;
+ CRITICAL_SECTION _parameterUpdateSection;
+
+ FilterParameters _parameters;
+ size_t _channelCount;
+ float _sampleRate;
+ double _attFactor;
+ std::vector _lowShelfBiquads;
+ std::vector _highShelfBiquads;
+
+ bool _neutral;
+ bool _neutralUpDate;
+ double _tempResult;
+ double _aLS[4];
+ double _a0LS;
+ double _aHS[4];
+ double _a0HS;
+};
+#pragma AVRT_VTABLES_END
diff --git a/filters/loudnessCorrection/LoudnessCorrectionFilterFactory.cpp b/filters/loudnessCorrection/LoudnessCorrectionFilterFactory.cpp
new file mode 100644
index 0000000..1e2cea6
--- /dev/null
+++ b/filters/loudnessCorrection/LoudnessCorrectionFilterFactory.cpp
@@ -0,0 +1,54 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Alexander Walch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "stdafx.h"
+#define _USE_MATH_DEFINES
+#include
+#include
+#include
+
+#include "helpers/MemoryHelper.h"
+#include "helpers/StringHelper.h"
+#include "helpers/LogHelper.h"
+#include "LoudnessCorrectionFilter.h"
+#include "LoudnessCorrectionFilterFactory.h"
+
+using namespace std;
+
+LoudnessCorrectionFilterFactory::LoudnessCorrectionFilterFactory()
+{
+}
+
+vector LoudnessCorrectionFilterFactory::createFilter(const wstring& configPath, wstring& command, wstring& parameters)
+{
+ vector allFilter(0);
+
+ if (command == L"LoudnessCorrection")
+ {
+ LoudnessCorrectionFilter::FilterParameters filterParameters(parameters);
+ if (filterParameters.isInitialized())
+ {
+ TraceF(L"Adding loudness correction filter");
+ void* mem = MemoryHelper::alloc(sizeof(LoudnessCorrectionFilter));
+ allFilter.push_back(new(mem) LoudnessCorrectionFilter(filterParameters));
+ }
+ }
+
+ return allFilter;
+}
diff --git a/filters/loudnessCorrection/LoudnessCorrectionFilterFactory.h b/filters/loudnessCorrection/LoudnessCorrectionFilterFactory.h
new file mode 100644
index 0000000..ca68531
--- /dev/null
+++ b/filters/loudnessCorrection/LoudnessCorrectionFilterFactory.h
@@ -0,0 +1,33 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Alexander Walch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#include
+#include
+
+#include "IFilterFactory.h"
+#include "IFilter.h"
+
+class LoudnessCorrectionFilterFactory : public IFilterFactory
+{
+public:
+ LoudnessCorrectionFilterFactory();
+ virtual std::vector createFilter(const std::wstring& configPath, std::wstring& command, std::wstring& parameters);
+};
diff --git a/filters/loudnessCorrection/ParameterArchive.h b/filters/loudnessCorrection/ParameterArchive.h
new file mode 100644
index 0000000..a65211d
--- /dev/null
+++ b/filters/loudnessCorrection/ParameterArchive.h
@@ -0,0 +1,169 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Alexander Walch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#include
+#include
+#include
+#include
+
+template struct to_WString_type_traits
+{
+ static inline std::wstring cast_ToWString(type& input) {return std::wstring();}
+};
+
+template<> struct to_WString_type_traits
+{
+ static inline std::wstring cast_ToWString(const float& input) {return std::to_wstring((long double)input);}
+};
+
+template<> struct to_WString_type_traits
+{
+ static inline std::wstring cast_ToWString(const double& input) {return std::to_wstring((long double)input);}
+};
+
+template<> struct to_WString_type_traits
+{
+ static inline std::wstring cast_ToWString(const int& input) {return std::to_wstring((_Longlong)input);}
+};
+
+template<> struct to_WString_type_traits
+{
+ static inline std::wstring cast_ToWString(const bool& input) {return std::to_wstring((_Longlong)input);}
+};
+
+template<> struct to_WString_type_traits
+{
+ static inline std::wstring cast_ToWString(const std::string& input) {return StringHelper::toWString(input, CP_ACP);}
+};
+
+template<> struct to_WString_type_traits
+{
+ static inline std::wstring cast_ToWString(const std::wstring& input) {return input;}
+};
+
+template struct from_WString_type_traits
+{
+ static inline type cast_fromWString(const std::wstring& input) {return (type)wcstod(input.c_str(), NULL);}
+};
+
+template<> struct from_WString_type_traits
+{
+ static inline float cast_fromWString(const std::wstring& input) {return (float)wcstod(input.c_str(), NULL);}
+};
+
+template<> struct from_WString_type_traits
+{
+ static inline double cast_fromWString(const std::wstring& input) {return wcstod(input.c_str(), NULL);}
+};
+
+template<> struct from_WString_type_traits
+{
+ static inline int cast_fromWString(const std::wstring& input) {return (int)wcstol(input.c_str(), NULL, 10);}
+};
+
+template<> struct from_WString_type_traits
+{
+ static inline bool cast_fromWString(const std::wstring& input) {return wcstol(input.c_str(), NULL, 10) == 0 ? false : true;}
+};
+
+template<> struct from_WString_type_traits
+{
+ static inline std::wstring cast_fromWString(const std::wstring& input) {return input;}
+};
+
+template struct constructor_traits
+{
+ static inline std::wstring initFrom(type input) {return std::wstring();}
+};
+
+template<> struct constructor_traits
+{
+ static inline std::wstring initFrom(std::wstring input) {return input;}
+};
+
+template<> struct constructor_traits >
+{
+ static inline std::wstring initFrom(std::vector input)
+ {
+ input.push_back(0);
+ std::string tempParams(&input[0]);
+ return to_WString_type_traits::cast_ToWString(tempParams);
+ }
+};
+
+class ParameterArchive
+{
+public:
+ ParameterArchive()
+ : _serializedParamters(std::wstring())
+ {
+ }
+ template ParameterArchive(T input)
+ {
+ _serializedParamters = constructor_traits::initFrom(input);
+ }
+
+ std::vector getSerializedParameters()
+ {
+ size_t noBytes = _serializedParamters.length() * sizeof(std::wstring);
+ std::vector outputParameter(noBytes);
+ CopyMemory(&outputParameter[0], reinterpret_cast(&_serializedParamters[0]), noBytes);
+ return outputParameter;
+ }
+
+ template void add(const T& parameter, const U& name)
+ {
+ std::wstring nameStr = to_WString_type_traits::cast_ToWString(name);
+ if (!nameStr.empty())
+ {
+ _serializedParamters += nameStr;
+ _serializedParamters += L" ";
+ }
+ _serializedParamters += to_WString_type_traits::cast_ToWString(parameter);
+ _serializedParamters += L" ";
+ };
+
+ template int get(T& parameter, const std::wregex& searchArgument)
+ {
+ std::wsmatch match;
+ bool found = regex_search(_serializedParamters, match, searchArgument);
+ if (!found)
+ {
+ return 1;
+ }
+ std::vector splittedStrings = StringHelper::split(match.str(1), L' ');
+ if (splittedStrings.empty())
+ {
+ return 1;
+ }
+ parameter = from_WString_type_traits::cast_fromWString(splittedStrings.back());
+ return 0;
+ };
+
+ bool find(const std::wregex& searchArgument)
+ {
+ std::wsmatch match;
+ return regex_search(_serializedParamters, match, searchArgument);
+ }
+
+private:
+ std::wstring _serializedParamters;
+};
diff --git a/filters/loudnessCorrection/VolumeController.cpp b/filters/loudnessCorrection/VolumeController.cpp
new file mode 100644
index 0000000..78c1db0
--- /dev/null
+++ b/filters/loudnessCorrection/VolumeController.cpp
@@ -0,0 +1,55 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Alexander Walch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "stdafx.h"
+#include "VolumeController.h"
+#include
+
+VolumeController::VolumeController()
+{
+ HRESULT hr;
+ CoInitialize(NULL);
+ IMMDeviceEnumerator* deviceEnumerator = NULL;
+ hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID*)&deviceEnumerator);
+ IMMDevice* defaultDevice = NULL;
+
+ hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &defaultDevice);
+ deviceEnumerator->Release();
+ deviceEnumerator = NULL;
+
+ _endpointVolume = NULL;
+ hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (LPVOID*)&_endpointVolume);
+ defaultDevice->Release();
+ defaultDevice = NULL;
+ float inkrement;
+ _endpointVolume->GetVolumeRange(&_minVol, &_maxVol, &inkrement);
+}
+
+HRESULT VolumeController::getVolume(float& currentVolume)
+{
+ HRESULT res = _endpointVolume->GetMasterVolumeLevel(¤tVolume);
+ return res;
+}
+
+HRESULT VolumeController::setVolume(float volume)
+{
+ volume = min(volume, _maxVol);
+ volume = max(volume, _minVol);
+ return _endpointVolume->SetMasterVolumeLevel(volume, NULL);
+}
\ No newline at end of file
diff --git a/filters/loudnessCorrection/VolumeController.h b/filters/loudnessCorrection/VolumeController.h
new file mode 100644
index 0000000..6205984
--- /dev/null
+++ b/filters/loudnessCorrection/VolumeController.h
@@ -0,0 +1,36 @@
+/*
+ This file is part of Equalizer APO, a system-wide equalizer.
+ Copyright (C) 2017 Alexander Walch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+
+class VolumeController
+{
+public:
+ VolumeController();
+ HRESULT getVolume(float& currentVolume);
+ HRESULT setVolume(float volume);
+private:
+ IAudioEndpointVolume* _endpointVolume;
+ float _minVol;
+ float _maxVol;
+};