XAudio2学习之自定义音频特效

XAPO API允许创建跨平台音频处理对象(XAPO)以及微软跨平台音频创建工具(XACT)在Windows和Xbox 360上给XAudio2使用。

XAPO API提供了IXAPO接口和CXAPOBase类,可以用来创建新的XAPO类型。IXAPO接口包含了创建一个新的XAPO所需要实现的所有方法。CXAPOBase类简单的继承实现了IXAPO接口,除了IXAPO::Process方法,因为对于每一个XAPO来说,这个方法是唯一的。

XAPO实例以IUnknown接口的形式传递给XAudio2。XAudio2使用QueryInterface来获取IXAPO接口,并且检测IXAPO是否继承了IXAPOParameters接口。

音频数据使用IXAPO::Process方法的pInputProcessParameters参数从voice传递给每个音频特效。然后使用pOutputProcessParameters来将处理后的数据传递给voice。

创建一个新的静态XAPO:

1.以CXAPOBase为基类派生一个新的XAPO类;

2.重写CXAPOBase类实现的IXAPO::LockForProcess方法:重写此方法允许音频数据的格式相关信息在IXAPO::Process方法中使用。

3.实现IXAPO::Process方法:

IXAPO::Process方法接受输入和输出音频数据的流缓冲区。典型的XAPO一般只有一个输入流缓冲区和一个输出流缓冲区。

处理输入流缓冲区的数据需要基于LockForProcess函数中赋予的音频格式,以及随着输入流缓冲区传给Process函数的任意标志。

处理过的输入流缓冲区数据需要拷贝到输出流缓冲区。输出流缓冲区的BufferFlags参数只能设置为XAPO_BUFFER_VALID或XAPO_BUFFER_SILENT。

下面的例子只是做了简单的从输入缓冲区拷贝数据到输出缓冲区,除非输入缓冲区的标志位是XAPO_BUFFER_SILENT。

class CAudioXAPO : public CXAPOBase
{
public:
	virtual HRESULT STDMETHODCALLTYPE LockForProcess(
		UINT32 InputLockedParameterCount,
		const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pInputLockedParameters,
		UINT32 OutputLockedParameterCount,
		const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pOutputLockedParameters
		)
	{
		assert(!IsLocked());
		assert(InputLockedParameterCount == 1);
		assert(OutputLockedParameterCount == 1);
		assert(pInputLockedParameters != NULL);
		assert(pOutputLockedParameters != NULL);
		assert(pInputLockedParameters[0].pFormat != NULL);
		assert(pOutputLockedParameters[0].pFormat != NULL);

		m_uChannels = pInputLockedParameters[0].pFormat->nChannels;
		m_uBytesPerSample = (pInputLockedParameters[0].pFormat->wBitsPerSample >> 3);

		return CXAPOBase::LockForProcess(
			InputLockedParameterCount,
			pInputLockedParameters,
			OutputLockedParameterCount,
			pOutputLockedParameters);
	}

	virtual void STDMETHODCALLTYPE Process(
		UINT32 InputProcessParameterCount,
		const XAPO_PROCESS_BUFFER_PARAMETERS* pInputProcessParameters,
		UINT32 OutputProcessParameterCount,
		XAPO_PROCESS_BUFFER_PARAMETERS* pOutputProcessParameters,
		BOOL IsEnabled
		)
	{
		assert(IsLocked());
		assert(InputProcessParameterCount == 1);
		assert(OutputProcessParameterCount == 1);
		assert(NULL != pInputProcessParameters);
		assert(NULL != pOutputProcessParameters);

		XAPO_BUFFER_FLAGS inFlags = pInputProcessParameters[0].BufferFlags;
		XAPO_BUFFER_FLAGS outFlags = pOutputProcessParameters[0].BufferFlags;

		// assert buffer flags are legitimate
		assert(inFlags == XAPO_BUFFER_VALID || inFlags == XAPO_BUFFER_SILENT);
		assert(outFlags == XAPO_BUFFER_VALID || outFlags == XAPO_BUFFER_SILENT);

		// check input APO_BUFFER_FLAGS
		switch (inFlags)
		{
			case XAPO_BUFFER_VALID:
			{
				void* pvSrc = pInputProcessParameters[0].pBuffer;
				assert(pvSrc != NULL);

				void* pvDst = pOutputProcessParameters[0].pBuffer;
				assert(pvDst != NULL);

				memcpy(pvDst, pvSrc, pInputProcessParameters[0].ValidFrameCount * m_uChannels * m_uBytesPerSample);
				break;
			}
			case XAPO_BUFFER_SILENT:
			{
				// All that needs to be done for this case is setting the
				// output buffer flag to XAPO_BUFFER_SILENT which is done below.
				break;
			}
		}
		// set destination valid frame count, and buffer flags
		pOutputProcessParameters[0].ValidFrameCount = pInputProcessParameters[0].ValidFrameCount; // set destination frame count same as source
		pOutputProcessParameters[0].BufferFlags = pInputProcessParameters[0].BufferFlags;     // set destination buffer flags same as source
	}

private:
	int m_uChannels;
	int m_uBytesPerSample;
};

