Added: Loudness correction filter by Alexander Walch that adjusts shelving filters based on the system volume. Also includes a GUI that allows calibration using a test sound.
This commit is contained in:
1 parent
534b63da5f
commit
ce857887af
33 files changed
+2146
-14
No files matched your search
@@ -13,12 +13,12 @@
|
||||
<Filter>helpers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\EqualizerAPO.licenseheader" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="helpers">
|
||||
<UniqueIdentifier>{8c70f87a-7d86-4826-bfa1-7a4c4ec5efec}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\EqualizerAPO.licenseheader" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -158,6 +158,10 @@
|
||||
<ClInclude Include="filters\IIRFilter.h" />
|
||||
<ClInclude Include="filters\IIRFilterFactory.h" />
|
||||
<ClInclude Include="filters\IncludeFilterFactory.h" />
|
||||
<ClInclude Include="filters\loudnessCorrection\LoudnessCorrectionFilterFactory.h" />
|
||||
<ClInclude Include="filters\loudnessCorrection\LoudnessCorrectionFilter.h" />
|
||||
<ClInclude Include="filters\loudnessCorrection\ParameterArchive.h" />
|
||||
<ClInclude Include="filters\loudnessCorrection\VolumeController.h" />
|
||||
<ClInclude Include="filters\PreampFilter.h" />
|
||||
<ClInclude Include="filters\PreampFilterFactory.h" />
|
||||
<ClInclude Include="filters\StageFilterFactory.h" />
|
||||
@@ -208,6 +212,9 @@
|
||||
<ClCompile Include="filters\IIRFilter.cpp" />
|
||||
<ClCompile Include="filters\IIRFilterFactory.cpp" />
|
||||
<ClCompile Include="filters\IncludeFilterFactory.cpp" />
|
||||
<ClCompile Include="filters\loudnessCorrection\LoudnessCorrectionFilterFactory.cpp" />
|
||||
<ClCompile Include="filters\loudnessCorrection\LoudnessCorrectionFilter.cpp" />
|
||||
<ClCompile Include="filters\loudnessCorrection\VolumeController.cpp" />
|
||||
<ClCompile Include="filters\PreampFilter.cpp" />
|
||||
<ClCompile Include="filters\PreampFilterFactory.cpp" />
|
||||
<ClCompile Include="filters\StageFilterFactory.cpp" />
|
||||
@@ -234,6 +241,9 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="EqualizerAPO.licenseheader" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
||||
@@ -129,6 +129,18 @@
|
||||
<ClInclude Include="FilterEngine.h" />
|
||||
<ClInclude Include="IFilter.h" />
|
||||
<ClInclude Include="IFilterFactory.h" />
|
||||
<ClInclude Include="filters\loudnessCorrection\ParameterArchive.h">
|
||||
<Filter>filters\loudnessCorrection</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="filters\loudnessCorrection\VolumeController.h">
|
||||
<Filter>filters\loudnessCorrection</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="filters\loudnessCorrection\LoudnessCorrectionFilterFactory.h">
|
||||
<Filter>filters\loudnessCorrection</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="filters\loudnessCorrection\LoudnessCorrectionFilter.h">
|
||||
<Filter>filters\loudnessCorrection</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
@@ -246,6 +258,15 @@
|
||||
<ClCompile Include="FilterConfiguration.cpp" />
|
||||
<ClCompile Include="FilterEngine.cpp" />
|
||||
<ClCompile Include="IFilter.cpp" />
|
||||
<ClCompile Include="filters\loudnessCorrection\VolumeController.cpp">
|
||||
<Filter>filters\loudnessCorrection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="filters\loudnessCorrection\LoudnessCorrectionFilterFactory.cpp">
|
||||
<Filter>filters\loudnessCorrection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="filters\loudnessCorrection\LoudnessCorrectionFilter.cpp">
|
||||
<Filter>filters\loudnessCorrection</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="filters">
|
||||
@@ -260,5 +281,11 @@
|
||||
<Filter Include="parser">
|
||||
<UniqueIdentifier>{4a6738bc-7359-4b18-bdb4-1f443f41e528}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="filters\loudnessCorrection">
|
||||
<UniqueIdentifier>{c473f978-6002-42aa-adf5-3b5f10868d2d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="EqualizerAPO.licenseheader" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+21
-4
@@ -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
|
||||
|
||||
@@ -23,5 +23,6 @@
|
||||
<file>icons/normalize_response.ico</file>
|
||||
<file>icons/reset_response.ico</file>
|
||||
<file>icons/resize_corner.ico</file>
|
||||
<file>sounds/pinkNoise.flac</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -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)
|
||||
|
||||
@@ -93,6 +93,8 @@ public:
|
||||
void savePreferences();
|
||||
void setScrollOffsets(int x, int y);
|
||||
|
||||
void updateAnalysis();
|
||||
|
||||
signals:
|
||||
void linesChanged();
|
||||
|
||||
|
||||
+1
-1
@@ -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<QString> lines);
|
||||
void getDeviceAndChannelMask(std::shared_ptr<AbstractAPOInfo>* selectedDevice, int* channelMask);
|
||||
bool askForClose(int tabIndex);
|
||||
void startAnalysis();
|
||||
void loadPreferences();
|
||||
void savePreferences();
|
||||
void updateRecentFiles();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 <QTimer>
|
||||
|
||||
#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;
|
||||
};
|
||||
@@ -0,0 +1,401 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LoudnessCorrectionFilterGUI</class>
|
||||
<widget class="QWidget" name="LoudnessCorrectionFilterGUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1048</width>
|
||||
<height>66</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0,0,0,0,0,0,0,0,0,0,0,0">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="13">
|
||||
<widget class="QDoubleSpinBox" name="volumeSpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string notr="true"> dB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-99.989999999999995</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="7">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="refLevelLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reference level:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="14">
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="13">
|
||||
<widget class="QLabel" name="volumeLabel">
|
||||
<property name="text">
|
||||
<string>Master volume:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>6</pointsize>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>contributed by
|
||||
Alexander Walch</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="10">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="5" rowspan="2">
|
||||
<widget class="QDial" name="refOffsetDial">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>66</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>66</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-99</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="9">
|
||||
<widget class="QLabel" name="attLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Attenuation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QSpinBox" name="refLevelSpinBox">
|
||||
<property name="suffix">
|
||||
<string notr="true"> dB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-999</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="8" rowspan="2">
|
||||
<widget class="QDial" name="attDial">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>66</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>66</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="9">
|
||||
<widget class="QDoubleSpinBox" name="attSpinBox">
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="6">
|
||||
<widget class="QSpinBox" name="refOffsetSpinBox">
|
||||
<property name="suffix">
|
||||
<string notr="true"> dB</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-999</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QLabel" name="refOffsetLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reference offset:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="2">
|
||||
<widget class="QDial" name="refLevelDial">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>66</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>66</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-99</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Loudness correction:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="11" rowspan="2">
|
||||
<widget class="QPushButton" name="calibrateButton">
|
||||
<property name="text">
|
||||
<string>Calibrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="12">
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>refLevelDial</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>refLevelSpinBox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>189</x>
|
||||
<y>43</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>278</x>
|
||||
<y>64</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>refLevelSpinBox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>refLevelDial</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>278</x>
|
||||
<y>64</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>189</x>
|
||||
<y>43</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>refOffsetDial</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>refOffsetSpinBox</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>384</x>
|
||||
<y>43</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>476</x>
|
||||
<y>64</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>refOffsetSpinBox</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>refOffsetDial</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>476</x>
|
||||
<y>64</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>384</x>
|
||||
<y>43</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<signal>updateModel()</signal>
|
||||
</slots>
|
||||
</ui>
|
||||
@@ -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 <QFile>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#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();
|
||||
}
|
||||
@@ -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 <QDialog>
|
||||
#include <QBuffer>
|
||||
|
||||
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;
|
||||
};
|
||||
@@ -0,0 +1,274 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LoudnessCorrectionFilterGUIDialog</class>
|
||||
<widget class="QDialog" name="LoudnessCorrectionFilterGUIDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>486</width>
|
||||
<height>495</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Calibration</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="channelGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Channel</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="leftRadioButton">
|
||||
<property name="text">
|
||||
<string>Left</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rightRadioButton">
|
||||
<property name="text">
|
||||
<string>Right</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="bothRadioButton">
|
||||
<property name="text">
|
||||
<string>Both</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="4">
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="stopButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="playButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Play</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label2">
|
||||
<property name="text">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="levelLabel">
|
||||
<property name="text">
|
||||
<string>Level at listening position:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="levelSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> dB</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>75</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label3">
|
||||
<property name="text">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>LoudnessCorrectionFilterGUIDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>LoudnessCorrectionFilterGUIDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -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<FilterTemplate> LoudnessCorrectionFilterGUIFactory::createFilterTemplates()
|
||||
{
|
||||
QList<FilterTemplate> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <QTimer>
|
||||
#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<FilterTemplate> 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;
|
||||
};
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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 <sndfile.hh>
|
||||
#include <QIODevice>
|
||||
|
||||
class QtSndfileHandle : public SndfileHandle
|
||||
{
|
||||
public:
|
||||
QtSndfileHandle(QIODevice& device, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0);
|
||||
};
|
||||
Binary file not shown.
Binary file not shown.
@@ -661,7 +661,7 @@ Wählen Sie eine andere Datei oder ändern Sie die Konfiguration des Geräts.</t
|
||||
<context>
|
||||
<name>FilterTable</name>
|
||||
<message>
|
||||
<location filename="../FilterTable.cpp" line="214"/>
|
||||
<location filename="../FilterTable.cpp" line="216"/>
|
||||
<source>Add filter</source>
|
||||
<translation>Filter hinzufügen</translation>
|
||||
</message>
|
||||
@@ -897,6 +897,130 @@ Change the file permissions or copy the file to the config directory.</source>
|
||||
<translation>Include (Konfigurationsdatei einbinden)</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>LoudnessCorrectionFilterGUI</name>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUI.ui" line="158"/>
|
||||
<source>Attenuation:</source>
|
||||
<translation>Abschwächung:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUI.ui" line="251"/>
|
||||
<source>Reference offset:</source>
|
||||
<translation>Referenzversatz:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUI.ui" line="73"/>
|
||||
<source>Reference level:</source>
|
||||
<translation>Referenzpegel:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source> dB</source>
|
||||
<translation type="obsolete"> dB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUI.ui" line="93"/>
|
||||
<source>Master volume:</source>
|
||||
<translation>Gesamtlautstärke:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUI.ui" line="106"/>
|
||||
<source>contributed by
|
||||
Alexander Walch</source>
|
||||
<translation>beigetragen durch
|
||||
Alexander Walch</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUI.ui" line="299"/>
|
||||
<source>Loudness correction:</source>
|
||||
<translation>Lautheitskorrektur:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUI.ui" line="309"/>
|
||||
<source>Calibrate</source>
|
||||
<translation>Kalibrieren</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>LoudnessCorrectionFilterGUIDialog</name>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="14"/>
|
||||
<source>Calibration</source>
|
||||
<translation>Kalibrierung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source><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></source>
|
||||
<translation type="vanished"><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></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="20"/>
|
||||
<source><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></source>
|
||||
<translation><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></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="44"/>
|
||||
<source>Channel</source>
|
||||
<translation>Kanal</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="50"/>
|
||||
<source>Left</source>
|
||||
<translation>Links</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="60"/>
|
||||
<source>Right</source>
|
||||
<translation>Rechts</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="67"/>
|
||||
<source>Both</source>
|
||||
<translation>Beide</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="100"/>
|
||||
<source>Stop</source>
|
||||
<translation>Stopp</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="126"/>
|
||||
<source>Play</source>
|
||||
<translation>Abspielen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="135"/>
|
||||
<source><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></source>
|
||||
<translation><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></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="163"/>
|
||||
<source>Level at listening position:</source>
|
||||
<translation>Pegel am Hörplatz:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="176"/>
|
||||
<source> dB</source>
|
||||
<translation> dB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIDialog.ui" line="204"/>
|
||||
<source><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></source>
|
||||
<translation><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></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>LoudnessCorrectionFilterGUIFactory</name>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIFactory.cpp" line="48"/>
|
||||
<source>Loudness correction</source>
|
||||
<translation>Lautheitskorrektur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../guis/LoudnessCorrectionFilterGUIFactory.cpp" line="48"/>
|
||||
<source>Advanced filters</source>
|
||||
<translation>Fortgeschrittene Filter</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
|
||||
@@ -182,8 +182,8 @@
|
||||
<ClCompile Include="EqualizerAPO.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\EqualizerAPO.licenseheader" />
|
||||
<None Include="EqualizerAPO.def" />
|
||||
<None Include="EqualizerAPO.licenseheader" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EqualizerAPO.rc">
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="EqualizerAPO.def" />
|
||||
<None Include="EqualizerAPO.licenseheader" />
|
||||
<None Include="..\EqualizerAPO.licenseheader" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="helpers">
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="VoicemeeterClient.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\EqualizerAPO.licenseheader" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="helpers">
|
||||
<UniqueIdentifier>{eb32c27d-e4c2-4cad-a72d-b798d4514714}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\EqualizerAPO.licenseheader" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -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:
|
||||
|
||||
@@ -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 <math.h>
|
||||
|
||||
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<std::wstring> LoudnessCorrectionFilter::initialize(float sampleRate, unsigned maxFrameCount, std::vector<std::wstring> 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<double>(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
|
||||
@@ -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 <IFilter.h>
|
||||
#include <filters/BiQuad.h>
|
||||
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
|
||||
#pragma AVRT_VTABLES_BEGIN
|
||||
class LoudnessCorrectionFilter : public IFilter
|
||||
{
|
||||
public:
|
||||
struct FilterParameters
|
||||
{
|
||||
bool state;
|
||||
float referenceLevel;
|
||||
float referenceOffset;
|
||||
float attenuation;
|
||||
std::vector<char> 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<typename T> 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<typename T> FilterParameters(T input)
|
||||
{
|
||||
_isInitialized = !deSerialize<T>(input);
|
||||
}
|
||||
bool isInitialized()
|
||||
{
|
||||
return _isInitialized;
|
||||
}
|
||||
private:
|
||||
bool _isInitialized;
|
||||
};
|
||||
|
||||
LoudnessCorrectionFilter(const FilterParameters& fParameters);
|
||||
virtual ~LoudnessCorrectionFilter();
|
||||
virtual bool getInPlace() {return true;}
|
||||
virtual std::vector<std::wstring> initialize(float sampleRate, unsigned maxFrameCount, std::vector<std::wstring> 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<BiQuad> _lowShelfBiquads;
|
||||
std::vector<BiQuad> _highShelfBiquads;
|
||||
|
||||
bool _neutral;
|
||||
bool _neutralUpDate;
|
||||
double _tempResult;
|
||||
double _aLS[4];
|
||||
double _a0LS;
|
||||
double _aHS[4];
|
||||
double _a0HS;
|
||||
};
|
||||
#pragma AVRT_VTABLES_END
|
||||
@@ -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 <cmath>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
|
||||
#include "helpers/MemoryHelper.h"
|
||||
#include "helpers/StringHelper.h"
|
||||
#include "helpers/LogHelper.h"
|
||||
#include "LoudnessCorrectionFilter.h"
|
||||
#include "LoudnessCorrectionFilterFactory.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
LoudnessCorrectionFilterFactory::LoudnessCorrectionFilterFactory()
|
||||
{
|
||||
}
|
||||
|
||||
vector<IFilter*> LoudnessCorrectionFilterFactory::createFilter(const wstring& configPath, wstring& command, wstring& parameters)
|
||||
{
|
||||
vector<IFilter*> 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;
|
||||
}
|
||||
@@ -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 <string>
|
||||
#include <hash_map>
|
||||
|
||||
#include "IFilterFactory.h"
|
||||
#include "IFilter.h"
|
||||
|
||||
class LoudnessCorrectionFilterFactory : public IFilterFactory
|
||||
{
|
||||
public:
|
||||
LoudnessCorrectionFilterFactory();
|
||||
virtual std::vector<IFilter*> createFilter(const std::wstring& configPath, std::wstring& command, std::wstring& parameters);
|
||||
};
|
||||
@@ -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 <regex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <helpers/StringHelper.h>
|
||||
|
||||
template<typename type> struct to_WString_type_traits
|
||||
{
|
||||
static inline std::wstring cast_ToWString(type& input) {return std::wstring();}
|
||||
};
|
||||
|
||||
template<> struct to_WString_type_traits<float>
|
||||
{
|
||||
static inline std::wstring cast_ToWString(const float& input) {return std::to_wstring((long double)input);}
|
||||
};
|
||||
|
||||
template<> struct to_WString_type_traits<double>
|
||||
{
|
||||
static inline std::wstring cast_ToWString(const double& input) {return std::to_wstring((long double)input);}
|
||||
};
|
||||
|
||||
template<> struct to_WString_type_traits<int>
|
||||
{
|
||||
static inline std::wstring cast_ToWString(const int& input) {return std::to_wstring((_Longlong)input);}
|
||||
};
|
||||
|
||||
template<> struct to_WString_type_traits<bool>
|
||||
{
|
||||
static inline std::wstring cast_ToWString(const bool& input) {return std::to_wstring((_Longlong)input);}
|
||||
};
|
||||
|
||||
template<> struct to_WString_type_traits<std::string>
|
||||
{
|
||||
static inline std::wstring cast_ToWString(const std::string& input) {return StringHelper::toWString(input, CP_ACP);}
|
||||
};
|
||||
|
||||
template<> struct to_WString_type_traits<std::wstring>
|
||||
{
|
||||
static inline std::wstring cast_ToWString(const std::wstring& input) {return input;}
|
||||
};
|
||||
|
||||
template<typename type> 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<float>
|
||||
{
|
||||
static inline float cast_fromWString(const std::wstring& input) {return (float)wcstod(input.c_str(), NULL);}
|
||||
};
|
||||
|
||||
template<> struct from_WString_type_traits<double>
|
||||
{
|
||||
static inline double cast_fromWString(const std::wstring& input) {return wcstod(input.c_str(), NULL);}
|
||||
};
|
||||
|
||||
template<> struct from_WString_type_traits<int>
|
||||
{
|
||||
static inline int cast_fromWString(const std::wstring& input) {return (int)wcstol(input.c_str(), NULL, 10);}
|
||||
};
|
||||
|
||||
template<> struct from_WString_type_traits<bool>
|
||||
{
|
||||
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<std::wstring>
|
||||
{
|
||||
static inline std::wstring cast_fromWString(const std::wstring& input) {return input;}
|
||||
};
|
||||
|
||||
template<typename type> struct constructor_traits
|
||||
{
|
||||
static inline std::wstring initFrom(type input) {return std::wstring();}
|
||||
};
|
||||
|
||||
template<> struct constructor_traits<std::wstring>
|
||||
{
|
||||
static inline std::wstring initFrom(std::wstring input) {return input;}
|
||||
};
|
||||
|
||||
template<> struct constructor_traits<std::vector<char> >
|
||||
{
|
||||
static inline std::wstring initFrom(std::vector<char> input)
|
||||
{
|
||||
input.push_back(0);
|
||||
std::string tempParams(&input[0]);
|
||||
return to_WString_type_traits<std::string>::cast_ToWString(tempParams);
|
||||
}
|
||||
};
|
||||
|
||||
class ParameterArchive
|
||||
{
|
||||
public:
|
||||
ParameterArchive()
|
||||
: _serializedParamters(std::wstring())
|
||||
{
|
||||
}
|
||||
template<typename T> ParameterArchive(T input)
|
||||
{
|
||||
_serializedParamters = constructor_traits<T>::initFrom(input);
|
||||
}
|
||||
|
||||
std::vector<char> getSerializedParameters()
|
||||
{
|
||||
size_t noBytes = _serializedParamters.length() * sizeof(std::wstring);
|
||||
std::vector<char> outputParameter(noBytes);
|
||||
CopyMemory(&outputParameter[0], reinterpret_cast<char*>(&_serializedParamters[0]), noBytes);
|
||||
return outputParameter;
|
||||
}
|
||||
|
||||
template<typename T, typename U> void add(const T& parameter, const U& name)
|
||||
{
|
||||
std::wstring nameStr = to_WString_type_traits<U>::cast_ToWString(name);
|
||||
if (!nameStr.empty())
|
||||
{
|
||||
_serializedParamters += nameStr;
|
||||
_serializedParamters += L" ";
|
||||
}
|
||||
_serializedParamters += to_WString_type_traits<T>::cast_ToWString(parameter);
|
||||
_serializedParamters += L" ";
|
||||
};
|
||||
|
||||
template<typename T> int get(T& parameter, const std::wregex& searchArgument)
|
||||
{
|
||||
std::wsmatch match;
|
||||
bool found = regex_search(_serializedParamters, match, searchArgument);
|
||||
if (!found)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
std::vector<std::wstring> splittedStrings = StringHelper::split(match.str(1), L' ');
|
||||
if (splittedStrings.empty())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
parameter = from_WString_type_traits<T>::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;
|
||||
};
|
||||
@@ -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 <mmdeviceapi.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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 <windows.h>
|
||||
#include <EndpointVolume.h>
|
||||
|
||||
class VolumeController
|
||||
{
|
||||
public:
|
||||
VolumeController();
|
||||
HRESULT getVolume(float& currentVolume);
|
||||
HRESULT setVolume(float volume);
|
||||
private:
|
||||
IAudioEndpointVolume* _endpointVolume;
|
||||
float _minVol;
|
||||
float _maxVol;
|
||||
};
|
||||
Reference in new issue
Block a user