下面的文章将指导您完成创建基于桌面对话框的应用程序的过程,该应用程序可用于相互转换音频文件。包括:
“engine”-一个类库,用于从一种格式到另一种格式的实际转换
枚举给定路径中的文件以及其中的任何子文件夹。

用户界面和用户体验
我开发的程序无需安装即可运行,无需外部DLL,甚至不需要静态库。只需构建并运行即可。
背景
MicrosoftMediaFoundation是一个基于Windows的多媒体平台,使开发人员能够创建各种多媒体软件。
转换音频文件
使用MicrosoftMediaFoundation转换音频文件需要对音频流进行编码和解码,这将在以下教程中进行说明。
第一步是为此类音频处理创建我们自己的类,我们称之为SG_Audio(Convert)。
SG_AudioConvert::SG_AudioConvert()
{
// Initialize whatever needs to be initialized
Init();
}
SG_AudioConvert::~SG_AudioConvert()
{
// Clean up whatever needs to be cleaned up
Cleanup();
}1234567891011复制代码类型:[c]
初始化中
我们的Init()功能由构造调用,执行以下操作:
检查它是否已经通过初始化。我们不希望(也不应该)多次这样做。
调用HeapSetInformation()为我们的堆启用某些功能。请注意,我们正在初始化单线程单元,您可以在这篇出色的文章中了解有关该术语的更多信息。
调用MFStartup()以启动WindowsMediaFoundation。
设置m_bInit为true,表示初始化已完成。
int SG_AudioConvert::Init()
{
HRESULT hr = S_OK;
// check already initialized
if (m_bInit)
return RET_OK;
(void)HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
hr = MFStartup(MF_VERSION);
m_bInit = TRUE;
return RET_OK; // success
}
m_bInit = FALSE;
return RET_FAIL; // fail
}12345678910111213141516171819202122复制代码类型:[c]
打扫干净
在继续之前,我们还介绍一下我们类的Destructor调用的清理过程。
int SG_AudioConvert::Cleanup()
{
MFShutdown();
CoUninitialize();
return RET_OK; // success
}1234567复制代码类型:[c]
在清理过程中,我们执行以下操作:
致电MFShutdown()
呼叫CoUninitialize()
我们的通用音频转换功能
我们开发
intSG_AudioConvert::ConvertProc()以将所有文件转换从支持的任何音频类型转换为其他任何类型。
我们将以下参数传递给它:
p_szSrc-我们的源文件
p_szDst-我们的目标文件
TargetFormat-我们目标格式的GUID-请参阅“音频编解码器”
ContainerType-我们的容器类型-请参阅“文件容器”
该函数的原型如下所示:
int SG_AudioConvert::ConvertProc(
const wchar_t* p_szSrc,
const wchar_t* p_szDst,
const GUID TargetFormat,
const GUID ContainerType);12345复制代码类型:[c]
转换
我们的通用转换函数如下所示:ConvertProc()
注:WriteLogFile()是在描述我的旧的日志记录功能之一这个文章。
int SG_AudioConvert::ConvertProc(const wchar_t* p_szSrc, const wchar_t* p_szDst,
const GUID TargetFormat, const GUID ContainerType)
{
CTranscoder transcoder;
HRESULT hr = S_OK;
// Create a media source for the input file.
hr = transcoder.OpenFile(p_szSrc);
if (SUCCEEDED(hr))
{
//Configure the profile and build a topology.
hr = transcoder.ConfigureAudioOutput(TargetFormat);
}
else
{
return RET_INPUT_FAIL; // open input file fail
}
if (SUCCEEDED(hr))
{
hr = transcoder.ConfigureContainer(ContainerType);
}
//Transcode and generate the output file.
if (SUCCEEDED(hr))
{
hr = transcoder.EncodeToFile(p_szDst);
}
if (SUCCEEDED(hr))
{
WriteLogFile(L"Output file created: %sn", p_szDst);
}
else
{
WriteLogFile(L"Output file was not created due to error: %sn", p_szDst);
}
if (!SUCCEEDED(hr))
{
return RET_ENC_FAIL; // encoding failed
}
return RET_OK; // encoding success
}123456789101112131415161718192021222324252627282930313233343536373839404142434445复制代码类型:[c]
我们的转换功能
这是我们的转换函数:
以下六个功能涵盖了以下音频格式的每种组合之间的转换:.mp3,.wav和.m4a。
// Convert to MP3
int SG_AudioConvert::Wav_to_Mp3(const wchar_t* p_szWavFile, const wchar_t* p_szMp3File)
{
// check initialize
if (!m_bInit)
return RET_NOT_INIT;
// convert
return(ConvertProc(p_szWavFile, p_szMp3File,
MFAudioFormat_MP3, MFTranscodeContainerType_MP3));
}
int SG_AudioConvert::M4A_to_Mp3(const wchar_t* p_szM4AFile, const wchar_t* p_szMp3File)
{
// check initialize
if (!m_bInit)
return RET_NOT_INIT;
// Convert
return(ConvertProc(p_szM4AFile, p_szMp3File,
MFAudioFormat_MP3, MFTranscodeContainerType_MP3));
}
// Convert to M4A
int SG_AudioConvert::Wav_to_M4A(const wchar_t* p_szWavFile, const wchar_t* p_szM4AFile)
{
// check initialize
if (!m_bInit)
return RET_NOT_INIT;
// Convert
return(ConvertProc(p_szWavFile, p_szM4AFile, MFAudioFormat_AAC,
MFTranscodeContainerType_MPEG4));
}
int SG_AudioConvert::MP3_to_M4A(const wchar_t* p_szMp3File, const wchar_t* p_szM4AFile)
{
// check initialize
if (!m_bInit)
return RET_NOT_INIT;
// Convert
return(ConvertProc(p_szMp3File, p_szM4AFile,MFAudioFormat_AAC,
MFTranscodeContainerType_MPEG4));
}
// Convert to Wav
int SG_AudioConvert::MP3_to_Wav(const wchar_t* p_szMp3File, const wchar_t* p_szWavFile)
{
// check initialize
if (!m_bInit)
return RET_NOT_INIT;
// Convert
return(ConvertProc(p_szMp3File, p_szWavFile, MFAudioFormat_PCM,
MFTranscodeContainerType_WAVE));
}
int SG_AudioConvert::M4A_to_Wav(const wchar_t* p_szM4AFile, const wchar_t* p_szWavFile)
{
// check initialize
if (!m_bInit)
return RET_NOT_INIT;
// Convert
return(ConvertProc(p_szM4AFile, p_szWavFile, MFAudioFormat_PCM,
MFTranscodeContainerType_WAVE));
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768复制代码类型:[c]
我们的文件搜索机制
我最近更新了一些旧代码(感谢LoukaDiagnekov)来支持现代应用程序,包括UNICODE字符串,并且该代码托管在此存储库中。
此类的一个不错的功能是可以在一个搜索中设置多个查询的功能。我们还可以递归地扫描文件夹及其子文件夹,以查找与我们的标准相匹配的文件。
这是struct运行搜索之前填写的主要内容。请注意,当涉及到数百万个文件时,此类有点慢,但是就我们的音频转换器工具而言,它可以正常工作。
// Specifies settings to use for searching for files
struct FindFileOptions_t
{
bool recursive; // Whether to look inside subdirectories
bool returnFolders; // Return folder names as results too
bool *terminateValue; // Value to check to see whether search should be
// terminated
wstring location; // Where to search for files
wstring filter; // Filter for files to be included
wstring excludeFile; // Exclude filter for files
wstring excludeDir; // Exclude filter for directories
};12345678910111213141516复制代码类型:[c]
我们的运作模式
我们定义了9种操作模式,可以将一种或两种格式秘密转换为第三种。这样,我们可以在给定路径中搜索一种或两种类型的文件,并在找到时将其转换为第三种格式。
typedef enum
{
M4A_WAV_TO_MP3 = 0, // convert m4a and wav to mp3
MP3_M4A_TO_WAV = 1, // convert mp3 and m4a to wav
MP3_WAV_TO_M4A = 2, // convert mp3 and wav to m4a
M4A_TO_MP3 = 3, // convert m4a to mp3
WAV_TO_MP3 = 4, // convert wav to mp3
MP3_TO_WAV = 5, // convert mp3 to wav
M4A_TO_WAV = 6, // convert m4a to wav
WAV_TO_M4A = 7, // convert wav to m4a
MP3_TO_M4A = 8, // convert mp3 to m4a
LAST_ELEMENT = 9
} OperationMode;1234567891011121314复制代码类型:[c]
让我们采用一种“操作模式”并对其进行详细说明。例如,MP3_WAV_TO_M4A。
在此模式下,我们希望在给定路径中搜索.mp3和.wav文件,并将所有找到的文件转换为m4a。
选择此模式后,我们将执行以下操作:
使用以下查询搜索文件:
#define QUERY_MP3_WAV L"*.mp3;*.wav";1复制代码类型:[cpp]
因此,回到我们的FindFile课程,我们将其设置为:
opts.filter = QUERY_MP3_WAV;1复制代码类型:[cpp]
然后,我们调用:
scanPath(wstring path)1复制代码类型:[cpp]
开始我们的文件搜索。搜索完成后,我们将得到一个数组,其中包含所有找到的文件,然后将这些文件转换为我们的目标音频类型。
用户界面

该软件基于基于Dialog的MFC应用程序。对话框可调整大小,并且每次调整对话框大小时都会调整每个元素。这是使用MarcRicharme的以下文章中的一些非常古老(但坚如磐石)的代码实现的。对话框也有其自己的皮肤,背景颜色,透明元素,因此它看起来比标准MFC应用程序更好。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 ZLME@ZLME.COM 举报,一经查实,立刻删除。