MonitorAPO 通过一种锁无关由应用程序初始化的通讯通道的方式来将音频数据传递给主线程。将MonitorAPO添加到上一篇的源码中,给一个source voice添加了两个特效。
主要是使用管道,在APO中的DoProcess函数中将数据写入,然后在主线程中就可以读出来了。
#include "DXUTLockFreePipe.h" typedef DXUTLockFreePipe<MONITOR_APO_PIPE_LEN> MonitorAPOPipe; struct MonitorAPOParams { MonitorAPOPipe *pipe; }; class __declspec( uuid("{A4945B8A-EB14-4c96-8067-DF726B528091}")) CMonitorAPO : public CSampleXAPOBase<CMonitorAPO, MonitorAPOParams> { public: CMonitorAPO(); ~CMonitorAPO(); void DoProcess( const MonitorAPOParams&, FLOAT32* __restrict pData, UINT32 cFrames, UINT32 cChannels ); };
需要使用到模板类DXUTLockFreePipe和模板类CSampleXAPOBase,前者是管道,用来获取数据。后者是XAPO用来完成特效。
CSimpleAPO *pSimpleXAPO = NULL; CSimpleAPO::CreateInstance(NULL, 0, &pSimpleXAPO);//创建XAPO实例 CMonitorAPO *pMpnitorAPO = NULL; CMonitorAPO::CreateInstance(NULL, 0, &pMpnitorAPO); XAUDIO2_EFFECT_DESCRIPTOR descriptor[2];//效果描述,包含了一个XAPO的信息 descriptor[0].InitialState = true; descriptor[0].OutputChannels = 2; descriptor[0].pEffect = dynamic_cast<IXAPO*>(pSimpleXAPO);//强制转换 descriptor[1].InitialState = true; descriptor[1].OutputChannels = 2; descriptor[1].pEffect = dynamic_cast<IXAPO*>(pMpnitorAPO);//强制转换 XAUDIO2_EFFECT_CHAIN eChain;//效果链,包含了含有几个效果对象 eChain.EffectCount = 2; eChain.pEffectDescriptors = descriptor; hr = pSourceVoice->SetEffectChain(&eChain);//将效果链传递给voice if (FAILED(hr)) return 0; pSimpleXAPO->Release();//传给voice后,voice接管此对象。防止外部对此对象修改,释放 pMpnitorAPO->Release(); SimpleAPOParams simpleParams;//设置参数 simpleParams.gain = 1.2f; hr = pSourceVoice->SetEffectParameters(0, &simpleParams, sizeof(SimpleAPOParams));//将设置传递给voice if (FAILED(hr)) return 0; MonitorAPOParams monitorParams; monitorParams.pipe = new MonitorAPOPipe; hr = pSourceVoice->SetEffectParameters(1, &monitorParams, sizeof(MonitorAPOParams));//将设置传递给voice if (FAILED(hr)) return 0;
CMonitorAPO派生自一个模板类CSampleXAPOBase,位于文件SampleAPOBase.h中。模板类实例化时需要提供XAPO类和参数类:APOClass和ParameterClass。参数类可以是结构体。
模板类实现了静态实例化函数CreateInstance,以及LockForProcess和Process接口函数。并预留了一个纯虚函数DoProcess来让子类实现不同的需求。
Process函数实现了如果输入缓冲区的标志位是XAPO_BUFFER_SILENT,将缓冲区置为0.如果为XAPO_BUFFER_VALID,表示数据有效,调用DoProcess来将数据进行写入管道:
void CMonitorAPO::DoProcess( const MonitorAPOParams& params, FLOAT32* __restrict pData, UINT32 cFrames, UINT32 cChannels ) { if( cFrames ) { MonitorAPOPipe* pipe = params.pipe; if( pipe ) pipe->Write( pData, cFrames * cChannels * (WaveFormat().wBitsPerSample >> 3) ); } }
其中BeginProcess接口可以获取最新的通过SetEffectParameters设置的参数。XAPO只能在Process函数内调用这个方法。
EndProcess告诉CXAPOParametersBase,XAPO已经完成了接收设置的最新的参数。此方法也必须在Process方法内调用。
交流QQ:1245178753
本文地址:http://blog.csdn.net/u011417605/article/details/51202619
源码下载:http://download.csdn.net/detail/u011417605/9497187