如何:创建 XAPO
XAPO API 提供 IXAPO 接口和 CXAPOBase 类,用于生成新的 XAPO 类型。 IXAPO 接口包含创建新 XAPO 需要实现的所有方法。 CXAPOBase 类提供 IXAPO 接口的基本实现。 CXAPOBase 实现除每个 XAPO 唯一的 IXAPO::P rocess 方法之外的所有 IXAPO 接口方法。
创建新的静态 XAPO
从 CXAPOBase 基类派生新的 XAPO 类。
注意
XAPOs 实现 IUnknown 接口。 IXAPO 和 IXAPOParameters 接口包括三个 IUnknown 方法:QueryInterface、AddRef 和 Release。 CXAPOBase 提供所有三个 IUnknown 方法的实现。 CXAPOBase 的新实例的引用计数为 1。 当它的引用计数变为 0 时,它将销毁它。 若要允许 XAudio2 在不再需要 XAPO 实例时销毁该实例,请在将 XAPO 添加到 XAudio2 效果链后,在 XAPO 上调用 IUnknown::Release 。 有关 将 XAPO 与 XAudio2 配合使用的详细信息,请参阅如何:在 XAudio2 中使用 XAPO。
重写 IXAPO::LockForProcess 方法的 CXAPOBase 类实现。
重写 LockForProcess 允许存储有关音频数据格式的信息,以便在 IXAPO::P rocess 中使用。
实现 IXAPO::P rocess 方法。
每当 XAPO 需要处理音频数据时,XAudio2 将调用 IXAPO::P rocess 方法。 进程 包含 XAPO 的大部分代码。
实现 Process 方法
IXAPO::P rocess 方法接受输入和输出音频数据的流缓冲区。 典型的 XAPO 需要一个输入流缓冲区和一个输出流缓冲区。 应基于 LockForProcess 函数中指定的格式以及使用输入流缓冲区传递给 Process 函数的任何标志来处理输入流缓冲区中的数据。 将处理的输入流缓冲区数据复制到输出流缓冲区。 将输出流缓冲区的 BufferFlags 参数设置为 XAPO_BUFFER_VALID 或 XAPO_BUFFER_SILENT。
以下示例演示了 一个 LockForProcess 和 Process 实现,该实现只是将数据从输入缓冲区复制到输出缓冲区。 但是,如果输入缓冲区标记为 XAPO_BUFFER_SILENT,则不会进行处理。
STDMETHOD(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);
}
STDMETHOD_(void, 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
}
编写 Process 方法时,请务必注意 XAudio2 音频数据是交错的。 这意味着来自每个通道的数据对于特定样本数是相邻的。 例如,如果有 4 声道波在 XAudio2 源语音中播放,则音频数据是通道 0 的样本、通道 1 的样本、通道 2 的样本、通道 3 的样本,然后是通道 0、1、2、3 等的下一个样本。
相关主题