当写Process方法的时候,需要注意的很重要的一点是XAudio2音频数据是交错的,这意味着每个通道的数据使用相邻的特定样本号来获取。例如:如果有一个4通道的波形音频在XAudio2中播放,音频数据就会是通道0一个采样,通道1一个采样,通道2一个采样,通道3一个采样,然后是依次循环。

DirectX SDK提供了示例:

Windows上路径:

SDK root \Samples\C++\XAudio2\XAudio2CustomAPO

Xbox 360上路径:

SDK root \Source\Samples\Audio\XAudio2CustomAPO

示例描述:

示例创建了一个简单的XAudio2回放图,添加一系列自定义APOs来播放source voice:

SimpleAPO 通过与处理的样本数据相乘应用一个简单的增益因子。

MonitorAPO 通过一种锁无关由应用程序初始化的通讯通道的方式来将音频数据传递给主线程。

Comp1APO 展示了典型的动态变化压缩效果。

这些APOs都是使用一个帮助模板类SampleAPOBase来实现的,可以处理共享注册,类工厂,参数处理操作。用不用这个模板类不是必要的,但是它可以用来简化这个例子。

交流QQ:1245178753

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

时间: 2024-12-16 19:56:12

XAudio2学习之自定义音频特效的相关文章

XAudio2音频特效

An audio effect is an object that takes incoming audio data, and performs some operation on the data before passing it on. You can use an effect to perform a variety of tasks, including adding reverb to an audio stream and monitoring peak volume leve

XAudio2学习之IXAudio2VoiceCallback回调

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

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;

XAudio2学习之内置音效:混响

XAudio2提供了两种内置音频特效,这两种音频特效以及它们的创建方式如下: Effect Creation Method Reverb XAudio2CreateReverb Volume Meter XAudio2CreateVolumeMeter 如何使用内置音频特效呢?大致步骤如下: 1.创建XAPO对象: 2.创建XAPO对象描述结构体对象,用于对XAPO信息进行描述: 3.创建效果链结构体对象,用于持有描述结构体对象:包括两个成员变量:一个是持有的对象个数,一个是所有对象的数组: 4

cocos2dx学习笔记(5)——粒子特效CCParticleSystem

0.使用方法 拿 CCParticleExplosion 举例. //创建CCParticleExplosion特效 CCParticleSystem *p1 = CCParticleExplosion::create(); //设置特效贴图 p1->setTexture(CCTextureCache::sharedTextureCache()->addImage("cocos2dx.png")); //设置自动释放 p1->setAutoRemoveOnFinish

MySQL学习笔记-自定义函数

MySQL学习笔记-自定义函数 1.自定义函数简介 自定义函数:用户自定义函数(user-defined function,UDF)是一种对MySQL扩展的途径,其用法与内置函数相同 自定义函数的两个必要条件:(1)参数  (2)返回值 自定义函数: 创建自定义函数 CREATE FUNCTION function_name RETURNS {STRING|INTEGER|REAL|DECIMAL} routine_body 关于函数体: 1.函数体可以由合法的SQL语句构成: 2.函数体可以是

安卓学习随笔 -- 自定义标题栏

在安卓中不喜欢系统默认的标题栏,那么如何让自定义一个自己的标题栏呢. 自定义后的标题栏如下: 首先这里需要定义一个自定义的标题栏布局 title.xml文件 (里边需要两个图片这个很简单) <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fi

UnityEditor研究学习之自定义Editor

UnityEditor研究学习之自定义Editor 今天我们来研究下Unity3d中自定义Editor,这个会让物体的脚本在Inspector视窗中,产生不同的视觉效果. 什么意思,举个例子,比如游戏中我有个角色Player,他有攻击力,护甲,装备等属性. 所以我定义一个脚本:MyPlayer.cs: using UnityEngine; using System.Collections; public class MyPlayer : MonoBehaviour { public int ar

StyleCop学习笔记——自定义规则

本文将简单的一步一步的指导这可能有助于学习如何创建自己的规则 1.创建一个项目. Visual Studio创建一个新的类库项目.NET3.5 2.引用两个DLL,StyleCop.dll和StyleCop.Csharp.dll. 3.添加自定义的规则. MyCustomAnalyzer.cs代码如下: using StyleCop; using StyleCop.CSharp; namespace MyCustomRules { /// <summary> /// Custom analyz