XAudio2学习之采样率转换

使用IXAduio2SubmixVoice可以对wave文件进行采样率转换,以满足设备对波形音频采样率的要求。在XAudio2学习三之获取音频输出设备信息可以看到音频播放设备是有自己支持播放的wave文件的格式的。

以将2通道/44.1k采样率的wave转为2通道/48k的wave为例:

首先,初始化COM组件;

 HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);;//com初始化
 	if (FAILED(hr))
 		return 0;

然后,然后创建IXAudio2引擎;

	IXAudio2 *pEngine = NULL;
 	hr = XAudio2Create(&pEngine);//创建引擎
 	if (FAILED(hr))
 		return 0;

然后,创建主声音,并指定通道数为2,采样率为48K;

WAVEFORMATEX waveFormatex;//设置主声音的格式
	waveFormatex.nChannels = 2;
	waveFormatex.nSamplesPerSec = 48000;
	waveFormatex.wBitsPerSample = 32;
	waveFormatex.nAvgBytesPerSec = 384000;
	waveFormatex.nBlockAlign = 8;
	waveFormatex.wFormatTag = WAVE_FORMAT_PCM;

 	IXAudio2MasteringVoice *pMasterVoice = NULL;
 	hr = pEngine->CreateMasteringVoice(&pMasterVoice,waveFormatex.nChannels,waveFormatex.nSamplesPerSec);//创建主声音,默认是输出当前扬声器
 	if (FAILED(hr))
 		return 0;

然后,读取wave文件,并获取文件格式信息;

CWaveFile waveFile;
 	hr = waveFile.Open(L"C:\\Users\\xdd\\Desktop\\时间都去哪儿了.wav", NULL, WAVEFILE_READ);//加载文件
 	if (FAILED(hr))
 		return 0;

	WAVEFORMATEX *waveFormat = waveFile.GetFormat();//获取文件格式

然后,创建IXAudio2SubmixVoice对象,创建时指定通道数为获取文件格式的通道数,采样率为文件的采样率,并指定对象的输出voice为mastering voice:

XAUDIO2_SEND_DESCRIPTOR pSend;
	pSend.pOutputVoice = pMasterVoice;//指定输出为mastering voice
	pSend.Flags = XAUDIO2_SEND_USEFILTER;

	XAUDIO2_VOICE_SENDS pSendList;
	pSendList.pSends = &pSend;
	pSendList.SendCount = 1;

	IXAudio2SubmixVoice *pSubmixVoice = NULL;
	hr = pEngine->CreateSubmixVoice(&pSubmixVoice, waveFormat->nChannels, waveFormat->nSamplesPerSec, 0, 0, &pSendList);//指定输出为mastering voice
	if (FAILED(hr))
		return 0;

除了上面在创建时直接指定输出voice外,还可以使用下面的方法:

pSubmixVoice->SetOutputVoices(&pSendList);

然后,创建IXAudio2SourceVoice对象,创建时使用获取的文件的格式信息,并指定输出voice为上面创建的IXAduio2SubmixVoice对象,同时使用IXAudio2VoiceCallback回调,方便播放:

pSend.pOutputVoice = pSubmixVoice;//指定输出为SubmixVoice
	pSend.Flags = XAUDIO2_SEND_USEFILTER;

	pSendList.pSends = &pSend;
	pSendList.SendCount = 1;

	VoiceCallback voiceCallBack;
 	IXAudio2SourceVoice *pSourceVoice = NULL;
	hr = pEngine->CreateSourceVoice(&pSourceVoice, waveFormat, 0, 1.0f, &voiceCallBack,&pSendList);//创建源声音,用来提交数据.指定输出为SubmixVoice
 	if (FAILED(hr))

然后,读取wave音频数据,并使用IXAudio2SourceVoice对象提交数据,启动播放:

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)
	{
		WaitForSingleObject(voiceCallBack.hBufferEndEvent, INFINITE);
		pSourceVoice->GetState(&state);
	}

最后,释放资源。

	pMasterVoice->DestroyVoice();//释放资源
	pSubmixVoice->DestroyVoice();//
 	pSourceVoice->DestroyVoice();//释放资源
 	pEngine->Release();//释放资源
 	CoUninitialize();//释放资源

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

编译,运行。可以听到很清晰的声音。

源码下载:http://download.csdn.net/detail/u011417605/9473537

本文地址:http://blog.csdn.net/u011417605/article/details/50990215

交流QQ:1245178753

时间: 2024-10-12 19:05:25

XAudio2学习之采样率转换的相关文章

