From 58ded8c2e411a79f5647dd9bbc6036a2befadb7d Mon Sep 17 00:00:00 2001 From: lordmulder Date: Tue, 25 Jan 2011 23:12:56 +0100 Subject: [PATCH] Added a normalization filter, based on SoX. --- LameXP.vcproj | 8 +++ gui/MainWindow.ui | 8 ++- src/Dialog_Processing.cpp | 8 ++- src/Filter_Downmix.cpp | 2 +- src/Filter_Normalize.cpp | 112 ++++++++++++++++++++++++++++++++++ src/Filter_Normalize.h | 37 +++++++++++ src/Thread_Initialization.cpp | 6 +- src/Thread_Process.cpp | 20 ++++-- src/Thread_Process.h | 3 + 9 files changed, 190 insertions(+), 14 deletions(-) create mode 100644 src/Filter_Normalize.cpp create mode 100644 src/Filter_Normalize.h diff --git a/LameXP.vcproj b/LameXP.vcproj index 3c3eb2d0..b7b2b413 100644 --- a/LameXP.vcproj +++ b/LameXP.vcproj @@ -410,6 +410,10 @@ RelativePath=".\src\Filter_Downmix.cpp" > + + @@ -1122,6 +1126,10 @@ RelativePath=".\src\Filter_Downmix.h" > + + diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index c27dcc99..98941b0f 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -985,7 +985,7 @@ 0 0 - 602 + 604 520 @@ -1688,10 +1688,10 @@ - -12.000000000000000 + -32.000000000000000 - 0.000000000000000 + -0.500000000000000 0.500000000000000 @@ -2298,6 +2298,8 @@ + + diff --git a/src/Dialog_Processing.cpp b/src/Dialog_Processing.cpp index e5a46e89..12e32931 100644 --- a/src/Dialog_Processing.cpp +++ b/src/Dialog_Processing.cpp @@ -33,6 +33,7 @@ #include "Encoder_AAC.h" #include "Encoder_FLAC.h" #include "Encoder_Wave.h" +#include "Filter_Normalize.h" #include "WinSevenTaskbar.h" #include @@ -495,7 +496,12 @@ void ProcessingDialog::startNextJob(void) encoder, m_settings->prependRelativeSourcePath() ); - + + if(m_settings->normalizationFilterEnabled()) + { + thread->addFilter(new NormalizeFilter(m_settings->normalizationFilterMaxVolume())); + } + m_threadList.append(thread); m_allJobs.append(thread->getId()); diff --git a/src/Filter_Downmix.cpp b/src/Filter_Downmix.cpp index 5edf56ef..89023993 100644 --- a/src/Filter_Downmix.cpp +++ b/src/Filter_Downmix.cpp @@ -49,7 +49,7 @@ bool DownmixFilter::apply(const QString &sourceFile, const QString &outputFile, process.setWorkingDirectory(lamexp_temp_folder()); args << "-V3"; - args << "--norm" << "--temp" << "."; + args << "--guard" << "--temp" << "."; args << QDir::toNativeSeparators(sourceFile); args << "-c2"; args << QDir::toNativeSeparators(outputFile); diff --git a/src/Filter_Normalize.cpp b/src/Filter_Normalize.cpp new file mode 100644 index 00000000..ccc9a142 --- /dev/null +++ b/src/Filter_Normalize.cpp @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2011 LoRd_MuldeR +// +// 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. +// +// http://www.gnu.org/licenses/gpl-2.0.txt +/////////////////////////////////////////////////////////////////////////////// + +#include "Filter_Normalize.h" + +#include "Global.h" + +#include +#include +#include + +NormalizeFilter::NormalizeFilter(int peakVolume) +: + m_binary(lamexp_lookup_tool("sox.exe")) +{ + if(m_binary.isEmpty()) + { + throw "Error initializing SoX filter. Tool 'sox.exe' is not registred!"; + } + + m_peakVolume = min(-50, max(-3200, peakVolume)); +} + +NormalizeFilter::~NormalizeFilter(void) +{ +} + +bool NormalizeFilter::apply(const QString &sourceFile, const QString &outputFile, volatile bool *abortFlag) +{ + QProcess process; + QStringList args; + + process.setWorkingDirectory(lamexp_temp_folder()); + + args << "-V3"; + args << "--temp" << "."; + args << QDir::toNativeSeparators(sourceFile); + args << QDir::toNativeSeparators(outputFile); + args << "gain"; + args << "-n" << QString().sprintf("%.2f", static_cast(m_peakVolume) / 100.0); + + if(!startProcess(process, m_binary, args)) + { + return false; + } + + bool bTimeout = false; + bool bAborted = false; + + while(process.state() != QProcess::NotRunning) + { + if(*abortFlag) + { + process.kill(); + bAborted = true; + emit messageLogged("\nABORTED BY USER !!!"); + break; + } + process.waitForReadyRead(); + if(!process.bytesAvailable() && process.state() == QProcess::Running) + { + process.kill(); + qWarning("SoX process timed out <-- killing!"); + bTimeout = true; + break; + } + while(process.bytesAvailable() > 0) + { + QByteArray line = process.readLine(); + QString text = QString::fromUtf8(line.constData()).simplified(); + if(!text.isEmpty()) + { + emit messageLogged(text); + } + } + } + + process.waitForFinished(); + if(process.state() != QProcess::NotRunning) + { + process.kill(); + process.waitForFinished(-1); + } + + emit statusUpdated(100); + emit messageLogged(QString().sprintf("\nExited with code: 0x%04X", process.exitCode())); + + if(bTimeout || bAborted || process.exitStatus() != QProcess::NormalExit || QFileInfo(outputFile).size() == 0) + { + return false; + } + + return true; +} diff --git a/src/Filter_Normalize.h b/src/Filter_Normalize.h new file mode 100644 index 00000000..bb9f80b1 --- /dev/null +++ b/src/Filter_Normalize.h @@ -0,0 +1,37 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2011 LoRd_MuldeR +// +// 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. +// +// http://www.gnu.org/licenses/gpl-2.0.txt +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "Filter_Abstract.h" + +class NormalizeFilter : public AbstractFilter +{ +public: + NormalizeFilter(int peakVolume = -50); + ~NormalizeFilter(void); + + virtual bool apply(const QString &sourceFile, const QString &outputFile, volatile bool *abortFlag); + +private: + const QString m_binary; + int m_peakVolume; +}; diff --git a/src/Thread_Initialization.cpp b/src/Thread_Initialization.cpp index 0c9d403d..0ee56bf9 100644 --- a/src/Thread_Initialization.cpp +++ b/src/Thread_Initialization.cpp @@ -55,10 +55,10 @@ g_lamexp_tools[] = {"d837bf6ee4dab557d8b02d46c75a24e58980fffa", "gpgv.gpg", UINT_MAX}, {"143fc001a2f6c56fe1b9e6f8a2eb2b53b9e1e504", "lame.exe", 39910}, {"a4e929cfaa42fa2e61a3d0c6434c77a06d45aef3", "mac.exe", 406}, - {"61d584ffaf428e9afb0ed9bd32706a954af492b0", "mediainfo_i386.exe", 739}, - {"81fb728cbc6057906fa1b637738e6aefe5dccf54", "mediainfo_x64.exe", 739}, + {"ec235c6404caa31e7975e9bbf9ba59599258ae1d", "mediainfo_i386.exe", 741}, + {"72d7efdcafc2dee3b534f27ab6e01916d02ba470", "mediainfo_x64.exe", 741}, {"55c293a80475f7aeccf449ac9487a4626e5139cb", "mpcdec.exe", UINT_MAX}, - {"8bbf4a3fffe2ff143eb5ba2cf82ca16d676e865d", "mpg123.exe", UINT_MAX}, + {"6b6913a54cac08b22d5b468aaed83550fc9ae5b4", "mpg123.exe", 1131}, {"8dd7138714c3bcb39f5a3213413addba13d06f1e", "oggdec.exe", UINT_MAX}, {"ecd15abe103184aca96e406f5f1c82c6fb2e665d", "oggenc2_i386.exe", 287}, {"ffe0fbd73352396dc3752ac9d484dbfc754a226d", "oggenc2_sse2.exe", 287}, diff --git a/src/Thread_Process.cpp b/src/Thread_Process.cpp index fa0944a0..3da17381 100644 --- a/src/Thread_Process.cpp +++ b/src/Thread_Process.cpp @@ -73,6 +73,11 @@ ProcessThread::~ProcessThread(void) lamexp_remove_file(m_tempFiles.takeFirst()); } + while(!m_filters.isEmpty()) + { + delete m_filters.takeFirst(); + } + LAMEXP_DELETE(m_encoder); } @@ -108,19 +113,17 @@ void ProcessThread::processFile() emit processStateFinished(m_jobId, outFileName, false); return; } - - QList filters; //Do we need Stereo downmix? if(m_audioFile.formatAudioChannels() > 2 && m_encoder->requiresDownmix()) { - filters.prepend(new DownmixFilter()); + m_filters.prepend(new DownmixFilter()); } QString sourceFile = m_audioFile.filePath(); //Decode source file - if(!filters.isEmpty() || !m_encoder->isFormatSupported(m_audioFile.formatContainerType(), m_audioFile.formatContainerProfile(), m_audioFile.formatAudioType(), m_audioFile.formatAudioProfile(), m_audioFile.formatAudioVersion())) + if(!m_filters.isEmpty() || !m_encoder->isFormatSupported(m_audioFile.formatContainerType(), m_audioFile.formatContainerProfile(), m_audioFile.formatAudioType(), m_audioFile.formatAudioProfile(), m_audioFile.formatAudioVersion())) { m_currentStep = DecodingStep; AbstractDecoder *decoder = DecoderRegistry::lookup(m_audioFile.formatContainerType(), m_audioFile.formatContainerProfile(), m_audioFile.formatAudioType(), m_audioFile.formatAudioProfile(), m_audioFile.formatAudioVersion()); @@ -150,10 +153,10 @@ void ProcessThread::processFile() } //Apply all filters - while(!filters.isEmpty()) + while(!m_filters.isEmpty()) { QString tempFile = generateTempFileName(); - AbstractFilter *poFilter = filters.takeFirst(); + AbstractFilter *poFilter = m_filters.takeFirst(); if(bSuccess) { @@ -317,6 +320,11 @@ QString ProcessThread::generateTempFileName(void) return tempFileName; } +void ProcessThread::addFilter(AbstractFilter *filter) +{ + m_filters.append(filter); +} + //////////////////////////////////////////////////////////// // EVENTS //////////////////////////////////////////////////////////// diff --git a/src/Thread_Process.h b/src/Thread_Process.h index 5d2974c3..d1fac69c 100644 --- a/src/Thread_Process.h +++ b/src/Thread_Process.h @@ -29,6 +29,7 @@ #include "Encoder_Abstract.h" class QMutex; +class AbstractFilter; class ProcessThread: public QThread { @@ -42,6 +43,7 @@ public: void abort() { m_aborted = true; } QUuid getId() { return m_jobId; } + void addFilter(AbstractFilter *filter); private slots: void handleUpdate(int progress); @@ -74,6 +76,7 @@ private: ProcessStep m_currentStep; QStringList m_tempFiles; const bool m_prependRelativeSourcePath; + QList m_filters; static QMutex *m_mutex_genFileName; };