XAudio2学习六之播放WAV文件

XAudio2学习六之播放WAV文件

徐冬冬

前面已经加载了WAV文件到内存中,那么如果想要播放这些数据,需要怎么实现呢?
大致步骤如下:
1.初始化COM组件;
2.创建XAudio2声音引擎;
3.创建主声音IXAudio2MasteringVoice;
4.加载WAV文件到内存;
5.创建源声音IXAudio2SourceVoice,并提交数据,启动播放;
6.获取播放状态,等待播放完成;
7.释放资源。
对于每一步的具体实现,下面详细说明一下:
初始化COM组件:
这个前面也提到过,可以参考XAudio2获取音频输出设备。
创建XAudio2声音引擎:
这个前面也提到过,可以参考XAudio2获取音频输出设备。
创建主声音IXAudio2MasteringVoice
 STDMETHOD(CreateMasteringVoice) (THIS_ __deref_out IXAudio2MasteringVoice** ppMasteringVoice,//对象二级指针
                                     UINT32 InputChannels X2DEFAULT(XAUDIO2_DEFAULT_CHANNELS),//通道数,缺省0
                                     UINT32 InputSampleRate X2DEFAULT(XAUDIO2_DEFAULT_SAMPLERATE),//采样率,缺省0
                                     UINT32 Flags X2DEFAULT(0), UINT32 DeviceIndex X2DEFAULT(0),//设备索引,缺省表示使用全局音频输出设备。
                                     __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE;//效果链,使用XAUDIO2_EFFECT_CHAIN结构体来指定效果。0表示无效果。
上面是创建主声音的接口。
IXAudio2MasteringVoice *pMasterVoice = NULL;
hr = pEngine->CreateMasteringVoice(&pMasterVoice);//创建主声音,默认是输出当前扬声器
可以得到一个IXAudio2MasteringVoice对象,可以将IXAudio2SourceVoice的输出明确指定为此对象,
也可以不指定, 不指定的情况下,IXAudio2SourceVoice对象默认输出到此对象。
如果存在多个 IXAudio2MasteringVoice对象, 那么就需要明确指定 IXAudio2SourceVoice提交的音频
流向哪一个主声音设备。
加载WAV文件到内存
这个前面也提到过,可以参考加载WAV文件。
创建源声音IXAudio2SourceVoice,并提交数据,启动播放
 STDMETHOD(CreateSourceVoice) (THIS_ __deref_out IXAudio2SourceVoice** ppSourceVoice,//源声音对象
                                  __in const WAVEFORMATEX* pSourceFormat,//需要提供格式,最好是和需要播放的文件的格式一致,可以使用文件的格式
                                  UINT32 Flags X2DEFAULT(0),//控制源声音的行为。必须为0
                                  float MaxFrequencyRatio X2DEFAULT(XAUDIO2_DEFAULT_FREQ_RATIO),//设置允许的最大频数比,缺省为2
                                  __in_opt IXAudio2VoiceCallback* pCallback X2DEFAULT(NULL),//回调。可以用于当前buffer是否播放完毕。
                                  __in_opt const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL),//输出。可以指定输出个数以及输出目标Voice
                                  __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE;//效果链
IXAudio2SourceVoice用来提交音频数据,并启动播放。是整个音频流的开始,数据由IXAudio2SourceVoice对象开始,
流向IXAudio2MasteringVoice中间可以经过n个IXAudio2SubmixVoice对象,其中n>=0。
 	XAUDIO2_BUFFER buffer;//将读取的文件数据,赋值XAUDIO2_BUFFER
 	buffer.AudioBytes = size;
 	buffer.pAudioData = pData;
 
 	hr = pSourceVoice->SubmitSourceBuffer(&buffer);//提交内存数据
 	if (FAILED(hr))
 		return 0;
 
 	hr = pSourceVoice->Start();//启动源声音
 	if (FAILED(hr))
 		return 0;
使用XAUDIO2_BUFFER来保存需要播放的数据大小和数据内存地址,使用SubmitSourceBuffer来提交数据,
数据提交后,并不能播放出声音,因为IXAudio2SourceVoice对象并没有启动,
需要通过调用pSourceVoice->Start();来启动播放。
获取播放状态,等待播放完成
XAUDIO2_VOICE_STATE state;
pSourceVoice->GetState(&state);//获取播放状态:已播放数据,待播放队列
播放过程中可以使用 pSourceVoice->GetState(&state);来获取播放的状态,
可以使用循环来控制等待播放,直到播放完成。
释放资源
资源不释放的话,会造成内存泄露。从而导致系统崩溃。
	pMasterVoice->DestroyVoice();//释放资源
 	pSourceVoice->DestroyVoice();//释放资源
 	pEngine->Release();//释放资源
 	CoUninitialize();//释放资源

	delete []pData;//释放资源
	pData = NULL;
完整代码:
#pragma once
#include "WaveFile.h"
#include "XAudio2.h"

 int main(int argc, char *argv[])
 {
	 HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);;//com初始化
 	if (FAILED(hr))
 		return 0;
 
 	IXAudio2 *pEngine = NULL;
 	hr = XAudio2Create(&pEngine);//创建引擎
 	if (FAILED(hr))
 		return 0;
 
 	IXAudio2MasteringVoice *pMasterVoice = NULL;
 	hr = pEngine->CreateMasteringVoice(&pMasterVoice);//创建主声音,默认是输出当前扬声器
 	if (FAILED(hr))
 		return 0;
 
 	CWaveFile waveFile;
 	hr = waveFile.Open(L"C:\\Users\\dlp\\Desktop\\24bit-48khz.wav", NULL, WAVEFILE_READ);//加载文件
 	if (FAILED(hr))
 		return 0;
 
 	WAVEFORMATEX *waveFormat = waveFile.GetFormat();//获取文件格式
 	IXAudio2SourceVoice *pSourceVoice = NULL;
 	hr = pEngine->CreateSourceVoice(&pSourceVoice, waveFormat);//创建源声音,用来提交数据
 	if (FAILED(hr))
 		return 0;
 
 	DWORD size = waveFile.GetSize();//获取文件的大小
 	BYTE *pData = new BYTE[size];//申请内存空间,用于保存数据
 	hr = waveFile.Read(pData, size, &size);//读取文件内容
 	if (FAILED(hr))
 		return 0;
 
	XAUDIO2_BUFFER buffer = {0};//将读取的文件数据,赋值XAUDIO2_BUFFER
 	buffer.AudioBytes = size;
 	buffer.pAudioData = pData;
	buffer.Flags = XAUDIO2_END_OF_STREAM;
 
 	hr = pSourceVoice->SubmitSourceBuffer(&buffer);//提交内存数据
 	if (FAILED(hr))
 		return 0;
 
 	hr = pSourceVoice->Start(0);//启动源声音
 	if (FAILED(hr))
 		return 0;
 
	XAUDIO2_VOICE_STATE state;
	pSourceVoice->GetState(&state);//获取状态
	while (state.BuffersQueued)
	{
		pSourceVoice->GetState(&state);
		Sleep(10);
	}
 
 	pMasterVoice->DestroyVoice();//释放资源
 	pSourceVoice->DestroyVoice();//释放资源
 	pEngine->Release();//释放资源
 	CoUninitialize();//释放资源

	delete []pData;//释放资源
	pData = NULL;

 	return 0;
 }

备注:请尊重版权,转载请联系作者QQ:1245178753。

交流请加:

群名称:XAudio2 交流群

群   号:233537460


本文链接: http://blog.csdn.net/u011417605/article/details/50789339
源码下载: http://download.csdn.net/detail/u011417605/9452803

你可能感兴趣的:(XAudio2)