diff --git a/src/Config.h b/src/Config.h index ab09552d..5f322f6e 100644 --- a/src/Config.h +++ b/src/Config.h @@ -35,7 +35,7 @@ #define VER_LAMEXP_MINOR_LO 4 #define VER_LAMEXP_TYPE Alpha #define VER_LAMEXP_PATCH 1 -#define VER_LAMEXP_BUILD 1857 +#define VER_LAMEXP_BUILD 1858 #define VER_LAMEXP_CONFG 1818 /////////////////////////////////////////////////////////////////////////////// diff --git a/src/Dialog_Processing.cpp b/src/Dialog_Processing.cpp index d65757c0..4334f4c8 100644 --- a/src/Dialog_Processing.cpp +++ b/src/Dialog_Processing.cpp @@ -569,10 +569,9 @@ void ProcessingDialog::startNextJob(void) m_runningThreads++; AudioFileModel currentFile = updateMetaInfo(m_pendingJobs.takeFirst()); - bool nativeResampling = false; //Create encoder instance - AbstractEncoder *encoder = EncoderRegistry::createInstance(m_settings->compressionEncoder(), m_settings, &nativeResampling); + AbstractEncoder *encoder = EncoderRegistry::createInstance(m_settings->compressionEncoder(), m_settings); //Create processing thread ProcessThread *thread = new ProcessThread @@ -589,11 +588,19 @@ void ProcessingDialog::startNextJob(void) { thread->addFilter(new DownmixFilter()); } - if((m_settings->samplingRate() > 0) && !nativeResampling) + if(m_settings->samplingRate() > 0) { - if(SettingsModel::samplingRates[m_settings->samplingRate()] != currentFile.techInfo().audioSamplerate() || currentFile.techInfo().audioSamplerate() == 0) + const int targetRate = SettingsModel::samplingRates[qBound(1, m_settings->samplingRate(), 6)]; + if((targetRate != currentFile.techInfo().audioSamplerate()) || (currentFile.techInfo().audioSamplerate() == 0)) { - thread->addFilter(new ResampleFilter(SettingsModel::samplingRates[m_settings->samplingRate()])); + if (encoder->toEncoderInfo()->isResamplingSupported()) + { + encoder->setSamplingRate(targetRate); + } + else + { + thread->addFilter(new ResampleFilter(targetRate)); + } } } if((m_settings->toneAdjustBass() != 0) || (m_settings->toneAdjustTreble() != 0)) diff --git a/src/Encoder_AAC.cpp b/src/Encoder_AAC.cpp index 9322e393..8407d910 100644 --- a/src/Encoder_AAC.cpp +++ b/src/Encoder_AAC.cpp @@ -114,6 +114,11 @@ class AACEncoderInfo : public AbstractEncoderInfo static const char* s_extension = "mp4"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return false; + } } static const g_aacEncoderInfo; diff --git a/src/Encoder_AAC_FDK.cpp b/src/Encoder_AAC_FDK.cpp index cc4c4bb5..c06d8dd1 100644 --- a/src/Encoder_AAC_FDK.cpp +++ b/src/Encoder_AAC_FDK.cpp @@ -120,6 +120,11 @@ class FDKAACEncoderInfo : public AbstractEncoderInfo static const char* s_extension = "mp4"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return false; + } } static const g_fdkAacEncoderInfo; diff --git a/src/Encoder_AAC_FHG.cpp b/src/Encoder_AAC_FHG.cpp index 238c9b6e..f91a6e81 100644 --- a/src/Encoder_AAC_FHG.cpp +++ b/src/Encoder_AAC_FHG.cpp @@ -117,6 +117,11 @@ class FHGAACEncoderInfo : public AbstractEncoderInfo static const char* s_extension = "mp4"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return false; + } } static const g_fhgAacEncoderInfo; diff --git a/src/Encoder_AAC_QAAC.cpp b/src/Encoder_AAC_QAAC.cpp index b033d4f6..14974062 100644 --- a/src/Encoder_AAC_QAAC.cpp +++ b/src/Encoder_AAC_QAAC.cpp @@ -125,6 +125,11 @@ class QAACEncoderInfo : public AbstractEncoderInfo static const char* s_extension = "mp4"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return true; + } } static const g_qaacEncoderInfo; @@ -187,6 +192,12 @@ bool QAACEncoder::encode(const QString &sourceFile, const AudioFileModel_MetaInf break; } + if (m_configSamplingRate > 0) + { + args << "-native-resampler" << "bats,127"; + args << "--rate" << QString::number(m_configSamplingRate); + } + if(!m_configCustomParams.isEmpty()) args << m_configCustomParams.split(" ", QString::SkipEmptyParts); if(!metaInfo.title().isEmpty()) args << "--title" << cleanTag(metaInfo.title()); diff --git a/src/Encoder_AC3.cpp b/src/Encoder_AC3.cpp index 4068cdfd..ee26b535 100644 --- a/src/Encoder_AC3.cpp +++ b/src/Encoder_AC3.cpp @@ -113,6 +113,11 @@ class AC3EncoderInfo : public AbstractEncoderInfo static const char* s_extension = "ac3"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return false; + } } static const g_aftenEncoderInfo; diff --git a/src/Encoder_Abstract.cpp b/src/Encoder_Abstract.cpp index 2f99bc53..38632e00 100644 --- a/src/Encoder_Abstract.cpp +++ b/src/Encoder_Abstract.cpp @@ -33,6 +33,7 @@ AbstractEncoder::AbstractEncoder(void) m_configBitrate = 0; m_configRCMode = 0; m_configCustomParams.clear(); + m_configSamplingRate = 0; } AbstractEncoder::~AbstractEncoder(void) @@ -43,9 +44,38 @@ AbstractEncoder::~AbstractEncoder(void) * Setters */ -void AbstractEncoder::setBitrate(int bitrate) { m_configBitrate = qMax(0, bitrate); } -void AbstractEncoder::setRCMode(int mode) { m_configRCMode = qMax(0, mode); } -void AbstractEncoder::setCustomParams(const QString &customParams) { m_configCustomParams = customParams.trimmed(); } +void AbstractEncoder::setRCMode(const int &mode) +{ + if (!toEncoderInfo()->isModeSupported(qMax(0, mode))) + { + MUTILS_THROW("This RC mode is not supported by the encoder!"); + } + m_configRCMode = qMax(0, mode); +} + +void AbstractEncoder::setBitrate(const int &bitrate) +{ + if (qMax(0, bitrate) >= toEncoderInfo()->valueCount(bitrate)) + { + MUTILS_THROW("The specified bitrate/quality is out of range!"); + } + m_configBitrate = qMax(0, bitrate); +} + +void AbstractEncoder::setCustomParams(const QString &customParams) +{ + m_configCustomParams = customParams.trimmed(); +} + +void AbstractEncoder::setSamplingRate(const int &value) +{ + if (!toEncoderInfo()->isResamplingSupported()) + { + MUTILS_THROW("This encoder does *not* support native resampling!"); + } + m_configSamplingRate = qBound(0, value, 48000); +}; + /* * Default implementation @@ -75,6 +105,7 @@ const bool AbstractEncoder::needsTimingInfo(void) return false; } + /* * Helper functions */ diff --git a/src/Encoder_Abstract.h b/src/Encoder_Abstract.h index f688a266..c84d428c 100644 --- a/src/Encoder_Abstract.h +++ b/src/Encoder_Abstract.h @@ -49,6 +49,7 @@ public: value_type_t; virtual bool isModeSupported(int mode) const = 0; //Returns whether the encoder does support the current RC mode + virtual bool isResamplingSupported(void) const = 0; //Returns whether the encoder has "native" resampling support 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 @@ -73,8 +74,9 @@ public: virtual const bool needsTimingInfo(void); //Common setter methods - virtual void setBitrate(int bitrate); - virtual void setRCMode(int mode); + virtual void setBitrate(const int &bitrate); + virtual void setRCMode(const int &mode); + virtual void setSamplingRate(const int &value); virtual void setCustomParams(const QString &customParams); //Encoder info @@ -88,6 +90,7 @@ public: protected: int m_configBitrate; //Bitrate *or* VBR-quality-level int m_configRCMode; //Rate-control mode + int m_configSamplingRate; //Target sampling rate QString m_configCustomParams; //Custom parameters, if any //Helper functions diff --git a/src/Encoder_DCA.cpp b/src/Encoder_DCA.cpp index 61a20973..2c2ecfc5 100644 --- a/src/Encoder_DCA.cpp +++ b/src/Encoder_DCA.cpp @@ -115,6 +115,11 @@ class DCAEncoderInfo : public AbstractEncoderInfo static const char* s_extension = "dts"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return false; + } } static const g_dcaEncoderInfo; diff --git a/src/Encoder_FLAC.cpp b/src/Encoder_FLAC.cpp index 4cea9b04..3f63e3ab 100644 --- a/src/Encoder_FLAC.cpp +++ b/src/Encoder_FLAC.cpp @@ -109,6 +109,11 @@ public: static const char* s_extension = "flac"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return false; + } } static const g_flacEncoderInfo; diff --git a/src/Encoder_MAC.cpp b/src/Encoder_MAC.cpp index 05018cc3..5778a9f9 100644 --- a/src/Encoder_MAC.cpp +++ b/src/Encoder_MAC.cpp @@ -109,6 +109,11 @@ class MACEncoderInfo : public AbstractEncoderInfo static const char* s_extension = "ape"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return false; + } } static const g_macEncoderInfo; diff --git a/src/Encoder_MP3.cpp b/src/Encoder_MP3.cpp index 3e7f77d6..bd5c86da 100644 --- a/src/Encoder_MP3.cpp +++ b/src/Encoder_MP3.cpp @@ -114,6 +114,11 @@ class MP3EncoderInfo : public AbstractEncoderInfo static const char* s_extension = "mp3"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return true; + } } static const g_mp3EncoderInfo; @@ -334,11 +339,6 @@ void MP3Encoder::setBitrateLimits(int minimumBitrate, int maximumBitrate) m_configBitrateMaximum = maximumBitrate; } -void MP3Encoder::setSamplingRate(int value) -{ - m_configSamplingRate = value; -} - void MP3Encoder::setChannelMode(int value) { m_configChannelMode = value; diff --git a/src/Encoder_MP3.h b/src/Encoder_MP3.h index 13e89e46..0bf4c710 100644 --- a/src/Encoder_MP3.h +++ b/src/Encoder_MP3.h @@ -41,7 +41,6 @@ public: //Advanced options virtual void setAlgoQuality(int value); virtual void setBitrateLimits(int minimumBitrate, int maximumBitrate); - virtual void setSamplingRate(int value); virtual void setChannelMode(int value); //Encoder info @@ -53,7 +52,6 @@ private: int m_algorithmQuality; int m_configBitrateMaximum; int m_configBitrateMinimum; - int m_configSamplingRate; int m_configChannelMode; int clipBitrate(int bitrate); diff --git a/src/Encoder_Opus.cpp b/src/Encoder_Opus.cpp index 3a5898f5..eeb01224 100644 --- a/src/Encoder_Opus.cpp +++ b/src/Encoder_Opus.cpp @@ -110,6 +110,11 @@ class OpusEncoderInfo : public AbstractEncoderInfo static const char* s_extension = "opus"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return false; + } } static const g_opusEncoderInfo; diff --git a/src/Encoder_Vorbis.cpp b/src/Encoder_Vorbis.cpp index 6d4873b1..0c6ffbb2 100644 --- a/src/Encoder_Vorbis.cpp +++ b/src/Encoder_Vorbis.cpp @@ -111,6 +111,11 @@ class VorbisEncoderInfo : public AbstractEncoderInfo static const char* s_extension = "ogg"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return true; + } } static const g_vorbisEncoderInfo; @@ -275,11 +280,6 @@ void VorbisEncoder::setBitrateLimits(int minimumBitrate, int maximumBitrate) m_configBitrateMaximum = maximumBitrate; } -void VorbisEncoder::setSamplingRate(int value) -{ - m_configSamplingRate = value; -} - const AbstractEncoderInfo *VorbisEncoder::getEncoderInfo(void) { return &g_vorbisEncoderInfo; diff --git a/src/Encoder_Vorbis.h b/src/Encoder_Vorbis.h index 4efc2e73..24ac3f77 100644 --- a/src/Encoder_Vorbis.h +++ b/src/Encoder_Vorbis.h @@ -37,7 +37,6 @@ public: virtual bool encode(const QString &sourceFile, const AudioFileModel_MetaInfo &metaInfo, const unsigned int duration, const QString &outputFile, volatile bool *abortFlag); virtual bool isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion); virtual void setBitrateLimits(int minimumBitrate, int maximumBitrate); - virtual void setSamplingRate(int value); //Encoder info virtual const AbstractEncoderInfo *toEncoderInfo(void) const { return getEncoderInfo(); } @@ -47,5 +46,4 @@ private: const QString m_binary; int m_configBitrateMaximum; int m_configBitrateMinimum; - int m_configSamplingRate; }; diff --git a/src/Encoder_Wave.cpp b/src/Encoder_Wave.cpp index a6eaa170..809bddbc 100644 --- a/src/Encoder_Wave.cpp +++ b/src/Encoder_Wave.cpp @@ -111,6 +111,11 @@ public: static const char* s_extension = "wav"; return s_extension; } + + virtual bool isResamplingSupported(void) const + { + return false; + } } static const g_waveEncoderInfo; diff --git a/src/Registry_Encoder.cpp b/src/Registry_Encoder.cpp index 77777a22..a9cdc06a 100644 --- a/src/Registry_Encoder.cpp +++ b/src/Registry_Encoder.cpp @@ -45,11 +45,10 @@ // Create encoder instance //////////////////////////////////////////////////////////// -AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const SettingsModel *settings, bool *nativeResampling) +AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const SettingsModel *settings) { int rcMode = -1; AbstractEncoder *encoder = NULL; - *nativeResampling = false; //Create new encoder instance and apply encoder-specific settings switch(encoderId) @@ -57,17 +56,12 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett /*-------- MP3Encoder /*--------*/ case SettingsModel::MP3Encoder: { - MP3Encoder *mp3Encoder = new MP3Encoder(); + MP3Encoder *const mp3Encoder = new MP3Encoder(); 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()); encoder = mp3Encoder; } @@ -75,16 +69,11 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett /*-------- VorbisEncoder /*--------*/ case SettingsModel::VorbisEncoder: { - VorbisEncoder *vorbisEncoder = new VorbisEncoder(); + VorbisEncoder *const vorbisEncoder = new VorbisEncoder(); if(settings->bitrateManagementEnabled()) { vorbisEncoder->setBitrateLimits(settings->bitrateManagementMinRate(), settings->bitrateManagementMaxRate()); } - if(settings->samplingRate() > 0) - { - vorbisEncoder->setSamplingRate(SettingsModel::samplingRates[settings->samplingRate()]); - *nativeResampling = true; - } encoder = vorbisEncoder; } break; @@ -95,28 +84,28 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett { case SettingsModel::AAC_ENCODER_QAAC: { - QAACEncoder *aacEncoder = new QAACEncoder(); + QAACEncoder *const aacEncoder = new QAACEncoder(); aacEncoder->setProfile(settings->aacEncProfile()); encoder = aacEncoder; } break; case SettingsModel::AAC_ENCODER_FHG: { - FHGAACEncoder *aacEncoder = new FHGAACEncoder(); + FHGAACEncoder *const aacEncoder = new FHGAACEncoder(); aacEncoder->setProfile(settings->aacEncProfile()); encoder = aacEncoder; } break; case SettingsModel::AAC_ENCODER_FDK: { - FDKAACEncoder *aacEncoder = new FDKAACEncoder(); + FDKAACEncoder *const aacEncoder = new FDKAACEncoder(); aacEncoder->setProfile(settings->aacEncProfile()); encoder = aacEncoder; } break; case SettingsModel::AAC_ENCODER_NERO: { - AACEncoder *aacEncoder = new AACEncoder(); + AACEncoder *const aacEncoder = new AACEncoder(); aacEncoder->setEnable2Pass(settings->neroAACEnable2Pass()); aacEncoder->setProfile(settings->aacEncProfile()); encoder = aacEncoder; @@ -131,7 +120,7 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett /*-------- AC3Encoder /*--------*/ case SettingsModel::AC3Encoder: { - AC3Encoder *ac3Encoder = new AC3Encoder(); + AC3Encoder *const ac3Encoder = new AC3Encoder(); ac3Encoder->setAudioCodingMode(settings->aftenAudioCodingMode()); ac3Encoder->setDynamicRangeCompression(settings->aftenDynamicRangeCompression()); ac3Encoder->setExponentSearchSize(settings->aftenExponentSearchSize()); @@ -142,14 +131,14 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett /*-------- FLACEncoder /*--------*/ case SettingsModel::FLACEncoder: { - FLACEncoder *flacEncoder = new FLACEncoder(); + FLACEncoder *const flacEncoder = new FLACEncoder(); encoder = flacEncoder; } break; /*-------- OpusEncoder --------*/ case SettingsModel::OpusEncoder: { - OpusEncoder *opusEncoder = new OpusEncoder(); + OpusEncoder *const opusEncoder = new OpusEncoder(); opusEncoder->setOptimizeFor(settings->opusOptimizeFor()); opusEncoder->setEncodeComplexity(settings->opusComplexity()); opusEncoder->setFrameSize(settings->opusFramesize()); @@ -159,21 +148,21 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett /*-------- DCAEncoder --------*/ case SettingsModel::DCAEncoder: { - DCAEncoder *dcaEncoder = new DCAEncoder(); + DCAEncoder *const dcaEncoder = new DCAEncoder(); encoder = dcaEncoder; } break; /*-------- MACEncoder --------*/ case SettingsModel::MACEncoder: { - MACEncoder *macEncoder = new MACEncoder(); + MACEncoder *const macEncoder = new MACEncoder(); encoder = macEncoder; } break; /*-------- PCMEncoder --------*/ case SettingsModel::PCMEncoder: { - WaveEncoder *waveEncoder = new WaveEncoder(); + WaveEncoder *const waveEncoder = new WaveEncoder(); encoder = waveEncoder; } break; diff --git a/src/Registry_Encoder.h b/src/Registry_Encoder.h index ee5f58ff..43fdeb5e 100644 --- a/src/Registry_Encoder.h +++ b/src/Registry_Encoder.h @@ -34,7 +34,7 @@ class EncoderRegistry : public QObject Q_OBJECT public: - static AbstractEncoder *createInstance(const int encoderId, const SettingsModel *settings, bool *nativeResampling); + static AbstractEncoder *createInstance(const int encoderId, const SettingsModel *settings); static const AbstractEncoderInfo *getEncoderInfo(const int encoderId); static void saveEncoderMode(SettingsModel *settings, const int encoderId, const int rcMode);