Freigeben über


So wird's gemacht: Erstellen eines XAPOs

Die XAPO-API stellt die IXAPO-Schnittstelle und die CXAPOBase-Klasse zum Erstellen neuer XAPO-Typen bereit. Die IXAPO-Schnittstelle enthält alle Methoden, die implementiert werden müssen, um ein neues XAPO zu erstellen. Die CXAPOBase-Klasse bietet eine grundlegende Implementierung der IXAPO-Schnittstelle . CXAPOBase implementiert alle IXAPO-Schnittstellenmethoden mit Ausnahme der IXAPO::P rocess-Methode , die für jeden XAPO eindeutig ist.

So erstellen Sie ein neues statisches XAPO

  1. Leiten Sie eine neue XAPO-Klasse von der CXAPOBase-Basisklasse ab.

    Hinweis

    XAPOs implementieren die IUnknown-Schnittstelle . Die IXAPO- und IXAPOParameters-Schnittstellen umfassen die drei IUnknown-Methoden: QueryInterface, AddRef und Release. CXAPOBase bietet Implementierungen aller drei IUnknown-Methoden . Eine neue instance von CXAPOBase weist die Referenzanzahl 1 auf. Sie wird zerstört, wenn die Referenzanzahl 0 wird. Damit XAudio2 eine instance eines XAPO zerstören kann, wenn er nicht mehr benötigt wird, rufen Sie IUnknown::Release auf dem XAPO auf, nachdem sie einer XAudio2-Effektkette hinzugefügt wurde. Weitere Informationen zur Verwendung eines XAPO mit XAudio2 finden Sie unter Vorgehensweise: Verwenden eines XAPO in XAudio2 .

     

  2. Überschreiben Sie die CXAPOBase-Klassenimplementierung der IXAPO::LockForProcess-Methode .

    Durch das Überschreiben von LockForProcess können Informationen über das Format von Audiodaten für die Verwendung in IXAPO::P rocess gespeichert werden.

  3. Implementieren Sie die IXAPO::P rocess-Methode .

    XAudio2 ruft die IXAPO::P rocess-Methode auf, wenn ein XAPO Audiodaten verarbeiten muss. Der Prozess enthält den Großteil des Codes für ein XAPO.

Implementieren der Prozessmethode

Die IXAPO::P rocess-Methode akzeptiert Streampuffer für Eingabe- und Ausgabeaudiodaten. Ein typischer XAPO erwartet einen Eingabedatenstrompuffer und einen Ausgabestreampuffer. Sie sollten die Verarbeitung von Daten aus dem Eingabedatenstrompuffer auf das in der LockForProcess-Funktion angegebene Format und alle Flags basieren, die mit dem Eingabestreampuffer an die Process-Funktion übergeben werden. Kopieren Sie die verarbeiteten Eingabedaten des Datenstrompuffers in den Ausgabestreampuffer. Legen Sie den BufferFlags-Parameter des Ausgabedatenstrompuffers auf XAPO_BUFFER_VALID oder XAPO_BUFFER_SILENT fest.

Im folgenden Beispiel wird eine LockForProcess - und Process-Implementierung veranschaulicht, die einfach Daten aus einem Eingabepuffer in einen Ausgabepuffer kopiert. Es gibt jedoch keine Verarbeitung, wenn der Eingabepuffer mit XAPO_BUFFER_SILENT gekennzeichnet ist.

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

}

Beim Schreiben einer Process-Methode ist es wichtig zu beachten, dass XAudio2-Audiodaten verschachtelt sind. Dies bedeutet, dass Daten aus jedem Kanal für eine bestimmte Beispielnummer nebeneinander stehen. Wenn beispielsweise eine 4-Kanal-Welle in einer XAudio2-Quellstimme wiedergegeben wird, sind die Audiodaten ein Beispiel für Kanal 0, ein Beispiel für Kanal 1, ein Beispiel für Kanal 2, ein Beispiel von Kanal 3 und dann das nächste Beispiel der Kanäle 0, 1, 2, 3 usw.

Audioeffekte

XAPO–Übersicht