Руководство: создание XAPO
API XAPO предоставляет интерфейс IXAPO и класс CXAPOBase для создания новых типов XAPO. Интерфейс IXAPO содержит все методы, которые необходимо реализовать для создания нового объекта XAPO. Класс CXAPOBase предоставляет базовую реализацию интерфейса IXAPO . CXAPOBase реализует все методы интерфейса IXAPO , за исключением метода IXAPO::P rocess , уникального для каждого XAPO.
Создание статического XAPO
Наследуйте новый класс XAPO от базового класса CXAPOBase .
Примечание
XAPOs реализуют интерфейс IUnknown . Интерфейсы IXAPO и IXAPOParameters включают три метода IUnknown : QueryInterface, AddRef и Release. CXAPOBase предоставляет реализации всех трех методов IUnknown . Новый экземпляр CXAPOBase будет иметь число ссылок 1. Он будет уничтожен, когда число ссылок станет 0. Чтобы разрешить XAudio2 уничтожать экземпляр XAPO, когда он больше не нужен, вызовите IUnknown::Release в XAPO после его добавления в цепочку эффектов XAudio2. Дополнительные сведения об использовании XAPO с XAudio2 см. в статье Практическое руководство. Использование XAPO в XAudio2 .
Переопределите реализацию класса CXAPOBase метода IXAPO::LockForProcess .
Переопределение LockForProcess позволяет хранить сведения о формате звуковых данных для использования в IXAPO::P rocess.
Реализуйте метод IXAPO::P rocess .
XAudio2 вызывает метод IXAPO::P rocess всякий раз, когда XAPO требуется обработать звуковые данные. Процесс содержит основную часть кода для XAPO.
Реализация метода Process
Метод IXAPO::P rocess принимает буферы потока для входных и выходных звуковых данных. Типичный XAPO ожидает один буфер входного потока и один буфер выходного потока. Обработка данных из буфера входного потока должна основываться на формате, указанном в функции LockForProcess , и всех флагах, передаваемых в функцию Process с буфером входного потока. Скопируйте данные обработанного буфера входного потока в буфер выходного потока. Задайте параметр BufferFlags буфера выходного потока как XAPO_BUFFER_VALID или XAPO_BUFFER_SILENT.
В следующем примере демонстрируется реализация LockForProcess и Process , которая просто копирует данные из входного буфера в выходной буфер. Однако обработка не выполняется, если входной буфер помечен 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
}
При написании метода Process важно отметить чередование аудиоданных XAudio2. Это означает, что данные из каждого канала являются смежными для определенного номера выборки. Например, если в исходном голосе XAudio2 воспроизводит 4-канальный канал, звуковые данные — это образец канала 0, образец канала 1, образец канала 2, образец канала 3, а затем следующая выборка каналов 0, 1, 2, 3 и т. д.
Связанные темы