Added optional support for the QAAC encoder. Requires QuickTime v7.7.1 (or later) and the QAAC front-end.
This commit is contained in:
parent
346985876f
commit
da5dfdc85e
@ -272,6 +272,7 @@ del "$(TargetDir)imageformats\q???d4.dll"
|
|||||||
<ClCompile Include="src\Dialog_WorkingBanner.cpp" />
|
<ClCompile Include="src\Dialog_WorkingBanner.cpp" />
|
||||||
<ClCompile Include="src\Encoder_AAC.cpp" />
|
<ClCompile Include="src\Encoder_AAC.cpp" />
|
||||||
<ClCompile Include="src\Encoder_AAC_FHG.cpp" />
|
<ClCompile Include="src\Encoder_AAC_FHG.cpp" />
|
||||||
|
<ClCompile Include="src\Encoder_AAC_QAAC.cpp" />
|
||||||
<ClCompile Include="src\Encoder_Abstract.cpp" />
|
<ClCompile Include="src\Encoder_Abstract.cpp" />
|
||||||
<ClCompile Include="src\Encoder_AC3.cpp" />
|
<ClCompile Include="src\Encoder_AC3.cpp" />
|
||||||
<ClCompile Include="src\Encoder_FLAC.cpp" />
|
<ClCompile Include="src\Encoder_FLAC.cpp" />
|
||||||
@ -322,6 +323,7 @@ del "$(TargetDir)imageformats\q???d4.dll"
|
|||||||
<ClCompile Include="tmp\MOC_Dialog_WorkingBanner.cpp" />
|
<ClCompile Include="tmp\MOC_Dialog_WorkingBanner.cpp" />
|
||||||
<ClCompile Include="tmp\MOC_Encoder_AAC.cpp" />
|
<ClCompile Include="tmp\MOC_Encoder_AAC.cpp" />
|
||||||
<ClCompile Include="tmp\MOC_Encoder_AAC_FHG.cpp" />
|
<ClCompile Include="tmp\MOC_Encoder_AAC_FHG.cpp" />
|
||||||
|
<ClCompile Include="tmp\MOC_Encoder_AAC_QAAC.cpp" />
|
||||||
<ClCompile Include="tmp\MOC_Encoder_Abstract.cpp" />
|
<ClCompile Include="tmp\MOC_Encoder_Abstract.cpp" />
|
||||||
<ClCompile Include="tmp\MOC_Encoder_AC3.cpp" />
|
<ClCompile Include="tmp\MOC_Encoder_AC3.cpp" />
|
||||||
<ClCompile Include="tmp\MOC_Encoder_FLAC.cpp" />
|
<ClCompile Include="tmp\MOC_Encoder_FLAC.cpp" />
|
||||||
@ -436,6 +438,17 @@ del "$(TargetDir)imageformats\q???d4.dll"
|
|||||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release_Static|Win32'">$(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)</Outputs>
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release_Static|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|Win32'">$(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)</Outputs>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="src\Encoder_AAC_QAAC.h">
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_%(Filename).cpp" "%(FullPath)"</Command>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp"</Message>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)</Outputs>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)</Outputs>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release_Static|Win32'">$(SolutionDir)tmp\MOC_%(Filename).cpp;%(Outputs)</Outputs>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp"</Message>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Release_Static|Win32'">MOC "$(SolutionDir)tmp\MOC_%(Filename).cpp"</Message>
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|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>
|
||||||
|
</CustomBuild>
|
||||||
<ClInclude Include="src\Tools.h" />
|
<ClInclude Include="src\Tools.h" />
|
||||||
<ClInclude Include="tmp\UIC_CueSheetImport.h" />
|
<ClInclude Include="tmp\UIC_CueSheetImport.h" />
|
||||||
<ClInclude Include="tmp\UIC_DropBox.h" />
|
<ClInclude Include="tmp\UIC_DropBox.h" />
|
||||||
|
@ -334,6 +334,12 @@
|
|||||||
<ClCompile Include="tmp\MOC_Thread_RAMObserver.cpp">
|
<ClCompile Include="tmp\MOC_Thread_RAMObserver.cpp">
|
||||||
<Filter>Generated Files\MOC</Filter>
|
<Filter>Generated Files\MOC</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Encoder_AAC_QAAC.cpp">
|
||||||
|
<Filter>Source Files\Encoders</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="tmp\MOC_Encoder_AAC_QAAC.cpp">
|
||||||
|
<Filter>Generated Files\MOC</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\Config.h">
|
<ClInclude Include="src\Config.h">
|
||||||
@ -626,6 +632,9 @@
|
|||||||
<CustomBuild Include="src\Thread_RAMObserver.h">
|
<CustomBuild Include="src\Thread_RAMObserver.h">
|
||||||
<Filter>Header Files\Threads</Filter>
|
<Filter>Header Files\Threads</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="src\Encoder_AAC_QAAC.h">
|
||||||
|
<Filter>Header Files\Encoders</Filter>
|
||||||
|
</CustomBuild>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="res\MainIcon.ico" />
|
<None Include="res\MainIcon.ico" />
|
||||||
|
@ -17,7 +17,9 @@ a:visited { color: #0000EE; }
|
|||||||
<h3>LameXP - Version History</h3><br>
|
<h3>LameXP - Version History</h3><br>
|
||||||
|
|
||||||
<a name="4.04"></a>Changes between v4.03 and v4.04:<br><ul>
|
<a name="4.04"></a>Changes between v4.03 and v4.04:<br><ul>
|
||||||
|
<li>Added support for the QAAC Encoder, requires QuickTime v7.7.1 or newer (see <a href="FAQ.html#71a113b0" target="_blank">FAQ doc</a> for details)
|
||||||
<li>Updated LAME encoder to v3.99.2 Final (2011-11-18), compiled with ICL 12.1.7 and MSVC 10.0 (<a href="http://lame.cvs.sourceforge.net/viewvc/lame/lame/doc/html/history.html?revision=1.134" target="_blank">details</a>)
|
<li>Updated LAME encoder to v3.99.2 Final (2011-11-18), compiled with ICL 12.1.7 and MSVC 10.0 (<a href="http://lame.cvs.sourceforge.net/viewvc/lame/lame/doc/html/history.html?revision=1.134" target="_blank">details</a>)
|
||||||
|
<li>Updated MediaInfo to v0.7.51+ (2011-11-19), compiled with ICL 12.1.6 and MSVC 10.0
|
||||||
<li>Implemented coalescing of update signals in order to reduce the CPU usage of the LameXP process
|
<li>Implemented coalescing of update signals in order to reduce the CPU usage of the LameXP process
|
||||||
</ul><br>
|
</ul><br>
|
||||||
|
|
||||||
|
13
doc/FAQ.html
13
doc/FAQ.html
@ -304,6 +304,7 @@ the same directory where your LameXP executable ('LameXP.exe') is located. For u
|
|||||||
use any suitable archiver, such as <a href="http://rarlabs.com/download.htm" target="_blank">WinRAR</a> or <a href="http://sevenzip.sourceforge.net/" target="_blank">7-Zip</a>. Once the required Nero encoder binaries are located in<br>
|
use any suitable archiver, such as <a href="http://rarlabs.com/download.htm" target="_blank">WinRAR</a> or <a href="http://sevenzip.sourceforge.net/" target="_blank">7-Zip</a>. Once the required Nero encoder binaries are located in<br>
|
||||||
the LameXP directory, the AAC encoding option should be "enabled" on the next startup of LameXP.<br>
|
the LameXP directory, the AAC encoding option should be "enabled" on the next startup of LameXP.<br>
|
||||||
<br>
|
<br>
|
||||||
|
<br>
|
||||||
Optionally LameXP also supports the FHG AAC Encoder now. Just like the Nero encoder, the FHG encoder can NOT<br>
|
Optionally LameXP also supports the FHG AAC Encoder now. Just like the Nero encoder, the FHG encoder can NOT<br>
|
||||||
be redistributed along with LameXP. However the FHG AAC Encoder is included with Winamp v5.62, which is<br>
|
be redistributed along with LameXP. However the FHG AAC Encoder is included with Winamp v5.62, which is<br>
|
||||||
available as a free download (you don't need to buy the "Pro" version!) from the official Winamp web-site at:<br><ul>
|
available as a free download (you don't need to buy the "Pro" version!) from the official Winamp web-site at:<br><ul>
|
||||||
@ -320,7 +321,17 @@ In order to enable the FHG AAC Encoder support you will also need the 'FHG AAC E
|
|||||||
<li><a href="http://uploaded.to/file/0h0c7qf6" target="_blank">http://uploaded.to/file/0h0c7qf6</a></ul>
|
<li><a href="http://uploaded.to/file/0h0c7qf6" target="_blank">http://uploaded.to/file/0h0c7qf6</a></ul>
|
||||||
<br>
|
<br>
|
||||||
Please follow the install instructions that are included with the 'FHG AAC Encoder Add-in' download package!<br>
|
Please follow the install instructions that are included with the 'FHG AAC Encoder Add-in' download package!<br>
|
||||||
Note that you do NOT need to install the Add-in, if you only want to use the Nero AAC Encoder.<br><br>
|
Note that you do NOT need to install the Add-in, if you only want to use the Nero AAC Encoder.<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
As a third option, LameXP supports the QAAC encoder, i.e. the AAC encoder of QuickTime/iTunes. Just like the<br>
|
||||||
|
other two AAC encoders, the QAAC encoder can NOT be redistributed along with LameXP. Thus if you want to use<br>
|
||||||
|
the QAAC encoder, then you have to install QuickTime v7.7.1 (or newer). Alternatively iTunes v10.5 (or newer)<br>
|
||||||
|
can be installed. Both, QuickTime and iTunes, can be <a href="http://www.apple.com/quicktime/download/" target="_blank">downloaded for free</a> from the official Apple web-site.<br>
|
||||||
|
<br>
|
||||||
|
In addition to installing QuickTime/iTunes, you must download the QAAC encoder from <a href="http://sites.google.com/site/qaacpage/" target="_blank">this</a> web-site. Then put<br>
|
||||||
|
'qaac.exe' and 'libsoxrate.dll' as well as 'msvcr100.dll' and 'msvcp100.dll' into the same directory where<br>
|
||||||
|
your LameXP executable ('LameXP.exe') is located. QAAC will then be "enabled" on the next startup of LameXP.<br><br>
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -29,8 +29,8 @@
|
|||||||
#define VER_LAMEXP_MINOR_HI 0
|
#define VER_LAMEXP_MINOR_HI 0
|
||||||
#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 2
|
||||||
#define VER_LAMEXP_BUILD 781
|
#define VER_LAMEXP_BUILD 782
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Tools versions
|
// Tools versions
|
||||||
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
#define VER_LAMEXP_TOOL_NEROAAC 1540
|
#define VER_LAMEXP_TOOL_NEROAAC 1540
|
||||||
#define VER_LAMEXP_TOOL_FHGAACENC 20110822
|
#define VER_LAMEXP_TOOL_FHGAACENC 20110822
|
||||||
|
#define VER_LAMEXP_TOOL_QAAC 104
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Helper macros (aka: having fun with the C pre-processor)
|
// Helper macros (aka: having fun with the C pre-processor)
|
||||||
|
@ -90,6 +90,7 @@ MainWindow::MainWindow(FileListModel *fileListModel, AudioFileModel *metaInfo, S
|
|||||||
m_settings(settingsModel),
|
m_settings(settingsModel),
|
||||||
m_neroEncoderAvailable(lamexp_check_tool("neroAacEnc.exe") && lamexp_check_tool("neroAacDec.exe") && lamexp_check_tool("neroAacTag.exe")),
|
m_neroEncoderAvailable(lamexp_check_tool("neroAacEnc.exe") && lamexp_check_tool("neroAacDec.exe") && lamexp_check_tool("neroAacTag.exe")),
|
||||||
m_fhgEncoderAvailable(lamexp_check_tool("fhgaacenc.exe") && lamexp_check_tool("enc_fhgaac.dll") && lamexp_check_tool("nsutil.dll") && lamexp_check_tool("libmp4v2.dll")),
|
m_fhgEncoderAvailable(lamexp_check_tool("fhgaacenc.exe") && lamexp_check_tool("enc_fhgaac.dll") && lamexp_check_tool("nsutil.dll") && lamexp_check_tool("libmp4v2.dll")),
|
||||||
|
m_qaacEncoderAvailable(lamexp_check_tool("qaac.exe") && lamexp_check_tool("libsoxrate.dll") && lamexp_check_tool("msvcp100.dll") && lamexp_check_tool("msvcr100.dll")),
|
||||||
m_accepted(false),
|
m_accepted(false),
|
||||||
m_firstTimeShown(true),
|
m_firstTimeShown(true),
|
||||||
m_OutputFolderViewInitialized(false)
|
m_OutputFolderViewInitialized(false)
|
||||||
@ -207,10 +208,10 @@ MainWindow::MainWindow(FileListModel *fileListModel, AudioFileModel *metaInfo, S
|
|||||||
m_modeButtonGroup->addButton(radioButtonModeQuality, SettingsModel::VBRMode);
|
m_modeButtonGroup->addButton(radioButtonModeQuality, SettingsModel::VBRMode);
|
||||||
m_modeButtonGroup->addButton(radioButtonModeAverageBitrate, SettingsModel::ABRMode);
|
m_modeButtonGroup->addButton(radioButtonModeAverageBitrate, SettingsModel::ABRMode);
|
||||||
m_modeButtonGroup->addButton(radioButtonConstBitrate, SettingsModel::CBRMode);
|
m_modeButtonGroup->addButton(radioButtonConstBitrate, SettingsModel::CBRMode);
|
||||||
radioButtonEncoderAAC->setEnabled(m_neroEncoderAvailable || m_fhgEncoderAvailable);
|
radioButtonEncoderAAC->setEnabled(m_neroEncoderAvailable || m_fhgEncoderAvailable || m_qaacEncoderAvailable);
|
||||||
radioButtonEncoderMP3->setChecked(m_settings->compressionEncoder() == SettingsModel::MP3Encoder);
|
radioButtonEncoderMP3->setChecked(m_settings->compressionEncoder() == SettingsModel::MP3Encoder);
|
||||||
radioButtonEncoderVorbis->setChecked(m_settings->compressionEncoder() == SettingsModel::VorbisEncoder);
|
radioButtonEncoderVorbis->setChecked(m_settings->compressionEncoder() == SettingsModel::VorbisEncoder);
|
||||||
radioButtonEncoderAAC->setChecked((m_settings->compressionEncoder() == SettingsModel::AACEncoder) && (m_neroEncoderAvailable || m_fhgEncoderAvailable));
|
radioButtonEncoderAAC->setChecked((m_settings->compressionEncoder() == SettingsModel::AACEncoder) && (m_neroEncoderAvailable || m_fhgEncoderAvailable || m_qaacEncoderAvailable));
|
||||||
radioButtonEncoderAC3->setChecked(m_settings->compressionEncoder() == SettingsModel::AC3Encoder);
|
radioButtonEncoderAC3->setChecked(m_settings->compressionEncoder() == SettingsModel::AC3Encoder);
|
||||||
radioButtonEncoderFLAC->setChecked(m_settings->compressionEncoder() == SettingsModel::FLACEncoder);
|
radioButtonEncoderFLAC->setChecked(m_settings->compressionEncoder() == SettingsModel::FLACEncoder);
|
||||||
radioButtonEncoderPCM->setChecked(m_settings->compressionEncoder() == SettingsModel::PCMEncoder);
|
radioButtonEncoderPCM->setChecked(m_settings->compressionEncoder() == SettingsModel::PCMEncoder);
|
||||||
@ -246,7 +247,7 @@ MainWindow::MainWindow(FileListModel *fileListModel, AudioFileModel *metaInfo, S
|
|||||||
while(checkBoxUseSystemTempFolder->isChecked() == m_settings->customTempPathEnabled()) checkBoxUseSystemTempFolder->click();
|
while(checkBoxUseSystemTempFolder->isChecked() == m_settings->customTempPathEnabled()) checkBoxUseSystemTempFolder->click();
|
||||||
while(checkBoxRenameOutput->isChecked() != m_settings->renameOutputFilesEnabled()) checkBoxRenameOutput->click();
|
while(checkBoxRenameOutput->isChecked() != m_settings->renameOutputFilesEnabled()) checkBoxRenameOutput->click();
|
||||||
while(checkBoxForceStereoDownmix->isChecked() != m_settings->forceStereoDownmix()) checkBoxForceStereoDownmix->click();
|
while(checkBoxForceStereoDownmix->isChecked() != m_settings->forceStereoDownmix()) checkBoxForceStereoDownmix->click();
|
||||||
checkBoxNeroAAC2PassMode->setEnabled(!m_fhgEncoderAvailable);
|
checkBoxNeroAAC2PassMode->setEnabled(!(m_fhgEncoderAvailable || m_qaacEncoderAvailable));
|
||||||
lineEditCustomParamLAME->setText(m_settings->customParametersLAME());
|
lineEditCustomParamLAME->setText(m_settings->customParametersLAME());
|
||||||
lineEditCustomParamOggEnc->setText(m_settings->customParametersOggEnc());
|
lineEditCustomParamOggEnc->setText(m_settings->customParametersOggEnc());
|
||||||
lineEditCustomParamNeroAAC->setText(m_settings->customParametersAacEnc());
|
lineEditCustomParamNeroAAC->setText(m_settings->customParametersAacEnc());
|
||||||
@ -1042,7 +1043,7 @@ void MainWindow::windowShown(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(m_settings->neroAacNotificationsEnabled() && (!m_fhgEncoderAvailable))
|
if(m_settings->neroAacNotificationsEnabled() && (!(m_fhgEncoderAvailable || m_qaacEncoderAvailable)))
|
||||||
{
|
{
|
||||||
QString appPath = QDir(QCoreApplication::applicationDirPath()).canonicalPath();
|
QString appPath = QDir(QCoreApplication::applicationDirPath()).canonicalPath();
|
||||||
if(appPath.isEmpty()) appPath = QCoreApplication::applicationDirPath();
|
if(appPath.isEmpty()) appPath = QCoreApplication::applicationDirPath();
|
||||||
|
@ -160,6 +160,7 @@ private:
|
|||||||
|
|
||||||
const bool m_neroEncoderAvailable;
|
const bool m_neroEncoderAvailable;
|
||||||
const bool m_fhgEncoderAvailable;
|
const bool m_fhgEncoderAvailable;
|
||||||
|
const bool m_qaacEncoderAvailable;
|
||||||
|
|
||||||
WorkingBanner *m_banner;
|
WorkingBanner *m_banner;
|
||||||
QStringList *m_delayedFileList;
|
QStringList *m_delayedFileList;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "Encoder_Vorbis.h"
|
#include "Encoder_Vorbis.h"
|
||||||
#include "Encoder_AAC.h"
|
#include "Encoder_AAC.h"
|
||||||
#include "Encoder_AAC_FHG.h"
|
#include "Encoder_AAC_FHG.h"
|
||||||
|
#include "Encoder_AAC_QAAC.h"
|
||||||
#include "Encoder_AC3.h"
|
#include "Encoder_AC3.h"
|
||||||
#include "Encoder_FLAC.h"
|
#include "Encoder_FLAC.h"
|
||||||
#include "Encoder_Wave.h"
|
#include "Encoder_Wave.h"
|
||||||
@ -660,7 +661,16 @@ void ProcessingDialog::startNextJob(void)
|
|||||||
break;
|
break;
|
||||||
case SettingsModel::AACEncoder:
|
case SettingsModel::AACEncoder:
|
||||||
{
|
{
|
||||||
if(lamexp_check_tool("fhgaacenc.exe") && lamexp_check_tool("enc_fhgaac.dll"))
|
if(lamexp_check_tool("qaac.exe") && lamexp_check_tool("libsoxrate.dll"))
|
||||||
|
{
|
||||||
|
QAACEncoder *aacEncoder = new QAACEncoder();
|
||||||
|
aacEncoder->setBitrate(m_settings->compressionBitrate());
|
||||||
|
aacEncoder->setRCMode(m_settings->compressionRCMode());
|
||||||
|
aacEncoder->setProfile(m_settings->aacEncProfile());
|
||||||
|
aacEncoder->setCustomParams(m_settings->customParametersAacEnc());
|
||||||
|
encoder = aacEncoder;
|
||||||
|
}
|
||||||
|
else if(lamexp_check_tool("fhgaacenc.exe") && lamexp_check_tool("enc_fhgaac.dll"))
|
||||||
{
|
{
|
||||||
FHGAACEncoder *aacEncoder = new FHGAACEncoder();
|
FHGAACEncoder *aacEncoder = new FHGAACEncoder();
|
||||||
aacEncoder->setBitrate(m_settings->compressionBitrate());
|
aacEncoder->setBitrate(m_settings->compressionBitrate());
|
||||||
|
@ -54,7 +54,7 @@ bool AACEncoder::encode(const QString &sourceFile, const AudioFileModel &metaInf
|
|||||||
switch(m_configRCMode)
|
switch(m_configRCMode)
|
||||||
{
|
{
|
||||||
case SettingsModel::VBRMode:
|
case SettingsModel::VBRMode:
|
||||||
args << "-q" << QString().sprintf("%.2f", qMin(1.0, qMax(0.0, static_cast<double>(m_configBitrate * 5) / 100.0)));
|
args << "-q" << QString().sprintf("%.2f", qBound(0.0, static_cast<double>(m_configBitrate * 5) / 100.0, 1.0));
|
||||||
break;
|
break;
|
||||||
case SettingsModel::ABRMode:
|
case SettingsModel::ABRMode:
|
||||||
args << "-br" << QString::number(qMax(32, qMin(500, (m_configBitrate * 8))) * 1000);
|
args << "-br" << QString::number(qMax(32, qMin(500, (m_configBitrate * 8))) * 1000);
|
||||||
|
184
src/Encoder_AAC_QAAC.cpp
Normal file
184
src/Encoder_AAC_QAAC.cpp
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// LameXP - Audio Encoder Front-End
|
||||||
|
// Copyright (C) 2004-2011 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 "Encoder_AAC_QAAC.h"
|
||||||
|
|
||||||
|
#include "Global.h"
|
||||||
|
#include "Model_Settings.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
QAACEncoder::QAACEncoder(void)
|
||||||
|
:
|
||||||
|
m_binary_enc(lamexp_lookup_tool("qaac.exe")),
|
||||||
|
m_binary_dll(lamexp_lookup_tool("libsoxrate.dll"))
|
||||||
|
{
|
||||||
|
if(m_binary_enc.isEmpty() || m_binary_dll.isEmpty())
|
||||||
|
{
|
||||||
|
throw "Error initializing QAAC. Tool 'qaac.exe' is not registred!";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_configProfile = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAACEncoder::~QAACEncoder(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QAACEncoder::encode(const QString &sourceFile, const AudioFileModel &metaInfo, const QString &outputFile, volatile bool *abortFlag)
|
||||||
|
{
|
||||||
|
QProcess process;
|
||||||
|
QStringList args;
|
||||||
|
|
||||||
|
if(m_configRCMode != SettingsModel::VBRMode)
|
||||||
|
{
|
||||||
|
switch(m_configProfile)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
args << "--he"; //Forces use of HE AAC profile (there is no explicit HEv2 switch for QAAC)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(m_configRCMode)
|
||||||
|
{
|
||||||
|
case SettingsModel::CBRMode:
|
||||||
|
args << "--cbr" << QString::number(qBound(32, m_configBitrate * 8, 500));
|
||||||
|
break;
|
||||||
|
case SettingsModel::ABRMode:
|
||||||
|
args << "--abr" << QString::number(qBound(32, m_configBitrate * 8, 500));
|
||||||
|
break;
|
||||||
|
case SettingsModel::VBRMode:
|
||||||
|
args << "--tvbr" << QString::number(qBound(0, qRound((static_cast<double>(m_configBitrate * 5) / 100.0) * 127.0), 127));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw "Bad rate-control mode!";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!m_configCustomParams.isEmpty()) args << m_configCustomParams.split(" ", QString::SkipEmptyParts);
|
||||||
|
|
||||||
|
if(!metaInfo.fileName().isEmpty()) args << "--title" << metaInfo.fileName();
|
||||||
|
if(!metaInfo.fileArtist().isEmpty()) args << "--artist" << metaInfo.fileArtist();
|
||||||
|
if(!metaInfo.fileAlbum().isEmpty()) args << "--album" << metaInfo.fileAlbum();
|
||||||
|
if(!metaInfo.fileGenre().isEmpty()) args << "--genre" << metaInfo.fileGenre();
|
||||||
|
if(!metaInfo.fileComment().isEmpty()) args << "--comment" << metaInfo.fileComment();
|
||||||
|
if(metaInfo.fileYear()) args << "--date" << QString::number(metaInfo.fileYear());
|
||||||
|
if(metaInfo.filePosition()) args << "--track" << QString::number(metaInfo.filePosition());
|
||||||
|
if(!metaInfo.fileCover().isEmpty()) args << "--artwork" << metaInfo.fileCover();
|
||||||
|
|
||||||
|
args << "-o" << QDir::toNativeSeparators(outputFile);
|
||||||
|
args << QDir::toNativeSeparators(sourceFile);
|
||||||
|
|
||||||
|
if(!startProcess(process, m_binary_enc, args))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bTimeout = false;
|
||||||
|
bool bAborted = false;
|
||||||
|
int prevProgress = -1;
|
||||||
|
|
||||||
|
QRegExp regExp("\\[(\\d+)\\.(\\d)%\\]");
|
||||||
|
|
||||||
|
while(process.state() != QProcess::NotRunning)
|
||||||
|
{
|
||||||
|
if(*abortFlag)
|
||||||
|
{
|
||||||
|
process.kill();
|
||||||
|
bAborted = true;
|
||||||
|
emit messageLogged("\nABORTED BY USER !!!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
process.waitForReadyRead(m_processTimeoutInterval);
|
||||||
|
if(!process.bytesAvailable() && process.state() == QProcess::Running)
|
||||||
|
{
|
||||||
|
process.kill();
|
||||||
|
qWarning("QAAC process timed out <-- killing!");
|
||||||
|
emit messageLogged("\nPROCESS TIMEOUT !!!");
|
||||||
|
bTimeout = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while(process.bytesAvailable() > 0)
|
||||||
|
{
|
||||||
|
QByteArray line = process.readLine();
|
||||||
|
QString text = QString::fromUtf8(line.constData()).simplified();
|
||||||
|
if(regExp.lastIndexIn(text) >= 0)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int progress = regExp.cap(1).toInt(&ok);
|
||||||
|
if(ok && (progress > prevProgress))
|
||||||
|
{
|
||||||
|
emit statusUpdated(progress);
|
||||||
|
prevProgress = qMin(progress + 2, 99);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(!text.isEmpty())
|
||||||
|
{
|
||||||
|
emit messageLogged(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.waitForFinished();
|
||||||
|
if(process.state() != QProcess::NotRunning)
|
||||||
|
{
|
||||||
|
process.kill();
|
||||||
|
process.waitForFinished(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit statusUpdated(100);
|
||||||
|
emit messageLogged(QString().sprintf("\nExited with code: 0x%04X", process.exitCode()));
|
||||||
|
|
||||||
|
if(bTimeout || bAborted || process.exitStatus() != QProcess::NormalExit)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QAACEncoder::extension(void)
|
||||||
|
{
|
||||||
|
return "mp4";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QAACEncoder::isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion)
|
||||||
|
{
|
||||||
|
if(containerType.compare("Wave", Qt::CaseInsensitive) == 0)
|
||||||
|
{
|
||||||
|
if(formatType.compare("PCM", Qt::CaseInsensitive) == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QAACEncoder::setProfile(int profile)
|
||||||
|
{
|
||||||
|
m_configProfile = profile;
|
||||||
|
}
|
47
src/Encoder_AAC_QAAC.h
Normal file
47
src/Encoder_AAC_QAAC.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// LameXP - Audio Encoder Front-End
|
||||||
|
// Copyright (C) 2004-2011 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 "Encoder_Abstract.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QAACEncoder : public AbstractEncoder
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QAACEncoder(void);
|
||||||
|
~QAACEncoder(void);
|
||||||
|
|
||||||
|
virtual bool encode(const QString &sourceFile, const AudioFileModel &metaInfo, 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 QString extension(void);
|
||||||
|
|
||||||
|
//Advanced options
|
||||||
|
virtual void setProfile(int profile);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString m_binary_enc;
|
||||||
|
const QString m_binary_dll;
|
||||||
|
int m_configProfile;
|
||||||
|
};
|
@ -169,6 +169,7 @@ static const char *g_lamexp_support_url = "http://forum.doom9.org/showthread.php
|
|||||||
//Tool versions (expected versions!)
|
//Tool versions (expected versions!)
|
||||||
static const unsigned int g_lamexp_toolver_neroaac = VER_LAMEXP_TOOL_NEROAAC;
|
static const unsigned int g_lamexp_toolver_neroaac = VER_LAMEXP_TOOL_NEROAAC;
|
||||||
static const unsigned int g_lamexp_toolver_fhgaacenc = VER_LAMEXP_TOOL_FHGAACENC;
|
static const unsigned int g_lamexp_toolver_fhgaacenc = VER_LAMEXP_TOOL_FHGAACENC;
|
||||||
|
static const unsigned int g_lamexp_toolver_qaacenc = VER_LAMEXP_TOOL_QAAC;
|
||||||
|
|
||||||
//Special folders
|
//Special folders
|
||||||
static QString g_lamexp_temp_folder;
|
static QString g_lamexp_temp_folder;
|
||||||
@ -239,7 +240,7 @@ const char *lamexp_version_compiler(void) { return g_lamexp_version_compiler; }
|
|||||||
const char *lamexp_version_arch(void) { return g_lamexp_version_arch; }
|
const char *lamexp_version_arch(void) { return g_lamexp_version_arch; }
|
||||||
unsigned int lamexp_toolver_neroaac(void) { return g_lamexp_toolver_neroaac; }
|
unsigned int lamexp_toolver_neroaac(void) { return g_lamexp_toolver_neroaac; }
|
||||||
unsigned int lamexp_toolver_fhgaacenc(void) { return g_lamexp_toolver_fhgaacenc; }
|
unsigned int lamexp_toolver_fhgaacenc(void) { return g_lamexp_toolver_fhgaacenc; }
|
||||||
|
unsigned int lamexp_toolver_qaacenc(void) { return g_lamexp_toolver_qaacenc; }
|
||||||
/*
|
/*
|
||||||
* URL getters
|
* URL getters
|
||||||
*/
|
*/
|
||||||
|
@ -81,6 +81,7 @@ const char *lamexp_version_arch(void);
|
|||||||
QDate lamexp_version_expires(void);
|
QDate lamexp_version_expires(void);
|
||||||
unsigned int lamexp_toolver_neroaac(void);
|
unsigned int lamexp_toolver_neroaac(void);
|
||||||
unsigned int lamexp_toolver_fhgaacenc(void);
|
unsigned int lamexp_toolver_fhgaacenc(void);
|
||||||
|
unsigned int lamexp_toolver_qaacenc(void);
|
||||||
const char *lamexp_website_url(void);
|
const char *lamexp_website_url(void);
|
||||||
const char *lamexp_support_url(void);
|
const char *lamexp_support_url(void);
|
||||||
DWORD lamexp_get_os_version(void);
|
DWORD lamexp_get_os_version(void);
|
||||||
|
@ -222,10 +222,13 @@ void SettingsModel::validate(void)
|
|||||||
{
|
{
|
||||||
if(!(lamexp_check_tool("fhgaacenc.exe") && lamexp_check_tool("enc_fhgaac.dll")))
|
if(!(lamexp_check_tool("fhgaacenc.exe") && lamexp_check_tool("enc_fhgaac.dll")))
|
||||||
{
|
{
|
||||||
if(this->compressionEncoder() == SettingsModel::AACEncoder)
|
if(!(lamexp_check_tool("qaac.exe") && lamexp_check_tool("libsoxrate.dll")))
|
||||||
{
|
{
|
||||||
qWarning("AAC encoder selected, but not available any more. Reverting to MP3!");
|
if(this->compressionEncoder() == SettingsModel::AACEncoder)
|
||||||
this->compressionEncoder(SettingsModel::MP3Encoder);
|
{
|
||||||
|
qWarning("AAC encoder selected, but not available any more. Reverting to MP3!");
|
||||||
|
this->compressionEncoder(SettingsModel::MP3Encoder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,11 +202,10 @@ void InitializationThread::run()
|
|||||||
//Register all translations
|
//Register all translations
|
||||||
initTranslations();
|
initTranslations();
|
||||||
|
|
||||||
//Look for Nero AAC encoder
|
//Look for AAC encoders
|
||||||
initNeroAac();
|
initNeroAac();
|
||||||
|
|
||||||
//Look for FHG AAC encoder
|
|
||||||
initFhgAac();
|
initFhgAac();
|
||||||
|
initQAac();
|
||||||
|
|
||||||
delay();
|
delay();
|
||||||
m_bSuccess = true;
|
m_bSuccess = true;
|
||||||
@ -482,6 +481,111 @@ void InitializationThread::initFhgAac(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InitializationThread::initQAac(void)
|
||||||
|
{
|
||||||
|
const QString appPath = QDir(QCoreApplication::applicationDirPath()).canonicalPath();
|
||||||
|
|
||||||
|
QFileInfo qaacFileInfo[4];
|
||||||
|
qaacFileInfo[0] = QFileInfo(QString("%1/qaac.exe").arg(appPath));
|
||||||
|
qaacFileInfo[1] = QFileInfo(QString("%1/libsoxrate.dll").arg(appPath));
|
||||||
|
qaacFileInfo[2] = QFileInfo(QString("%1/msvcp100.dll").arg(appPath));
|
||||||
|
qaacFileInfo[3] = QFileInfo(QString("%1/msvcr100.dll").arg(appPath));
|
||||||
|
|
||||||
|
bool qaacFilesFound = true;
|
||||||
|
for(int i = 0; i < 4; i++) { if(!qaacFileInfo[i].exists()) qaacFilesFound = false; }
|
||||||
|
|
||||||
|
//Lock the FhgAacEnc binaries
|
||||||
|
if(!qaacFilesFound)
|
||||||
|
{
|
||||||
|
qDebug("QAAC binaries not found -> QAAC support will be disabled!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug("Found QAAC encoder:\n%s\n", qaacFileInfo[0].canonicalFilePath().toUtf8().constData());
|
||||||
|
|
||||||
|
LockedFile *qaacBin[4];
|
||||||
|
for(int i = 0; i < 4; i++) qaacBin[i] = NULL;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
qaacBin[i] = new LockedFile(qaacFileInfo[i].canonicalFilePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 4; i++) LAMEXP_DELETE(qaacBin[i]);
|
||||||
|
qWarning("Failed to get excluive lock to FhgAacEnc binary -> FhgAacEnc support will be disabled!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProcess process;
|
||||||
|
process.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
process.setReadChannel(QProcess::StandardOutput);
|
||||||
|
process.start(qaacFileInfo[0].canonicalFilePath(), QStringList());
|
||||||
|
|
||||||
|
if(!process.waitForStarted())
|
||||||
|
{
|
||||||
|
qWarning("QAAC process failed to create!");
|
||||||
|
qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData());
|
||||||
|
process.kill();
|
||||||
|
process.waitForFinished(-1);
|
||||||
|
for(int i = 0; i < 4; i++) LAMEXP_DELETE(qaacBin[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRegExp qaacEncSig("qaac (\\d)\\.(\\d)(\\d)", Qt::CaseInsensitive);
|
||||||
|
unsigned int qaacVersion = 0;
|
||||||
|
|
||||||
|
while(process.state() != QProcess::NotRunning)
|
||||||
|
{
|
||||||
|
process.waitForReadyRead();
|
||||||
|
if(!process.bytesAvailable() && process.state() == QProcess::Running)
|
||||||
|
{
|
||||||
|
qWarning("QAAC process time out -> killing!");
|
||||||
|
process.kill();
|
||||||
|
process.waitForFinished(-1);
|
||||||
|
for(int i = 0; i < 4; i++) LAMEXP_DELETE(qaacBin[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while(process.bytesAvailable() > 0)
|
||||||
|
{
|
||||||
|
QString line = QString::fromUtf8(process.readLine().constData()).simplified();
|
||||||
|
if(qaacEncSig.lastIndexIn(line) >= 0)
|
||||||
|
{
|
||||||
|
unsigned int tmp[3] = {0, 0, 0};
|
||||||
|
bool ok[3] = {false, false, false};
|
||||||
|
tmp[0] = qaacEncSig.cap(1).toUInt(&ok[0]);
|
||||||
|
tmp[1] = qaacEncSig.cap(2).toUInt(&ok[1]);
|
||||||
|
tmp[2] = qaacEncSig.cap(3).toUInt(&ok[2]);
|
||||||
|
if(ok[0] && ok[1] && ok[2])
|
||||||
|
{
|
||||||
|
qaacVersion = (qBound(0U, tmp[0], 9U) * 100) + (qBound(0U, tmp[1], 9U) * 10) + qBound(0U, tmp[2], 9U);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(qaacVersion > 0))
|
||||||
|
{
|
||||||
|
qWarning("QAAC version couldn't be determined -> QAAC support will be disabled!");
|
||||||
|
for(int i = 0; i < 4; i++) LAMEXP_DELETE(qaacBin[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(qaacVersion < lamexp_toolver_qaacenc())
|
||||||
|
{
|
||||||
|
qWarning("QAAC version is too much outdated -> QAAC support will be disabled!");
|
||||||
|
for(int i = 0; i < 4; i++) LAMEXP_DELETE(qaacBin[i]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
lamexp_register_tool(qaacFileInfo[i].fileName(), qaacBin[i], qaacVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void InitializationThread::selfTest(void)
|
void InitializationThread::selfTest(void)
|
||||||
{
|
{
|
||||||
const unsigned int cpu[4] = {CPU_TYPE_X86_GEN, CPU_TYPE_X86_SSE, CPU_TYPE_X64_GEN, CPU_TYPE_X64_SSE};
|
const unsigned int cpu[4] = {CPU_TYPE_X86_GEN, CPU_TYPE_X86_SSE, CPU_TYPE_X64_GEN, CPU_TYPE_X64_SSE};
|
||||||
|
@ -45,6 +45,7 @@ private:
|
|||||||
void initTranslations(void);
|
void initTranslations(void);
|
||||||
void initNeroAac(void);
|
void initNeroAac(void);
|
||||||
void initFhgAac(void);
|
void initFhgAac(void);
|
||||||
|
void initQAac(void);
|
||||||
|
|
||||||
bool m_bSuccess;
|
bool m_bSuccess;
|
||||||
lamexp_cpu_t m_cpuFeatures;
|
lamexp_cpu_t m_cpuFeatures;
|
||||||
|
Loading…
Reference in New Issue
Block a user