Compartilhar via


Como: Criar um XAPO

A API XAPO fornece a interface IXAPO e a classe CXAPOBase para criar novos tipos de XAPO. A interface IXAPO contém todos os métodos que precisam ser implementados para criar um novo XAPO. A classe CXAPOBase fornece uma implementação básica da interface IXAPO . O CXAPOBase implementa todos os métodos de interface IXAPO , exceto o método IXAPO::P rocess , que é exclusivo para cada XAPO.

Para criar um novo XAPO estático

  1. Derive uma nova classe XAPO da classe base CXAPOBase .

    Observação

    Os XAPOs implementam a interface IUnknown . As interfaces IXAPO e IXAPOParameters incluem os três métodos IUnknown : QueryInterface, AddRef e Release. O CXAPOBase fornece implementações dos três métodos IUnknown . Uma nova instância do CXAPOBase terá uma contagem de referência de 1. Ele será destruído quando sua contagem de referência se tornar 0. Para permitir que xAudio2 destrua uma instância de um XAPO quando ela não for mais necessária, chame IUnknown::Release no XAPO depois que ela for adicionada a uma cadeia de efeitos XAudio2. Confira Como usar um XAPO no XAudio2 para obter mais informações sobre como usar um XAPO com XAudio2.

     

  2. Substitua a implementação da classe CXAPOBase do método IXAPO::LockForProcess .

    Substituir LockForProcess permite que informações sobre o formato de dados de áudio sejam armazenadas para uso em IXAPO::P rocess.

  3. Implemente o método IXAPO::P rocess .

    XAudio2 chama o método IXAPO::P rocess sempre que um XAPO precisa processar dados de áudio. O processo contém a maior parte do código para um XAPO.

Implementando o método process

O método IXAPO::P rocess aceita buffers de fluxo para dados de áudio de entrada e saída. Um XAPO típico espera um buffer de fluxo de entrada e um buffer de fluxo de saída. Você deve basear o processamento de dados do buffer de fluxo de entrada no formato especificado na função LockForProcess e quaisquer sinalizadores passados para a função Process com o buffer de fluxo de entrada. Copie os dados de buffer de fluxo de entrada processados para o buffer de fluxo de saída. Defina o parâmetro BufferFlags do buffer de fluxo de saída como XAPO_BUFFER_VALID ou XAPO_BUFFER_SILENT.

O exemplo a seguir demonstra uma implementação de LockForProcess e Process que simplesmente copia dados de um buffer de entrada para um buffer de saída. No entanto, não haverá processamento se o buffer de entrada estiver marcado com 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

}

Ao escrever um método Process , é importante observar que os dados de áudio XAudio2 são intercalados. Isso significa que os dados de cada canal são adjacentes para um número de exemplo específico. Por exemplo, se houver uma onda de 4 canais sendo reproduzida em uma voz de origem XAudio2, os dados de áudio serão uma amostra do canal 0, uma amostra do canal 1, uma amostra do canal 2, um exemplo do canal 3 e, em seguida, o próximo exemplo de canais 0, 1, 2, 3 e assim por diante.

Efeitos de áudio

Visão geral do XAPO