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