Поделиться через


Руководство: создание XAPO

API XAPO предоставляет интерфейс IXAPO и класс CXAPOBase для создания новых типов XAPO. Интерфейс IXAPO содержит все методы, которые необходимо реализовать для создания нового объекта XAPO. Класс CXAPOBase предоставляет базовую реализацию интерфейса IXAPO . CXAPOBase реализует все методы интерфейса IXAPO , за исключением метода IXAPO::P rocess , уникального для каждого XAPO.

Создание статического XAPO

  1. Наследуйте новый класс 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 .

     

  2. Переопределите реализацию класса CXAPOBase метода IXAPO::LockForProcess .

    Переопределение LockForProcess позволяет хранить сведения о формате звуковых данных для использования в IXAPO::P rocess.

  3. Реализуйте метод 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 и т. д.

Звуковые эффекты

Обзор протокола XAPO