방법: XAPO 만들기

XAPO API는 새 XAPO 형식을 빌드하기 위한 IXAPO 인터페이스 및 CXAPOBase 클래스를 제공합니다. IXAPO 인터페이스에는 새 XAPO를 만들기 위해 구현해야 하는 모든 메서드가 포함되어 있습니다. CXAPOBase 클래스는 IXAPO 인터페이스의 기본 구현을 제공합니다. CXAPOBase는 각 XAPO에 고유한 IXAPO::P rocess 메서드를 제외한 모든 IXAPO 인터페이스 메서드를 구현합니다.

새 정적 XAPO를 만들려면

  1. CXAPOBase 기본 클래스에서 새 XAPO 클래스를 파생합니다.

    참고

    XAPO는 IUnknown 인터페이스를 구현합니다. IXAPOIXAPOParameters 인터페이스에는 QueryInterface, AddRefRelease의 세 가지 IUnknown 메서드가 포함됩니다. CXAPOBase세 가지 IUnknown 메서드의 구현을 모두 제공합니다. CXAPOBase의 새 instance 참조 수는 1입니다. 참조 수가 0이 되면 제거됩니다. XAudio2가 더 이상 필요하지 않을 때 XAPO의 instance 삭제할 수 있도록 하려면 XAudio2 효과 체인에 추가된 후 XAPO에서 IUnknown::Release를 호출합니다. XAudio2에서 XAPO를 사용하는 방법에 대한 자세한 내용은 방법: XAudio2에서 XAPO 사용을 참조하세요.

     

  2. IXAPO::LockForProcess 메서드의 CXAPOBase 클래스 구현을 재정의합니다.

    LockForProcess를 재정의하면 오디오 데이터 형식에 대한 정보를 IXAPO::P rocess에 사용할 수 있도록 저장할 수 있습니다.

  3. IXAPO::P rocess 메서드를 구현합니다.

    XAudio2는 XAPO가 오디오 데이터를 처리해야 할 때마다 IXAPO::P rocess 메서드를 호출합니다. 프로세스 에는 XAPO에 대한 코드의 대부분이 포함됩니다.

Process 메서드 구현

IXAPO::P rocess 메서드는 입력 및 출력 오디오 데이터에 대한 스트림 버퍼를 허용합니다. 일반적인 XAPO에는 하나의 입력 스트림 버퍼와 하나의 출력 스트림 버퍼가 예상됩니다. 입력 스트림 버퍼의 데이터 처리는 LockForProcess 함수에 지정된 형식과 입력 스트림 버퍼를 사용하여 Process 함수에 전달된 플래그를 기반으로 해야 합니다. 처리된 입력 스트림 버퍼 데이터를 출력 스트림 버퍼에 복사합니다. 출력 스트림 버퍼의 BufferFlags 매개 변수를 XAPO_BUFFER_VALID 또는 XAPO_BUFFER_SILENT 설정합니다.

다음 예제에서는 입력 버퍼에서 출력 버퍼로 데이터를 복사하는 LockForProcessProcess 구현을 보여 줍니다. 그러나 입력 버퍼가 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 개요