Added new AbstractEncoderInfo class, which provides information about a specific encoder's configuration options. Also moved code for creating encoder instances into a separate EncoderRegistry class.

This commit is contained in:
LoRd_MuldeR 2013-09-30 21:39:56 +02:00
parent db95584256
commit ccb19ec07f
8 changed files with 437 additions and 5 deletions

View File

@ -324,6 +324,7 @@ del "$(TargetDir)imageformats\q???d4.dll"
<ClCompile Include="src\Model_Settings.cpp" />
<ClCompile Include="src\PlaylistImporter.cpp" />
<ClCompile Include="src\Registry_Decoder.cpp" />
<ClCompile Include="src\Registry_Encoder.cpp" />
<ClCompile Include="src\ShellIntegration.cpp" />
<ClCompile Include="src\Thread_CPUObserver.cpp" />
<ClCompile Include="src\Thread_CueSplitter.cpp" />
@ -373,6 +374,7 @@ del "$(TargetDir)imageformats\q???d4.dll"
<ClCompile Include="tmp\MOC_Model_MetaInfo.cpp" />
<ClCompile Include="tmp\MOC_Model_Progress.cpp" />
<ClCompile Include="tmp\MOC_Registry_Decoder.cpp" />
<ClCompile Include="tmp\MOC_Registry_Encoder.cpp" />
<ClCompile Include="tmp\MOC_ShellIntegration.cpp" />
<ClCompile Include="tmp\MOC_Thread_CPUObserver.cpp" />
<ClCompile Include="tmp\MOC_Thread_CueSplitter.cpp" />
@ -544,6 +546,17 @@ del "$(TargetDir)imageformats\q???d4.dll"
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)</Outputs>
</CustomBuild>
<ClInclude Include="src\Decoder_Opus.h" />
<CustomBuild Include="src\Registry_Encoder.h">
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)"</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)"</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release_Static|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)"</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp"</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp"</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Release_Static|Win32'">MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp"</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release_Static|Win32'">$(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)</Outputs>
</CustomBuild>
<ClInclude Include="src\Tools.h" />
<CustomBuild Include="src\Tool_WaveProperties.h">
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)"</Command>

View File

@ -382,6 +382,12 @@
<ClCompile Include="etc\Prerequisites\strnatcmp\src\strnatcmp.cpp">
<Filter>Source Files\Misc\3rd Party</Filter>
</ClCompile>
<ClCompile Include="src\Registry_Encoder.cpp">
<Filter>Source Files\Misc</Filter>
</ClCompile>
<ClCompile Include="tmp\MOC_Registry_Encoder.cpp">
<Filter>Generated Files\MOC</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Config.h">
@ -510,6 +516,9 @@
<ClInclude Include="src\Decoder_Opus.h">
<Filter>Header Files\Decoders</Filter>
</ClInclude>
<ClInclude Include="src\Registry_Encoder.h">
<Filter>Header Files\Misc</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="LameXP.rc" />

View File

@ -34,7 +34,7 @@
#define VER_LAMEXP_MINOR_LO 8
#define VER_LAMEXP_TYPE Final
#define VER_LAMEXP_PATCH 1
#define VER_LAMEXP_BUILD 1338
#define VER_LAMEXP_BUILD 1340
#define VER_LAMEXP_CONFG 1338
///////////////////////////////////////////////////////////////////////////////

View File