XAudio2学习之IXAudio2VoiceCallback回调

使用IXAudio2VoiceCallback回调的好处是,在音频数据播放完的时候,可以通知外部程序进行其他操作. 使用IXAudio2VoiceCallback需要继承此接口,然后重新实现,因为内部所有函数都是纯虚函数.所有函数中使用比较多的是OnStreamEnd函数,当音频数据播放完成的时候,OnStreamEnd会触发一个事件. 继承实现IXAudio2VoiceCallback接口: class VoiceCallback : public IXAudio2VoiceCallback

C++学习笔记33 转换运算符

有时候我们想将一个类类型转换为另一个类类型,同时,这两个类并不存在继承关系,这时候我们就需要一种叫做转换运算符的运算符. 一个简单的例子.要将类A转换为int类型 #include <iostream> #include <string> using namespace std; class A{ private: int n; string str; public: A(int m,string s):n(m),str(s){ } }; int main(){ A a(10,&q

XAudio2学习之调节音量

XAudio2音量调节分为全局和声道调节以及连接音量调节.所谓全局就是说设置了音量后会影响整个音频流的声音大小:声道调节就是说只调节某一个声道的音量大小:连接音量设置是说设置voice与其输出voice之间的声道映射音量.举个例子来说明: IXAudio2SourceVoice->IXAudio2SubmixVoice->IXAudio2MasteringVoice 由三个voice组成的音频图.IXAudio2SourceVoice为2声道,IXAudio2SubmixVoice和IXAud

XAudio2学习之音效相关结构体

任何XAudio2 voice都可以持有一个音频效果链.你可以使用XAUDIO2_EFFECT_DESCRIPTOR数组来指定效果链.每个描述因子都包含了由客户端提供的指向音效对象的指针.这些对象必须实现APO接口. 结构体定义为: typedef struct XAUDIO2_EFFECT_DESCRIPTOR { IUnknown *pEffect; BOOL InitialState; UINT32 OutputChannels; } XAUDIO2_EFFECT_DESCRIPTOR;

python3.8的PySimpleGUI学习的温度转换(℃转℉)

一.代码1: #导出模块 import PySimpleGUI as sg #总体布局,sg.InputText(),默认size=(45,1). layout = [ [sg.Text('Celcius(摄氏温度)'), sg.InputText(size=(15,1)),sg.Text('℃')], #第1行的3个布局 [sg.Submit()], #第2行 ] #定义窗口即标题 #window = sg.Window('Temperature Converter').Layout(layo

scala学习笔记-数组转换(8)

使用yield和函数式编程转换数组 1 // 对Array进行转换,获取的还是Array 2 val a = Array(1, 2, 3, 4, 5) 3 val a2 = for (ele <- a) yield ele * ele 4 // 对ArrayBuffer进行转换,获取的还是ArrayBuffer 5 val b = ArrayBuffer[Int]() 6 b += (1, 2, 3, 4, 5) 7 val b2 = for (ele <- b) yield ele * el

CSS 3 学习——transform 3D转换渲染

以下内容根据官方规范翻译,没有翻译关于SVG变换的内容和关于矩阵计算的内容. 一般情况下,元素在一个无景深无立体感的平面(flat plane)上渲染,这个平面就是其包含块所处的平面.同时,页面上的其他元素也共享这个平面.2D变换函数虽然能改变元素的表现,但是这个被改变的元素仍然是在其包含块所处的平面内被渲染. 3D变换会产生一个变换矩阵,该变换矩阵在Z轴上的分量不为0.结果是把元素渲染到一个不同于其包含块所处的平面内.这将影响到通常情况下的"后来居上"的渲染规则:变换元素可能会和其相

CSS 3学习——transform 2D转换

首先声明一点,transform属性不为none的元素是它的定位子元素(绝对定位和固定定位)的包含块,而且对内创建一个新的层叠上下文. 注意:可以通过 transform-box 属性指定元素的那个盒子发生了变换,该属性的默认值是"border-box",查MDN只有Firefox支持该属性(我试的没效果). CSS 3 中2D转换的实现用到两个属性: 属性 描述 CSS transform 向元素应用 2D 或 3D 转换. 3 transform-origin 指定变换的基点的位置

JAVA 学习 进制转换

写一个函数trans();    1 能够进行十进制转二进制    2 能够进行十进制转八进制    3 能够进行十进制转十六进制    4 封装函数 代码实现: class ArraryTest { public static void main(String[] args) { int num=60; String str_Bin=toBinary(num); String str_Oct=toOctal(num); String str_Hex=toHex(num); System.out