使用方法:在 XAudio2 中載入音訊資料檔
注意
此內容僅適用于傳統型應用程式,而且需要修訂才能在 Windows 市集應用程式中運作。 請參閱 CreateFile2、 CreateEventEx、 WaitForSingleObjectEx、 SetFilePointerEx和 GetOverlappedResultEx的檔。 請參閱Windows SDK 範例庫中BasicSound Windows 8 範例中的 SoundFileReader.h/.cpp。
本主題描述在 XAudio2 中填入播放音訊資料所需結構的步驟。 下列步驟會載入音訊檔案的 'fmt' 和 'data' 區塊,並使用這些區塊來填入 一個顯示型 態和 XAUDIO2_BUFFER 結構。
準備剖析音訊檔案
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 使用來源語音播放音訊,它需要一個XAUDIO2_BUFFER結構。 在包含其第一個成員的顯示方式中,「」的「顯示」XTENSIBLE結構,可能會是較大的結構,例如包含其第一個成員的一個。」 如需詳細資訊,請參閱 「要求」 參考頁面。
在此範例中, 使用一個包含 兩個以上通道的 PCM 音訊檔案,來允許載入包含兩個以上的通道的 PCM 音訊檔案。
下列步驟說明如何使用上述的函式來填入XAUDIO2_BUFFER結構及XAUDIO2_BUFFER結構。 在此情況下,載入的音訊檔案包含 PCM 資料,而且只會包含 'RIFF'、'fmt '和 'data' 區塊。 其他格式可能包含其他區塊類型,如 資源交換檔案格式 (RIFF) 中所述。
宣告XAUDIO2_BUFFER結構。
WAVEFORMATEXTENSIBLE wfx = {0}; XAUDIO2_BUFFER buffer = {0};
使用 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() );
在音訊檔案中找出 '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;
找出 'fmt' 區塊,並將其內容複寫到 [][顯示][XTENSIBLE ] 結構。
FindChunk(hFile,fourccFMT, dwChunkSize, dwChunkPosition ); ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition );
找出 '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);
填入 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
相關主題
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應