The information whether an encoder supports "native" resampling is provided via AbstractEncoderInfo class + enable "native" resampling for QAAC encoder.

This commit is contained in:
LoRd_MuldeR 2016-01-30 17:51:10 +01:00
parent 87a6e5cc18
commit de243d258f
20 changed files with 132 additions and 50 deletions

View File

@ -35,7 +35,7 @@
#define VER_LAMEXP_MINOR_LO 4 #define VER_LAMEXP_MINOR_LO 4
#define VER_LAMEXP_TYPE Alpha #define VER_LAMEXP_TYPE Alpha
#define VER_LAMEXP_PATCH 1 #define VER_LAMEXP_PATCH 1
#define VER_LAMEXP_BUILD 1857 #define VER_LAMEXP_BUILD 1858
#define VER_LAMEXP_CONFG 1818 #define VER_LAMEXP_CONFG 1818
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -569,10 +569,9 @@ void ProcessingDialog::startNextJob(void)
m_runningThreads++; m_runningThreads++;
AudioFileModel currentFile = updateMetaInfo(m_pendingJobs.takeFirst()); AudioFileModel currentFile = updateMetaInfo(m_pendingJobs.takeFirst());
bool nativeResampling = false;
//Create encoder instance //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 //Create processing thread
ProcessThread *thread = new ProcessThread ProcessThread *thread = new ProcessThread
@ -589,11 +588,19 @@ void ProcessingDialog::startNextJob(void)
{ {
thread->addFilter(new DownmixFilter()); 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)) if((m_settings->toneAdjustBass() != 0) || (m_settings->toneAdjustTreble() != 0))

View File

@ -114,6 +114,11 @@ class AACEncoderInfo : public AbstractEncoderInfo
static const char* s_extension = "mp4"; static const char* s_extension = "mp4";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return false;
}
} }
static const g_aacEncoderInfo; static const g_aacEncoderInfo;

View File

@ -120,6 +120,11 @@ class FDKAACEncoderInfo : public AbstractEncoderInfo
static const char* s_extension = "mp4"; static const char* s_extension = "mp4";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return false;
}
} }
static const g_fdkAacEncoderInfo; static const g_fdkAacEncoderInfo;

View File

@ -117,6 +117,11 @@ class FHGAACEncoderInfo : public AbstractEncoderInfo
static const char* s_extension = "mp4"; static const char* s_extension = "mp4";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return false;
}
} }
static const g_fhgAacEncoderInfo; static const g_fhgAacEncoderInfo;

View File

@ -125,6 +125,11 @@ class QAACEncoderInfo : public AbstractEncoderInfo
static const char* s_extension = "mp4"; static const char* s_extension = "mp4";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return true;
}
} }
static const g_qaacEncoderInfo; static const g_qaacEncoderInfo;
@ -187,6 +192,12 @@ bool QAACEncoder::encode(const QString &sourceFile, const AudioFileModel_MetaInf
break; 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(!m_configCustomParams.isEmpty()) args << m_configCustomParams.split(" ", QString::SkipEmptyParts);
if(!metaInfo.title().isEmpty()) args << "--title" << cleanTag(metaInfo.title()); if(!metaInfo.title().isEmpty()) args << "--title" << cleanTag(metaInfo.title());

View File

@ -113,6 +113,11 @@ class AC3EncoderInfo : public AbstractEncoderInfo
static const char* s_extension = "ac3"; static const char* s_extension = "ac3";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return false;
}
} }
static const g_aftenEncoderInfo; static const g_aftenEncoderInfo;

View File

@ -33,6 +33,7 @@ AbstractEncoder::AbstractEncoder(void)
m_configBitrate = 0; m_configBitrate = 0;
m_configRCMode = 0; m_configRCMode = 0;
m_configCustomParams.clear(); m_configCustomParams.clear();
m_configSamplingRate = 0;
} }
AbstractEncoder::~AbstractEncoder(void) AbstractEncoder::~AbstractEncoder(void)
@ -43,9 +44,38 @@ AbstractEncoder::~AbstractEncoder(void)
* Setters * Setters
*/ */
void AbstractEncoder::setBitrate(int bitrate) { m_configBitrate = qMax(0, bitrate); } void AbstractEncoder::setRCMode(const int &mode)
void AbstractEncoder::setRCMode(int mode) { m_configRCMode = qMax(0, mode); } {
void AbstractEncoder::setCustomParams(const QString &customParams) { m_configCustomParams = customParams.trimmed(); } 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 * Default implementation
@ -75,6 +105,7 @@ const bool AbstractEncoder::needsTimingInfo(void)
return false; return false;
} }
/* /*
* Helper functions * Helper functions
*/ */

