在这篇文章中,对MP3、WMA、WAV和OGG Vorbis格式支持,这需要Windows Media 9或更高版本的支持。此外,还对代码进行了一些额外的工作,以重新组织代码结构。
输入流可以包括文件、CD、麦克风等。在本文中,输入流是音频文件。因此,定义了一个名为CInput的基类,用于所有输入类型,并在此类中定义了一些纯虚函数。派生类必须实现GetDataInternal函数,该函数从音频文件中读取音频数据并填充到缓冲区中。
在本文中,使用Windows Media Format (WMF) 解码WMA格式。主要使用的接口包括IWMSyncReader、INSSBuffer和IWMHeaderInfo。IWMSyncReader接口提供了使用同步调用读取WMA文件的能力。INSSBuffer接口是缓冲区对象的基本接口。缓冲区对象是内存缓冲区的包装器。此接口公开的方法用于操作缓冲区。IWMHeaderInfo接口用于设置和检索ASF文件头部分的信息。可以使用此接口的方法操作三种类型的头信息:元数据属性、标记和脚本命令。有关更多信息,请查阅MSDN。
本文中集成了libmad、libogg和libvorbis等库。为MP3、WMA、WAV和OGG Vorbis文件的读取定义了四个类,分别是CWMIn、CWaveIn、CMP3In和CVorbisIn。有关更多详细信息,请查阅代码。
应用程序使用libmad解码MP3文件,不再依赖于Windows Media Format (WMF),这个库非常酷,很喜欢。
本文中实现的组件在《使用DirectSound播放WAV文件并实时显示其频谱 - 第二部分》中已经介绍过,使用DirectSound进行输出。因此,如果对此有疑问,应该先阅读那篇文章。也可以在CodeProject上搜索关键词DirectSound,将找到许多相关文章。
总是觉得在窗口中显示的频谱不正确,尤其是在播放一些音频文件时。因此,希望能得到帮助,并彻底解决这个问题。
使用libmad解码mp3文件,不再依赖于Windows Media Format (WMF)。
// 初始化DirectSound
IDirectSound8* pDS = NULL;
DirectSoundCreate8(NULL, &pDS, NULL);
if (pDS == NULL) {
// 错误处理
}
// 设置音频格式
WAVEFORMATEX wfx;
ZeroMemory(&wfx, sizeof(WAVEFORMATEX));
wfx.cbSize = sizeof(WAVEFORMATEX);
wfx.nChannels = 2;
wfx.nSamplesPerSec = 44100;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nBlockAlign = 4;
wfx.nAvgBytesPerSec = 176400;
// 创建音频缓冲区
IDirectSoundBuffer* pDSB = NULL;
DSBUFFERDESC dsbd;
ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbd.dwBufferBytes = 0;
dsbd.lpwfxFormat = &wfx
pDS->CreateSoundBuffer(&dsbd, &pDSB, NULL);
if (pDSB == NULL) {
// 错误处理
}
// 播放音频
pDSB->Play(0, 0, DSBPLAY_LOOPING);