Share via


Procedura: Creare un oggetto di elaborazione audio di XAudio2 (XAPO)

L'API XAPO fornisce l'interfaccia IXAPO e la classe CXAPOBase per la creazione di nuovi tipi XAPO. L'interfaccia IXAPO contiene tutti i metodi che devono essere implementati per creare un nuovo XAPO . La classe CXAPOBase fornisce un'implementazione di base dell'interfaccia IXAPO . CXAPOBase implementa tutti i metodi di interfaccia IXAPO , ad eccezione del metodo IXAPO::P rocess , univoco per ogni XAPO.

Per creare una nuova XAPO statica

  1. Derivare una nuova classe XAPO dalla classe di base CXAPOBase .

    Nota

    XAPOs implementa l'interfaccia IUnknown . Le interfacce IXAPO e IXAPOParameters includono i tre metodi IUnknown: QueryInterface, AddRef e Release. CXAPOBase fornisce implementazioni di tutti e tre i metodi IUnknown . Una nuova istanza di CXAPOBase avrà un numero di riferimenti pari a 1. Verrà distrutto quando il conteggio dei riferimenti diventa 0. Per consentire a XAudio2 di eliminare un'istanza di XAPO quando non è più necessaria, chiamare IUnknown::Release nella XAPO dopo l'aggiunta a una catena di effetti XAudio2. Per altre informazioni sull'uso di un XAPO con XAudio2, vedere Procedura: Usare una XAPO con XAudio2 .

     

  2. Eseguire l'override dell'implementazione della classe CXAPOBase del metodo IXAPO::LockForProcess .

    L'override di LockForProcess consente di archiviare informazioni sul formato di dati audio da archiviare per l'uso in IXAPO::P rocess.

  3. Implementare il metodo IXAPO::P rocess .

    XAudio2 chiama il metodo IXAPO::P rocess ogni volta che un XAPO deve elaborare i dati audio. Il processo contiene la maggior parte del codice per un XAPO.

Implementazione del metodo Process

Il metodo IXAPO::P rocess accetta buffer di flusso per i dati audio di input e output. Una tipica XAPO prevede un buffer di flusso di input e un buffer di flusso di output. È consigliabile basare l'elaborazione dei dati dal buffer di flusso di input nel formato specificato nella funzione LockForProcess e tutti i flag passati alla funzione Process con il buffer di flusso di input. Copiare i dati del buffer di flusso di input elaborati nel buffer di flusso di output. Impostare il parametro BufferFlags del buffer di output come XAPO_BUFFER_VALID o XAPO_BUFFER_SILENT.

Nell'esempio seguente viene illustrata un'implementazione di LockForProcess e Process che copia semplicemente i dati da un buffer di input a un buffer di output. Tuttavia, non esiste alcuna elaborazione se il buffer di input è contrassegnato con 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

}

Quando si scrive un metodo Process , è importante notare che i dati audio XAudio2 sono interleaved. Ciò significa che i dati di ogni canale sono adiacenti per un determinato numero di esempio. Ad esempio, se è presente un'onda a 4 canali che giocano in una voce di origine XAudio2, i dati audio sono un esempio di canale 0, un esempio di canale 1, un esempio di canale 2, un esempio di canale 3 e quindi il successivo esempio di canali 0, 1, 2, 3 e così via.

Effetti audio

Panoramica di XAPO