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
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 .
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.
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.
Argomenti correlati