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
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 .
Ü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.
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.
Zugehörige Themen