View File

@ -49,6 +49,7 @@ public:
value_type_t; value_type_t;
virtual bool isModeSupported(int mode) const = 0; //Returns whether the encoder does support the current RC mode 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 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 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 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); virtual const bool needsTimingInfo(void);
//Common setter methods //Common setter methods
virtual void setBitrate(int bitrate); virtual void setBitrate(const int &bitrate);
virtual void setRCMode(int mode); virtual void setRCMode(const int &mode);
virtual void setSamplingRate(const int &value);
virtual void setCustomParams(const QString &customParams); virtual void setCustomParams(const QString &customParams);
//Encoder info //Encoder info
@ -88,6 +90,7 @@ public:
protected: protected:
int m_configBitrate; //Bitrate *or* VBR-quality-level int m_configBitrate; //Bitrate *or* VBR-quality-level
int m_configRCMode; //Rate-control mode int m_configRCMode; //Rate-control mode
int m_configSamplingRate; //Target sampling rate
QString m_configCustomParams; //Custom parameters, if any QString m_configCustomParams; //Custom parameters, if any
//Helper functions //Helper functions

View File

@ -115,6 +115,11 @@ class DCAEncoderInfo : public AbstractEncoderInfo
static const char* s_extension = "dts"; static const char* s_extension = "dts";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return false;
}
} }
static const g_dcaEncoderInfo; static const g_dcaEncoderInfo;

View File

@ -109,6 +109,11 @@ public:
static const char* s_extension = "flac"; static const char* s_extension = "flac";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return false;
}
} }
static const g_flacEncoderInfo; static const g_flacEncoderInfo;

View File

@ -109,6 +109,11 @@ class MACEncoderInfo : public AbstractEncoderInfo
static const char* s_extension = "ape"; static const char* s_extension = "ape";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return false;
}
} }
static const g_macEncoderInfo; static const g_macEncoderInfo;

View File

@ -114,6 +114,11 @@ class MP3EncoderInfo : public AbstractEncoderInfo
static const char* s_extension = "mp3"; static const char* s_extension = "mp3";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return true;
}
} }
static const g_mp3EncoderInfo; static const g_mp3EncoderInfo;
@ -334,11 +339,6 @@ void MP3Encoder::setBitrateLimits(int minimumBitrate, int maximumBitrate)
m_configBitrateMaximum = maximumBitrate; m_configBitrateMaximum = maximumBitrate;
} }
void MP3Encoder::setSamplingRate(int value)
{
m_configSamplingRate = value;
}
void MP3Encoder::setChannelMode(int value) void MP3Encoder::setChannelMode(int value)
{ {
m_configChannelMode = value; m_configChannelMode = value;

View File

@ -41,7 +41,6 @@ public:
//Advanced options //Advanced options
virtual void setAlgoQuality(int value); virtual void setAlgoQuality(int value);
virtual void setBitrateLimits(int minimumBitrate, int maximumBitrate); virtual void setBitrateLimits(int minimumBitrate, int maximumBitrate);
virtual void setSamplingRate(int value);
virtual void setChannelMode(int value); virtual void setChannelMode(int value);
//Encoder info //Encoder info
@ -53,7 +52,6 @@ private:
int m_algorithmQuality; int m_algorithmQuality;
int m_configBitrateMaximum; int m_configBitrateMaximum;
int m_configBitrateMinimum; int m_configBitrateMinimum;
int m_configSamplingRate;
int m_configChannelMode; int m_configChannelMode;
int clipBitrate(int bitrate); int clipBitrate(int bitrate);

View File

@ -110,6 +110,11 @@ class OpusEncoderInfo : public AbstractEncoderInfo
static const char* s_extension = "opus"; static const char* s_extension = "opus";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return false;
}
} }
static const g_opusEncoderInfo; static const g_opusEncoderInfo;

View File

@ -111,6 +111,11 @@ class VorbisEncoderInfo : public AbstractEncoderInfo
static const char* s_extension = "ogg"; static const char* s_extension = "ogg";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return true;
}
} }
static const g_vorbisEncoderInfo; static const g_vorbisEncoderInfo;
@ -275,11 +280,6 @@ void VorbisEncoder::setBitrateLimits(int minimumBitrate, int maximumBitrate)
m_configBitrateMaximum = maximumBitrate; m_configBitrateMaximum = maximumBitrate;
} }
void VorbisEncoder::setSamplingRate(int value)
{
m_configSamplingRate = value;
}
const AbstractEncoderInfo *VorbisEncoder::getEncoderInfo(void) const AbstractEncoderInfo *VorbisEncoder::getEncoderInfo(void)
{ {
return &g_vorbisEncoderInfo; return &g_vorbisEncoderInfo;

View File

@ -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 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 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 setBitrateLimits(int minimumBitrate, int maximumBitrate);
virtual void setSamplingRate(int value);
//Encoder info //Encoder info
virtual const AbstractEncoderInfo *toEncoderInfo(void) const { return getEncoderInfo(); } virtual const AbstractEncoderInfo *toEncoderInfo(void) const { return getEncoderInfo(); }
@ -47,5 +46,4 @@ private:
const QString m_binary; const QString m_binary;
int m_configBitrateMaximum; int m_configBitrateMaximum;
int m_configBitrateMinimum; int m_configBitrateMinimum;
int m_configSamplingRate;
}; };