@ -28,6 +28,25 @@ class QProcess;
class QStringList;
class QMutex;
class AbstractEncoderInfo
{
public:
typedef enum
{
TYPE_BITRATE = 0,
TYPE_APPROX_BITRATE = 1,
TYPE_QUALITY_LEVEL = 2,
TYPE_COMPRESSION_LEVEL = 3,
TYPE_UNCOMPRESSED = 4
}
value_type_t;
virtual bool isModeSupported(int mode) const = 0; //Returns whether the encoder does support the current RC mode
virtual int valueCount(int mode) const = 0; //The number of bitrate/quality values for current RC mode
virtual int valueAt(int mode, int index) const = 0; //The bitrate/quality value at 'index' for the current RC mode
virtual int valueType(int mode) const = 0; //The display type of the values for the current RC mode
};
class AbstractEncoder : public AbstractTool
{
Q_OBJECT
@ -50,6 +69,13 @@ public:
virtual void setRCMode(int mode);
virtual void setCustomParams(const QString &customParams);
//Encoder info
static const AbstractEncoderInfo *getEncoderInfo(void)
{
throw "This method is supposed to be re-implemented in derived classes!";
return NULL;
}
protected:
int m_configBitrate; //Bitrate *or* VBR-quality-level
int m_configRCMode; //Rate-control mode

View File

@ -28,7 +28,81 @@
#include <QDir>
#include <limits.h>
static const int g_lameAgorithmQualityLUT[] = {9, 7, 3, 0, INT_MAX};
static const int g_lameAgorithmQualityLUT[5] = {9, 7, 3, 0, INT_MAX};
static const int g_mp3BitrateLUT[15] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1};
static const int g_lameVBRQualityLUT[11] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0, INT_MAX};
///////////////////////////////////////////////////////////////////////////////
class : public AbstractEncoderInfo
{
virtual bool isModeSupported(int mode) const
{
switch(mode)
{
case SettingsModel::VBRMode:
case SettingsModel::ABRMode:
case SettingsModel::CBRMode:
return true;
break;
default:
throw "Bad RC mode specified!";
}
}
virtual int valueCount(int mode) const
{
switch(mode)
{
case SettingsModel::VBRMode:
return 10;
break;
case SettingsModel::ABRMode:
case SettingsModel::CBRMode:
return 14;
break;
default:
throw "Bad RC mode specified!";
}
}
virtual int valueAt(int mode, int index) const
{
switch(mode)
{
case SettingsModel::VBRMode:
return g_lameVBRQualityLUT[index];
break;
case SettingsModel::ABRMode:
case SettingsModel::CBRMode:
return g_mp3BitrateLUT[index];
break;
default:
throw "Bad RC mode specified!";
}
}
virtual int valueType(int mode) const
{
switch(mode)
{
case SettingsModel::VBRMode:
return TYPE_QUALITY_LEVEL;
break;
case SettingsModel::ABRMode:
return TYPE_APPROX_BITRATE;
break;
case SettingsModel::CBRMode:
return TYPE_BITRATE;
break;
default:
throw "Bad RC mode specified!";
}
}
}
g_mp3EncoderInfo;
///////////////////////////////////////////////////////////////////////////////
MP3Encoder::MP3Encoder(void)
:
@ -61,14 +135,14 @@ bool MP3Encoder::encode(const QString &sourceFile, const AudioFileModel &metaInf
switch(m_configRCMode)
{
case SettingsModel::VBRMode:
args << "-V" << QString::number(9 - qBound(0, m_configBitrate, 9));
args << "-V" << QString::number(g_lameVBRQualityLUT[qBound(0, m_configBitrate, 9)]);
break;
case SettingsModel::ABRMode:
args << "--abr" << QString::number(SettingsModel::mp3Bitrates[qBound(0, m_configBitrate, 13)]);
args << "--abr" << QString::number(g_mp3BitrateLUT[qBound(0, m_configBitrate, 13)]);
break;
case SettingsModel::CBRMode:
args << "--cbr";
args << "-b" << QString::number(SettingsModel::mp3Bitrates[qBound(0, m_configBitrate, 13)]);
args << "-b" << QString::number(g_mp3BitrateLUT[qBound(0, m_configBitrate, 13)]);
break;
default:
throw "Bad rate-control mode!";
@ -282,3 +356,8 @@ int MP3Encoder::clipBitrate(int bitrate)
return targetBitrate;
}
const AbstractEncoderInfo *MP3Encoder::getEncoderInfo(void)
{
return &g_mp3EncoderInfo;
}

View File

@ -44,6 +44,9 @@ public:
virtual void setSamplingRate(int value);
virtual void setChannelMode(int value);
//Encoder info
static const AbstractEncoderInfo *getEncoderInfo(void);
private:
const QString m_binary;
int m_algorithmQuality;

263
src/Registry_Encoder.cpp Normal file
View File

@ -0,0 +1,263 @@
///////////////////////////////////////////////////////////////////////////////
// LameXP - Audio Encoder Front-End
// Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
//
// 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 "Registry_Encoder.h"
#include "Model_Settings.h"
#include "Encoder_AAC.h"
#include "Encoder_AAC_FHG.h"
#include "Encoder_AAC_QAAC.h"
#include "Encoder_AC3.h"
#include "Encoder_DCA.h"
#include "Encoder_FLAC.h"
#include "Encoder_MP3.h"
#include "Encoder_Vorbis.h"
#include "Encoder_Opus.h"
#include "Encoder_Wave.h"
#define IS_VBR(RC_MODE) ((RC_MODE) == SettingsModel::VBRMode)
AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const SettingsModel *settings, bool *nativeResampling)
{
int rcMode = -1;
AbstractEncoder *encoder = NULL;
*nativeResampling = false;
switch(encoderId)
{
/*-------- MP3Encoder /*--------*/
case SettingsModel::MP3Encoder:
{
MP3Encoder *mp3Encoder = new MP3Encoder();
mp3Encoder->setRCMode(rcMode = settings->compressionRCModeLAME());
mp3Encoder->setBitrate(IS_VBR(rcMode) ? settings->compressionVbrLevelLAME() : settings->compressionBitrateLAME());
mp3Encoder->setAlgoQuality(settings->lameAlgoQuality());
if(settings->bitrateManagementEnabled())
{
mp3Encoder->setBitrateLimits(settings->bitrateManagementMinRate(), settings->bitrateManagementMaxRate());
}
if(settings->samplingRate() > 0)
{
mp3Encoder->setSamplingRate(SettingsModel::samplingRates[settings->samplingRate()]);
*nativeResampling = true;
}
mp3Encoder->setChannelMode(settings->lameChannelMode());
mp3Encoder->setCustomParams(settings->customParametersLAME());
encoder = mp3Encoder;
}
break;
/*-------- VorbisEncoder /*--------*/
case SettingsModel::VorbisEncoder:
{
VorbisEncoder *vorbisEncoder = new VorbisEncoder();
vorbisEncoder->setRCMode(rcMode = settings->compressionRCModeOggEnc());
vorbisEncoder->setBitrate(IS_VBR(rcMode) ? settings->compressionVbrLevelOggEnc() : settings->compressionBitrateOggEnc());
if(settings->bitrateManagementEnabled())
{
vorbisEncoder->setBitrateLimits(settings->bitrateManagementMinRate(), settings->bitrateManagementMaxRate());
}
if(settings->samplingRate() > 0)
{
vorbisEncoder->setSamplingRate(SettingsModel::samplingRates[settings->samplingRate()]);
*nativeResampling = true;
}
vorbisEncoder->setCustomParams(settings->customParametersOggEnc());
encoder = vorbisEncoder;
}
break;
/*-------- AACEncoder /*--------*/
case SettingsModel::AACEncoder:
{
switch(SettingsModel::getAacEncoder())
{
case SettingsModel::AAC_ENCODER_QAAC:
{
QAACEncoder *aacEncoder = new QAACEncoder();
aacEncoder->setRCMode(rcMode = settings->compressionRCModeAacEnc());
aacEncoder->setBitrate(IS_VBR(rcMode) ? settings->compressionVbrLevelAacEnc() : settings->compressionBitrateAacEnc());
aacEncoder->setProfile(settings->aacEncProfile());
aacEncoder->setCustomParams(settings->customParametersAacEnc());
encoder = aacEncoder;
}
break;
case SettingsModel::AAC_ENCODER_FHG:
{
FHGAACEncoder *aacEncoder = new FHGAACEncoder();
aacEncoder->setRCMode(rcMode = settings->compressionRCModeAacEnc());
aacEncoder->setBitrate(IS_VBR(rcMode) ? settings->compressionVbrLevelAacEnc() : settings->compressionBitrateAacEnc());
aacEncoder->setProfile(settings->aacEncProfile());
aacEncoder->setCustomParams(settings->customParametersAacEnc());
encoder = aacEncoder;
}
break;
case SettingsModel::AAC_ENCODER_NERO:
{
AACEncoder *aacEncoder = new AACEncoder();
aacEncoder->setRCMode(rcMode = settings->compressionRCModeAacEnc());
aacEncoder->setBitrate(IS_VBR(rcMode) ? settings->compressionVbrLevelAacEnc() : settings->compressionBitrateAacEnc());
aacEncoder->setEnable2Pass(settings->neroAACEnable2Pass());
aacEncoder->setProfile(settings->aacEncProfile());
aacEncoder->setCustomParams(settings->customParametersAacEnc());
encoder = aacEncoder;
}
break;
default:
throw "makeEncoder(): Unknown AAC encoder specified!";
break;
}
}
break;
/*-------- AC3Encoder /*--------*/
case SettingsModel::AC3Encoder:
{
AC3Encoder *ac3Encoder = new AC3Encoder();
ac3Encoder->setRCMode(rcMode = settings->compressionRCModeAften());
ac3Encoder->setBitrate(IS_VBR(rcMode) ? settings->compressionVbrLevelAften() : settings->compressionBitrateAften());
ac3Encoder->setCustomParams(settings->customParametersAften());
ac3Encoder->setAudioCodingMode(settings->aftenAudioCodingMode());
ac3Encoder->setDynamicRangeCompression(settings->aftenDynamicRangeCompression());
ac3Encoder->setExponentSearchSize(settings->aftenExponentSearchSize());
ac3Encoder->setFastBitAllocation(settings->aftenFastBitAllocation());
encoder = ac3Encoder;
}
break;
/*-------- FLACEncoder /*--------*/
case SettingsModel::FLACEncoder:
{
FLACEncoder *flacEncoder = new FLACEncoder();
flacEncoder->setBitrate(settings->compressionVbrLevelFLAC());
flacEncoder->setRCMode(SettingsModel::VBRMode);
flacEncoder->setCustomParams(settings->customParametersFLAC());
encoder = flacEncoder;
}
break;
/*-------- OpusEncoder --------*/
case SettingsModel::OpusEncoder:
{
OpusEncoder *opusEncoder = new OpusEncoder();
opusEncoder->setRCMode(rcMode = settings->compressionRCModeOpusEnc());
opusEncoder->setBitrate(settings->compressionBitrateOpusEnc()); /*Opus always uses bitrate*/
opusEncoder->setOptimizeFor(settings->opusOptimizeFor());
opusEncoder->setEncodeComplexity(settings->opusComplexity());
opusEncoder->setFrameSize(settings->opusFramesize());
opusEncoder->setCustomParams(settings->customParametersOpus());
encoder = opusEncoder;
}
break;
/*-------- DCAEncoder --------*/
case SettingsModel::DCAEncoder:
{
DCAEncoder *dcaEncoder = new DCAEncoder();
dcaEncoder->setRCMode(SettingsModel::CBRMode);
dcaEncoder->setBitrate(IS_VBR(rcMode) ? 0 : settings->compressionBitrateDcaEnc());
encoder = dcaEncoder;
}
break;
/*-------- PCMEncoder --------*/
case SettingsModel::PCMEncoder:
{
WaveEncoder *waveEncoder = new WaveEncoder();
waveEncoder->setBitrate(0); /*does NOT apply to PCM output*/
waveEncoder->setRCMode(0); /*does NOT apply to PCM output*/
encoder = waveEncoder;
}
break;
/*-------- default --------*/
default:
throw "Unsupported encoder!";
}
//Sanity checking
if(!encoder)
{
throw "No encoder instance has been assigend!";
}
return encoder;
}
const AbstractEncoderInfo *EncoderRegistry::getEncoderInfo(const int encoderId)
{
const AbstractEncoderInfo *info = NULL;
switch(encoderId)
{
/*-------- MP3Encoder /*--------*/
case SettingsModel::MP3Encoder:
info = MP3Encoder::getEncoderInfo();
break;
/*-------- VorbisEncoder /*--------*/
case SettingsModel::VorbisEncoder:
info = VorbisEncoder::getEncoderInfo();
break;
/*-------- AACEncoder /*--------*/
case SettingsModel::AACEncoder:
{
switch(SettingsModel::getAacEncoder())
{
case SettingsModel::AAC_ENCODER_QAAC:
info = QAACEncoder::getEncoderInfo();
break;
case SettingsModel::AAC_ENCODER_FHG:
info = FHGAACEncoder::getEncoderInfo();
break;
case SettingsModel::AAC_ENCODER_NERO:
info = AACEncoder::getEncoderInfo();
break;
default:
throw "Unknown AAC encoder specified!";
break;
}
}
break;
/*-------- AC3Encoder /*--------*/
case SettingsModel::AC3Encoder:
info = AC3Encoder::getEncoderInfo();
break;
/*-------- FLACEncoder /*--------*/
case SettingsModel::FLACEncoder:
info = FLACEncoder::getEncoderInfo();
break;
/*-------- OpusEncoder --------*/
case SettingsModel::OpusEncoder:
info = OpusEncoder::getEncoderInfo();
break;
/*-------- DCAEncoder --------*/
case SettingsModel::DCAEncoder:
info = DCAEncoder::getEncoderInfo();
break;
/*-------- PCMEncoder --------*/
case SettingsModel::PCMEncoder:
info = WaveEncoder::getEncoderInfo();
break;
/*-------- default --------*/
default:
throw "Unsupported encoder!";
}
//Sanity checking
if(!info)
{
throw "No encoder instance has been assigend!";
}
return info;
}

39
src/Registry_Encoder.h Normal file
View File

@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////////
// LameXP - Audio Encoder Front-End
// Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
//
// 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 <QObject>
class AbstractEncoder;
class AbstractEncoderInfo;
class SettingsModel;
class EncoderRegistry : public QObject
{
Q_OBJECT
public:
static AbstractEncoder *createInstance(const int encoderId, const SettingsModel *settings, bool *nativeResampling);
static const AbstractEncoderInfo *getEncoderInfo(const int encoderId);
static void saveEncoderConfig(SettingsModel *settings, const int encoderId, const int rcMode, const int value);
static int loadEncoderConfig(const SettingsModel *settings, const int encoderId, const int rcMode);
};