LameXP/src/Registry_Encoder.cpp

410 lines
14 KiB
C++
Raw Normal View History

///////////////////////////////////////////////////////////////////////////////
// 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 "Global.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)
////////////////////////////////////////////////////////////
// Create encoder instance
////////////////////////////////////////////////////////////
AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const SettingsModel *settings, bool *nativeResampling)
{
int rcMode = -1;
AbstractEncoder *encoder = NULL;
*nativeResampling = false;
//Sanity checking
if((rcMode < SettingsModel::VBRMode) || (rcMode > SettingsModel::CBRMode))
{
throw "Unknown rate-control mode!";
}
//Create new encoder instance
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(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;
}
////////////////////////////////////////////////////////////
// Get encoder info
////////////////////////////////////////////////////////////
const AbstractEncoderInfo *EncoderRegistry::getEncoderInfo(const int encoderId)
{
const AbstractEncoderInfo *info = NULL;
switch(encoderId)
{
case SettingsModel::MP3Encoder: info = MP3Encoder::getEncoderInfo(); break;
case SettingsModel::VorbisEncoder: info = VorbisEncoder::getEncoderInfo(); break;
case SettingsModel::AC3Encoder: info = AC3Encoder::getEncoderInfo(); break;
case SettingsModel::FLACEncoder: info = FLACEncoder::getEncoderInfo(); break;
case SettingsModel::OpusEncoder: info = OpusEncoder::getEncoderInfo(); break;
case SettingsModel::DCAEncoder: info = DCAEncoder::getEncoderInfo(); break;
case SettingsModel::PCMEncoder: info = WaveEncoder::getEncoderInfo(); break;
case SettingsModel::AACEncoder:
switch(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;
default: throw "Unsupported encoder!";
}
//Sanity checking
if(!info)
{
throw "No encoder instance has been assigend!";
}
return info;
}
////////////////////////////////////////////////////////////
// Load/store encoder RC mode
////////////////////////////////////////////////////////////
#define STORE_MODE(ENCODER_ID, RC_MODE) do \
{ \
settings->compressionRCMode##ENCODER_ID(RC_MODE); \
} \
while(0)
#define LOAD_MODE(RC_MODE, ENCODER_ID) do \
{ \
(RC_MODE) = settings->compressionRCMode##ENCODER_ID(); \
} \
while(0)
void EncoderRegistry::saveEncoderMode(SettingsModel *settings, const int encoderId, const int rcMode)
{
//Sanity checking
if((rcMode < SettingsModel::VBRMode) || (rcMode > SettingsModel::CBRMode))
{
throw "Unknown rate-control mode!";
}
//Store the encoder bitrate/quality value
switch(encoderId)
{
case SettingsModel::MP3Encoder: STORE_MODE(LAME, rcMode); break;
case SettingsModel::VorbisEncoder: STORE_MODE(OggEnc, rcMode); break;
case SettingsModel::AACEncoder: STORE_MODE(AacEnc, rcMode); break;
case SettingsModel::AC3Encoder: STORE_MODE(Aften, rcMode); break;
case SettingsModel::FLACEncoder: STORE_MODE(FLAC, rcMode); break;
case SettingsModel::OpusEncoder: STORE_MODE(OpusEnc, rcMode); break;
case SettingsModel::DCAEncoder: STORE_MODE(DcaEnc, rcMode); break;
case SettingsModel::PCMEncoder: STORE_MODE(Wave, rcMode); break;
default: throw "Unsupported encoder!";
}
}
int EncoderRegistry::loadEncoderMode(SettingsModel *settings, const int encoderId)
{
int rcMode = -1;
//Store the encoder bitrate/quality value
switch(encoderId)
{
case SettingsModel::MP3Encoder: LOAD_MODE(rcMode, LAME); break;
case SettingsModel::VorbisEncoder: LOAD_MODE(rcMode, OggEnc); break;
case SettingsModel::AACEncoder: LOAD_MODE(rcMode, AacEnc); break;
case SettingsModel::AC3Encoder: LOAD_MODE(rcMode, Aften); break;
case SettingsModel::FLACEncoder: LOAD_MODE(rcMode, FLAC); break;
case SettingsModel::OpusEncoder: LOAD_MODE(rcMode, OpusEnc); break;
case SettingsModel::DCAEncoder: LOAD_MODE(rcMode, DcaEnc); break;
case SettingsModel::PCMEncoder: LOAD_MODE(rcMode, Wave); break;
default: throw "Unsupported encoder!";
}
return rcMode;
}
////////////////////////////////////////////////////////////
// Load/store encoder bitrate/quality value
////////////////////////////////////////////////////////////
#define STORE_VALUE(ENCODER_ID, RC_MODE, VALUE) do \
{ \
if(IS_VBR(RC_MODE)) \
{ \
settings->compressionVbrLevel##ENCODER_ID(VALUE); \
} \
else \
{ \
settings->compressionBitrate##ENCODER_ID(VALUE); \
} \
} \
while(0)
#define LOAD_VALUE(VALUE, ENCODER_ID, RC_MODE) do \
{ \
if(IS_VBR(RC_MODE)) \
{ \
(VALUE) = settings->compressionVbrLevel##ENCODER_ID(); \
} \
else \
{ \
(VALUE) = settings->compressionBitrate##ENCODER_ID(); \
} \
} \
while(0)
void EncoderRegistry::saveEncoderValue(SettingsModel *settings, const int encoderId, const int rcMode, const int value)
{
//Sanity checking
if((rcMode < SettingsModel::VBRMode) || (rcMode > SettingsModel::CBRMode))
{
throw "Unknown rate-control mode!";
}
//Store the encoder bitrate/quality value
switch(encoderId)
{
case SettingsModel::MP3Encoder: STORE_VALUE(LAME, rcMode, value); break;
case SettingsModel::VorbisEncoder: STORE_VALUE(OggEnc, rcMode, value); break;
case SettingsModel::AACEncoder: STORE_VALUE(AacEnc, rcMode, value); break;
case SettingsModel::AC3Encoder: STORE_VALUE(Aften, rcMode, value); break;
case SettingsModel::FLACEncoder: STORE_VALUE(FLAC, rcMode, value); break;
case SettingsModel::OpusEncoder: STORE_VALUE(OpusEnc, rcMode, value); break;
case SettingsModel::DCAEncoder: STORE_VALUE(DcaEnc, rcMode, value); break;
case SettingsModel::PCMEncoder: STORE_VALUE(Wave, rcMode, value); break;
default: throw "Unsupported encoder!";
}
}
int EncoderRegistry::loadEncoderValue(const SettingsModel *settings, const int encoderId, const int rcMode)
{
int value = INT_MAX;
//Sanity checking
if((rcMode < SettingsModel::VBRMode) || (rcMode > SettingsModel::CBRMode))
{
throw "Unknown rate-control mode!";
}
//Load the encoder bitrate/quality value
switch(encoderId)
{
case SettingsModel::MP3Encoder: LOAD_VALUE(value, LAME, rcMode); break;
case SettingsModel::VorbisEncoder: LOAD_VALUE(value, OggEnc, rcMode); break;
case SettingsModel::AACEncoder: LOAD_VALUE(value, AacEnc, rcMode); break;
case SettingsModel::AC3Encoder: LOAD_VALUE(value, Aften, rcMode); break;
case SettingsModel::FLACEncoder: LOAD_VALUE(value, FLAC, rcMode); break;
case SettingsModel::OpusEncoder: LOAD_VALUE(value, OpusEnc, rcMode); break;
case SettingsModel::DCAEncoder: LOAD_VALUE(value, DcaEnc, rcMode); break;
case SettingsModel::PCMEncoder: LOAD_VALUE(value, Wave, rcMode); break;
default: throw "Unsupported encoder!";
}
return value;
}
////////////////////////////////////////////////////////////
// Static Functions
////////////////////////////////////////////////////////////
int EncoderRegistry::getAacEncoder(void)
{
if(lamexp_check_tool("qaac.exe") && lamexp_check_tool("libsoxrate.dll"))
{
return SettingsModel::AAC_ENCODER_QAAC;
}
else if(lamexp_check_tool("fhgaacenc.exe") && lamexp_check_tool("enc_fhgaac.dll") && lamexp_check_tool("nsutil.dll") && lamexp_check_tool("libmp4v2.dll"))
{
return SettingsModel::AAC_ENCODER_FHG;
}
else if(lamexp_check_tool("neroAacEnc.exe") && lamexp_check_tool("neroAacDec.exe") && lamexp_check_tool("neroAacTag.exe"))
{
return SettingsModel::AAC_ENCODER_NERO;
}
else
{
return SettingsModel::AAC_ENCODER_NONE;
}
}