View File

@ -111,6 +111,11 @@ public:
static const char* s_extension = "wav"; static const char* s_extension = "wav";
return s_extension; return s_extension;
} }
virtual bool isResamplingSupported(void) const
{
return false;
}
} }
static const g_waveEncoderInfo; static const g_waveEncoderInfo;

View File

@ -45,11 +45,10 @@
// Create encoder instance // 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; int rcMode = -1;
AbstractEncoder *encoder = NULL; AbstractEncoder *encoder = NULL;
*nativeResampling = false;
//Create new encoder instance and apply encoder-specific settings //Create new encoder instance and apply encoder-specific settings
switch(encoderId) switch(encoderId)
@ -57,17 +56,12 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett
/*-------- MP3Encoder /*--------*/ /*-------- MP3Encoder /*--------*/
case SettingsModel::MP3Encoder: case SettingsModel::MP3Encoder:
{ {
MP3Encoder *mp3Encoder = new MP3Encoder(); MP3Encoder *const mp3Encoder = new MP3Encoder();
mp3Encoder->setAlgoQuality(settings->lameAlgoQuality()); mp3Encoder->setAlgoQuality(settings->lameAlgoQuality());
if(settings->bitrateManagementEnabled()) if(settings->bitrateManagementEnabled())
{ {
mp3Encoder->setBitrateLimits(settings->bitrateManagementMinRate(), settings->bitrateManagementMaxRate()); mp3Encoder->setBitrateLimits(settings->bitrateManagementMinRate(), settings->bitrateManagementMaxRate());
} }
if(settings->samplingRate() > 0)
{
mp3Encoder->setSamplingRate(SettingsModel::samplingRates[settings->samplingRate()]);
*nativeResampling = true;
}
mp3Encoder->setChannelMode(settings->lameChannelMode()); mp3Encoder->setChannelMode(settings->lameChannelMode());
encoder = mp3Encoder; encoder = mp3Encoder;
} }
@ -75,16 +69,11 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett
/*-------- VorbisEncoder /*--------*/ /*-------- VorbisEncoder /*--------*/
case SettingsModel::VorbisEncoder: case SettingsModel::VorbisEncoder:
{ {
VorbisEncoder *vorbisEncoder = new VorbisEncoder(); VorbisEncoder *const vorbisEncoder = new VorbisEncoder();
if(settings->bitrateManagementEnabled()) if(settings->bitrateManagementEnabled())
{ {
vorbisEncoder->setBitrateLimits(settings->bitrateManagementMinRate(), settings->bitrateManagementMaxRate()); vorbisEncoder->setBitrateLimits(settings->bitrateManagementMinRate(), settings->bitrateManagementMaxRate());
} }
if(settings->samplingRate() > 0)
{
vorbisEncoder->setSamplingRate(SettingsModel::samplingRates[settings->samplingRate()]);
*nativeResampling = true;
}
encoder = vorbisEncoder; encoder = vorbisEncoder;
} }
break; break;
@ -95,28 +84,28 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett
{ {
case SettingsModel::AAC_ENCODER_QAAC: case SettingsModel::AAC_ENCODER_QAAC:
{ {
QAACEncoder *aacEncoder = new QAACEncoder(); QAACEncoder *const aacEncoder = new QAACEncoder();
aacEncoder->setProfile(settings->aacEncProfile()); aacEncoder->setProfile(settings->aacEncProfile());
encoder = aacEncoder; encoder = aacEncoder;
} }
break; break;
case SettingsModel::AAC_ENCODER_FHG: case SettingsModel::AAC_ENCODER_FHG:
{ {
FHGAACEncoder *aacEncoder = new FHGAACEncoder(); FHGAACEncoder *const aacEncoder = new FHGAACEncoder();
aacEncoder->setProfile(settings->aacEncProfile()); aacEncoder->setProfile(settings->aacEncProfile());
encoder = aacEncoder; encoder = aacEncoder;
} }
break; break;
case SettingsModel::AAC_ENCODER_FDK: case SettingsModel::AAC_ENCODER_FDK:
{ {
FDKAACEncoder *aacEncoder = new FDKAACEncoder(); FDKAACEncoder *const aacEncoder = new FDKAACEncoder();
aacEncoder->setProfile(settings->aacEncProfile()); aacEncoder->setProfile(settings->aacEncProfile());
encoder = aacEncoder; encoder = aacEncoder;
} }
break; break;
case SettingsModel::AAC_ENCODER_NERO: case SettingsModel::AAC_ENCODER_NERO:
{ {
AACEncoder *aacEncoder = new AACEncoder(); AACEncoder *const aacEncoder = new AACEncoder();
aacEncoder->setEnable2Pass(settings->neroAACEnable2Pass()); aacEncoder->setEnable2Pass(settings->neroAACEnable2Pass());
aacEncoder->setProfile(settings->aacEncProfile()); aacEncoder->setProfile(settings->aacEncProfile());
encoder = aacEncoder; encoder = aacEncoder;
@ -131,7 +120,7 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett
/*-------- AC3Encoder /*--------*/ /*-------- AC3Encoder /*--------*/
case SettingsModel::AC3Encoder: case SettingsModel::AC3Encoder:
{ {
AC3Encoder *ac3Encoder = new AC3Encoder(); AC3Encoder *const ac3Encoder = new AC3Encoder();
ac3Encoder->setAudioCodingMode(settings->aftenAudioCodingMode()); ac3Encoder->setAudioCodingMode(settings->aftenAudioCodingMode());
ac3Encoder->setDynamicRangeCompression(settings->aftenDynamicRangeCompression()); ac3Encoder->setDynamicRangeCompression(settings->aftenDynamicRangeCompression());
ac3Encoder->setExponentSearchSize(settings->aftenExponentSearchSize()); ac3Encoder->setExponentSearchSize(settings->aftenExponentSearchSize());
@ -142,14 +131,14 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett
/*-------- FLACEncoder /*--------*/ /*-------- FLACEncoder /*--------*/
case SettingsModel::FLACEncoder: case SettingsModel::FLACEncoder:
{ {
FLACEncoder *flacEncoder = new FLACEncoder(); FLACEncoder *const flacEncoder = new FLACEncoder();
encoder = flacEncoder; encoder = flacEncoder;
} }
break; break;
/*-------- OpusEncoder --------*/ /*-------- OpusEncoder --------*/
case SettingsModel::OpusEncoder: case SettingsModel::OpusEncoder:
{ {
OpusEncoder *opusEncoder = new OpusEncoder(); OpusEncoder *const opusEncoder = new OpusEncoder();
opusEncoder->setOptimizeFor(settings->opusOptimizeFor()); opusEncoder->setOptimizeFor(settings->opusOptimizeFor());
opusEncoder->setEncodeComplexity(settings->opusComplexity()); opusEncoder->setEncodeComplexity(settings->opusComplexity());
opusEncoder->setFrameSize(settings->opusFramesize()); opusEncoder->setFrameSize(settings->opusFramesize());
@ -159,21 +148,21 @@ AbstractEncoder *EncoderRegistry::createInstance(const int encoderId, const Sett
/*-------- DCAEncoder --------*/ /*-------- DCAEncoder --------*/
case SettingsModel::DCAEncoder: case SettingsModel::DCAEncoder:
{ {
DCAEncoder *dcaEncoder = new DCAEncoder(); DCAEncoder *const dcaEncoder = new DCAEncoder();
encoder = dcaEncoder; encoder = dcaEncoder;
} }
break; break;
/*-------- MACEncoder --------*/ /*-------- MACEncoder --------*/
case SettingsModel::MACEncoder: case SettingsModel::MACEncoder:
{ {
MACEncoder *macEncoder = new MACEncoder(); MACEncoder *const macEncoder = new MACEncoder();
encoder = macEncoder; encoder = macEncoder;
} }
break; break;
/*-------- PCMEncoder --------*/ /*-------- PCMEncoder --------*/
case SettingsModel::PCMEncoder: case SettingsModel::PCMEncoder:
{ {
WaveEncoder *waveEncoder = new WaveEncoder(); WaveEncoder *const waveEncoder = new WaveEncoder();
encoder = waveEncoder; encoder = waveEncoder;
} }
break; break;

View File

@ -34,7 +34,7 @@ class EncoderRegistry : public QObject
Q_OBJECT Q_OBJECT
public: 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 const AbstractEncoderInfo *getEncoderInfo(const int encoderId);
static void saveEncoderMode(SettingsModel *settings, const int encoderId, const int rcMode); static void saveEncoderMode(SettingsModel *settings, const int encoderId, const int rcMode);