方法: XAPO の作成

XAPO API には、新しい XAPO 型を構築するための IXAPO インターフェイスと CXAPOBase クラスが用意されています。 IXAPO インターフェイスには、新しい XAPO を作成するために実装する必要があるすべてのメソッドが含まれています。 CXAPOBase クラスは、IXAPO インターフェイスの基本的な実装を提供します。 CXAPOBase は、各 XAPO に固有の IXAPO::P rocess メソッドを除くすべての IXAPO インターフェイス メソッドを実装します。

新しい静的 XAPO を作成するには

  1. CXAPOBase 基本クラスから新しい XAPO クラスを派生させます。

    注意

    XAPO は IUnknown インターフェイスを実装します。 IXAPO インターフェイスと IXAPOParameters インターフェイスには、QueryInterfaceAddRefRelease の 3 つの IUnknown メソッドが含まれています。 CXAPOBase には、3 つの IUnknown メソッドの実装がすべて用意されています。 CXAPOBase の新しいインスタンスの参照カウントは 1 になります。 参照カウントが 0 になると破棄されます。 XAudio2 が不要になったときに XAPO のインスタンスを破棄できるようにするには、XAudio2 エフェクト チェーンに追加された後、XAPO で IUnknown::Release を呼び出します。 XAudio2 での XAPO の使用の詳細については、「方法: XAudio2 で XAPO を使用する」を参照してください。

     

  2. IXAPO::LockForProcess メソッドの CXAPOBase クラスの実装をオーバーライドします。

    LockForProcess をオーバーライドすると、IXAPO::P rocess で使用するために、オーディオ データの形式に関する情報を格納できます。

  3. IXAPO::P rocess メソッドを実装します

    XAudio2 は、XAPO がオーディオ データを処理する必要がある場合は常に IXAPO::P rocess メソッドを呼び出します。 プロセス には、XAPO のコードの大部分が含まれています。

プロセス メソッドの実装

IXAPO::P rocess メソッドは、入出力オーディオ データのストリーム バッファーを受け入れます。 一般的な XAPO では、1 つの入力ストリーム バッファーと 1 つの出力ストリーム バッファーが必要です。 入力ストリーム バッファーからのデータの処理は、 LockForProcess 関数で指定された形式と、入力ストリーム バッファーを使用して Process 関数に渡されるフラグに基づく必要があります。 処理された入力ストリーム バッファー データを出力ストリーム バッファーにコピーします。 出力ストリーム バッファーの BufferFlags パラメーターを XAPO_BUFFER_VALID または XAPO_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 オーディオ データがインターリーブされることに注意することが重要です。 つまり、各チャネルからのデータは、特定のサンプル番号に対して隣接しています。 たとえば、XAudio2 ソース音声に 4 チャネルの波が再生されている場合、オーディオ データはチャネル 0 のサンプル、チャネル 1 のサンプル、チャネル 2 のサンプル、チャネル 3 のサンプル、チャネル 0、1、2、3 などの次のサンプルです。

オーディオ効果

XAPO 概要