Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Not
Det här innehållet gäller endast för skrivbordsappar (och kräver revision för att fungera i en UWP-app). Se dokumentationen för CreateFile2, CreateEventEx, WaitForSingleObjectEx, SetFilePointerExoch GetOverlappedResultEx. Se SoundFileReader.h och .cpp i BasicSound Windows 8-exempelappen från det nu arkiverade Windows SDK-exempelgalleriet.
Så här fyller du i de strukturer som krävs för att spela upp ljuddata i XAudio2:
- Du kan läsa in eller strömma en ljudfil,
- eller så kan du generera en egen vågform och representera vågformen som exempel i en buffert (se Ett enkelt XAudio2-projekt i full).
Det här avsnittet fokuserar på metoden för att läsa in en ljudfil. Följande steg läser in fmt och data segment i en ljudfil och använder dem för att fylla i en WAVEFORMATEXTENSIBLE- struktur och en XAUDIO2_BUFFER struktur.
Förbereder parsning av ljudfilen
Ljudfiler som stöds av XAudio2 formateras med RIFF (Resource Interchange File Format). RIFF beskrivs i avsnittet RIFF (Resource Interchange File Format). Ljuddata i en RIFF-fil läses in genom att hitta RIFF-segmentet och sedan loopa genom segmentet för att hitta enskilda segment som finns i RIFF-segmentet. Följande funktioner är exempel på kod för att hitta segment och läsa in data som finns i segmenten.
Så här hittar du ett segment i en RIFF-fil:
#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; }Så här läser du data i ett segment efter att de har hittats.
När ett önskat segment hittas kan dess data läsas genom att justera filpekaren till början av dataavsnittet i segmentet. En funktion för att läsa data från ett segment när den hittas kan se ut så här.
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; }
Fylla i XAudio2-strukturer med innehållet i RIFF-chunkar
För att XAudio2 ska kunna spela upp ljud med en källröst behöver den en WAVEFORMATEX- struktur och en XAUDIO2_BUFFER struktur. Den WAVEFORMATEX- strukturen kan vara en större struktur, till exempel WAVEFORMATEXTENSIBLE- som innehåller en WAVEFORMATEX- struktur som sin första medlem. Mer information finns på referenssidan WAVEFORMATEX.
I det här exemplet används en WAVEFORMATEXTENSIBLE- för att tillåta inläsning av PCM-ljudfiler med fler än två kanaler.
Följande steg illustrerar hur du använder funktionerna som beskrivs ovan för att fylla i en WAVEFORMATEXTENSIBLE- struktur och en XAUDIO2_BUFFER struktur. I det här fallet innehåller ljudfilen som läses in PCM-data och innehåller endast ett RIFF-, fmt- och datasegment. Andra format kan innehålla ytterligare segmenttyper enligt beskrivningen i RIFF (Resource Interchange File Format).
Deklarera WAVEFORMATEXTENSIBLE- och XAUDIO2_BUFFER-strukturer.
WAVEFORMATEXTENSIBLE wfx = {0}; XAUDIO2_BUFFER buffer = {0};Öppna ljudfilen med 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() );Leta upp RIFF-segmentet i ljudfilen och kontrollera filtypen.
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;Leta upp 'fmt'-segmentet och kopiera dess innehåll till en WAVEFORMATEXTENSIBLE-struktur .
FindChunk(hFile,fourccFMT, dwChunkSize, dwChunkPosition ); ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition );Leta upp datasegmentet och läs dess innehåll i en buffert.
//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);Fyll i en XAUDIO2_BUFFER struktur.
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