다음을 통해 공유


방법: XAudio2에서 오디오 데이터 파일 로드

참고 항목

이 콘텐츠는 데스크톱 앱에만 적용되며 UWP 앱에서 작동하려면 수정이 필요합니다. CreateFile2, CreateEventEx, WaitForSingleObjectEx, SetFilePointerEx 및 GetOverlappedResultEx에 대한 설명서를 참조하세요. .cpp 현재 보관된 Windows SDK 샘플 갤러리의 BasicSound Windows 8 샘플 앱을 참조 SoundFileReader.h 하세요.

XAudio2에서 오디오 데이터를 재생하는 데 필요한 구조를 채우려면 다음을 수행합니다.

  • 오디오 파일을 로드하거나 스트리밍할 수 있습니다.
  • 또는 고유한 파형을 생성하고 해당 파형을 버퍼의 샘플로 나타낼 수 있습니다(전체의 간단한 XAudio2 프로젝트 참조).

이 항목에서는 오디오 파일을 로드하는 방법에 중점을 둡니다. 다음 단계에서는 오디오 파일의 청크 및 청크를 로드 fmt 하고 이를 사용하여 WAVEFORMATEXTENSIBLE 구조체와 XAUDIO2_BUFFER 구조를 채웁니다.data

오디오 파일 구문 분석 준비

XAudio2에서 지원하는 오디오 파일은 RIFF(리소스 교환 파일 형식)로 형식이 지정됩니다. RIFF는 RIFF(리소스 교환 파일 형식) 항목 에 설명되어 있습니다. RIFF 파일의 오디오 데이터는 RIFF 청크를 찾은 다음 청크를 반복하여 RIFF 청크에 포함된 개별 청크를 찾아 로드됩니다. 다음 함수는 청크를 찾고 청크에 포함된 데이터를 로드하는 코드의 예입니다.

  • RIFF 파일에서 청크를 찾으려면 다음을 수행합니다.

    #ifdef _XBOX //Big-Endian
    #define fourccRIFF 'RIFF'
    #define fourccDATA 'data'
    #define fourccFMT 'fmt '
    #define fourccWAVE 'WAVE'
    #define fourccXWMA 'XWMA'
    #define fourccDPDS 'dpds'
    #endif
    
    #ifndef _XBOX //Little-Endian
    #define fourccRIFF 'FFIR'
    #define fourccDATA 'atad'
    #define fourccFMT ' tmf'
    #define fourccWAVE 'EVAW'
    #define fourccXWMA 'AMWX'
    #define fourccDPDS 'sdpd'
    #endif
    HRESULT FindChunk(HANDLE hFile, DWORD fourcc, DWORD & dwChunkSize, DWORD & dwChunkDataPosition)
    {
        HRESULT hr = S_OK;
        if( INVALID_SET_FILE_POINTER == SetFilePointer( hFile, 0, NULL, FILE_BEGIN ) )
            return HRESULT_FROM_WIN32( GetLastError() );
    
        DWORD dwChunkType;
        DWORD dwChunkDataSize;
        DWORD dwRIFFDataSize = 0;
        DWORD dwFileType;
        DWORD bytesRead = 0;
        DWORD dwOffset = 0;
    
        while (hr == S_OK)
        {
            DWORD dwRead;
            if( 0 == ReadFile( hFile, &dwChunkType, sizeof(DWORD), &dwRead, NULL ) )
                hr = HRESULT_FROM_WIN32( GetLastError() );
    
            if( 0 == ReadFile( hFile, &dwChunkDataSize, sizeof(DWORD), &dwRead, NULL ) )
                hr = HRESULT_FROM_WIN32( GetLastError() );
    
            switch (dwChunkType)
            {
            case fourccRIFF:
                dwRIFFDataSize = dwChunkDataSize;
                dwChunkDataSize = 4;
                if( 0 == ReadFile( hFile, &dwFileType, sizeof(DWORD), &dwRead, NULL ) )
                    hr = HRESULT_FROM_WIN32( GetLastError() );
                break;
    
            default:
                if( INVALID_SET_FILE_POINTER == SetFilePointer( hFile, dwChunkDataSize, NULL, FILE_CURRENT ) )
                return HRESULT_FROM_WIN32( GetLastError() );            
            }
    
            dwOffset += sizeof(DWORD) * 2;
    
            if (dwChunkType == fourcc)
            {
                dwChunkSize = dwChunkDataSize;
                dwChunkDataPosition = dwOffset;
                return S_OK;
            }
    
            dwOffset += dwChunkDataSize;
    
            if (bytesRead >= dwRIFFDataSize) return S_FALSE;
    
        }
    
        return S_OK;
    }
    
  • 청크가 배치된 후 청크에서 데이터를 읽으려면

    원하는 청크가 발견되면 청크의 데이터 섹션 시작 부분에 대한 파일 포인터를 조정하여 해당 데이터를 읽을 수 있습니다. 청크가 발견되면 청크에서 데이터를 읽는 함수는 다음과 같습니다.

    HRESULT ReadChunkData(HANDLE hFile, void * buffer, DWORD buffersize, DWORD bufferoffset)
    {
        HRESULT hr = S_OK;
        if( INVALID_SET_FILE_POINTER == SetFilePointer( hFile, bufferoffset, NULL, FILE_BEGIN ) )
            return HRESULT_FROM_WIN32( GetLastError() );
        DWORD dwRead;
        if( 0 == ReadFile( hFile, buffer, buffersize, &dwRead, NULL ) )
            hr = HRESULT_FROM_WIN32( GetLastError() );
        return hr;
    }
    

