/////////////////////////////////////////////////////////////////////////////// // LameXP - Audio Encoder Front-End // Copyright (C) 2004-2013 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 "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; } }