共用方式為


如何:在 XAudio2 中載入音訊資料檔

注意

此內容僅適用於傳統型應用程式(且需要修訂才能在 UWP 應用程式中運作)。 請參閱 CreateFile2、CreateEventEx、WaitForSingleObjectExSetFilePointerEx 和 GetOverlappedResultEx 的檔。 從現在封存的 Windows SDK 範例資源庫,查看 SoundFileReader.h BasicSound Windows 8 範例應用程式中的 和 .cpp

若要填入在 XAudio2 中播放音訊資料所需的結構:

  • 您可以載入或串流音訊檔案,
  • 或者,您可以產生自己的超聲波,並以緩衝區中的樣本表示該電壓(請參閱 完整的簡單 XAudio2 專案)。

本主題著重於載入音訊檔案的方法。 下列步驟會載入音訊檔案的 fmt 和 區塊,並使用它們來填入 SEMANTICATEXTENSIBLE 結構和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 以來源語音播放音訊,它需要有一個 SOSATEX 結構和 XAUDIO2_BUFFER 結構。 波解X 結構可能是較大的結構,例如,包含作為其第一個成員的波解XTENSIBLE。 如需詳細資訊, 請參閱>>> >參考頁面。

在此範例中,有一個有兩個以上通道的 PCM 音訊檔案載入時,會使用有一個 感波 道。

下列步驟說明如何使用上述的函式來填入 波情ATEXTENSIBLE 結構和 XAUDIO2_BUFFER 結構。 在此情況下,載入的音訊檔案包含 PCM 數據,而且只會包含 'RIFF'、'fmt '和 'data' 區塊。 其他格式可能包含其他區塊類型,如資源交換檔格式 (RIFF) 中所述

  1. 宣告 工作訊號TENSIBLEXAUDIO2_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』 區塊,並將其內容 複製到「電壓」ATEXTENSIBLE 結構中。

    FindChunk(hFile,fourccFMT, dwChunkSize, dwChunkPosition );
    ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition );
    
  5. 找出 「數據」區塊,並將其內容讀入緩衝區。

    //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