如何:创建 XAPO

XAPO API 提供 IXAPO 接口和 CXAPOBase 类,用于生成新的 XAPO 类型。 IXAPO 接口包含创建新 XAPO 需要实现的所有方法。 CXAPOBase 类提供 IXAPO 接口的基本实现。 CXAPOBase 实现除每个 XAPO 唯一的 IXAPO::P rocess 方法之外的所有 IXAPO 接口方法。

创建新的静态 XAPO

  1. CXAPOBase 基类派生新的 XAPO 类。

    注意

    XAPOs 实现 IUnknown 接口。 IXAPOIXAPOParameters 接口包括三个 IUnknown 方法:QueryInterfaceAddRefReleaseCXAPOBase 提供所有三个 IUnknown 方法的实现。 CXAPOBase 的新实例的引用计数为 1。 当它的引用计数变为 0 时,它将销毁它。 若要允许 XAudio2 在不再需要 XAPO 实例时销毁该实例,请在将 XAPO 添加到 XAudio2 效果链后,在 XAPO 上调用 IUnknown::Release 。 有关 将 XAPO 与 XAudio2 配合使用的详细信息,请参阅如何:在 XAudio2 中使用 XAPO。

     

  2. 重写 IXAPO::LockForProcess 方法的 CXAPOBase 类实现。

    重写 LockForProcess 允许存储有关音频数据格式的信息,以便在 IXAPO::P rocess 中使用。

  3. 实现 IXAPO::P rocess 方法。

    每当 XAPO 需要处理音频数据时,XAudio2 将调用 IXAPO::P rocess 方法。 进程 包含 XAPO 的大部分代码。

实现 Process 方法

IXAPO::P rocess 方法接受输入和输出音频数据的流缓冲区。 典型的 XAPO 需要一个输入流缓冲区和一个输出流缓冲区。 应基于 LockForProcess 函数中指定的格式以及使用输入流缓冲区传递给 Process 函数的任何标志来处理输入流缓冲区中的数据。 将处理的输入流缓冲区数据复制到输出流缓冲区。 将输出流缓冲区的 BufferFlags 参数设置为 XAPO_BUFFER_VALIDXAPO_BUFFER_SILENT

以下示例演示了 一个 LockForProcessProcess 实现,该实现只是将数据从输入缓冲区复制到输出缓冲区。 但是,如果输入缓冲区标记为 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 等的下一个样本。

音频效果

XAPO 概述