RIFF 청크의 내용으로 XAudio2 구조체 채우기

XAudio2가 원본 음성으로 오디오를 재생하려면 WAVEFORMATEX 구조와 XAUDIO2_BUFFER 구조가 필요합니다. WAVEFORMATEX 구조체는 WAVEFORMATEX 구조체를 첫 번째 멤버로 포함하는 WAVEFORMATEXTENSIBLE과 같은 더 큰 구조체일 수 있습니다. 자세한 내용은 WAVEFORMATEX 참조 페이지를 참조하세요.

이 예제 에서는 WAVEFORMATEXTENSIBLE 을 사용하여 두 개 이상의 채널이 있는 PCM 오디오 파일을 로드할 수 있습니다.

다음 단계에서는 위에서 설명한 함수를 사용하여 WAVEFORMATEXTENSIBLE 구조체 및 XAUDIO2_BUFFER 구조를 채우는 방법을 보여 줍니다. 이 경우 로드되는 오디오 파일에는 PCM 데이터가 포함되며 'RIFF', 'fmt' 및 'data' 청크만 포함됩니다. 다른 형식은 RIFF(리소스 교환 파일 형식)설명된 대로 추가 청크 형식을 포함할 수 있습니다.

  1. WAVEFORMATEXTENSIBLEXAUDIO2_BUFFER 구조를 선언합니다.

    WAVEFORMATEXTENSIBLE wfx = {0};
    XAUDIO2_BUFFER buffer = {0};
    
  2. CreateFile을 사용하여 오디오 파일을 엽니다.

    #ifdef _XBOX
    char * strFileName = "game:\\media\\MusicMono.wav";
    #else
    TCHAR * strFileName = _TEXT("media\\MusicMono.wav");
    #endif
    // Open the file
    HANDLE hFile = CreateFile(
        strFileName,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        0,
        NULL );
    
    if( INVALID_HANDLE_VALUE == hFile )
        return HRESULT_FROM_WIN32( GetLastError() );
    
    if( INVALID_SET_FILE_POINTER == SetFilePointer( hFile, 0, NULL, FILE_BEGIN ) )
        return HRESULT_FROM_WIN32( GetLastError() );
    
  3. 오디오 파일에서 'RIFF' 청크를 찾아 파일 형식을 확인합니다.

    DWORD dwChunkSize;
    DWORD dwChunkPosition;
    //check the file type, should be fourccWAVE or 'XWMA'
    FindChunk(hFile,fourccRIFF,dwChunkSize, dwChunkPosition );
    DWORD filetype;
    ReadChunkData(hFile,&filetype,sizeof(DWORD),dwChunkPosition);
    if (filetype != fourccWAVE)
        return S_FALSE;
    
  4. 'fmt' 청크를 찾아 해당 내용을 WAVEFORMATEXTENSIBLE 구조체로 복사합니다.

    FindChunk(hFile,fourccFMT, dwChunkSize, dwChunkPosition );
    ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition );
    
  5. 'data' 청크를 찾아 해당 내용을 버퍼로 읽습니다.

    //fill out the audio data buffer with the contents of the fourccDATA chunk
    FindChunk(hFile,fourccDATA,dwChunkSize, dwChunkPosition );
    BYTE * pDataBuffer = new BYTE[dwChunkSize];
    ReadChunkData(hFile, pDataBuffer, dwChunkSize, dwChunkPosition);
    
  6. XAUDIO2_BUFFER 구조를 채웁다.

    buffer.AudioBytes = dwChunkSize;  //size of the audio buffer in bytes
    buffer.pAudioData = pDataBuffer;  //buffer containing audio data
    buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer