So wird's gemacht: Laden von Datendateien in XAudio2
Hinweis
Dieser Inhalt gilt nur für Desktop-Apps und erfordert eine Revision, um in einer Windows Store-App zu funktionieren. Weitere Informationen finden Sie in der Dokumentation zu CreateFile2, CreateEventEx, WaitForSingleObjectEx, SetFilePointerExund GetOverlappedResultEx. Weitere Informationen finden Sie unter SoundFileReader.h/.cpp im BasicSound Windows 8-Beispiel aus dem Windows SDK-Beispielkatalog.
In diesem Thema werden die Schritte zum Auffüllen der Strukturen beschrieben, die zum Wiedergeben von Audiodaten in XAudio2 erforderlich sind. Die folgenden Schritte laden die Blöcke "fmt" und "data" einer Audiodatei und verwenden sie, um eine WAVEFORMATEXTENSIBLE-Struktur und eine XAUDIO2 _ BUFFER-Struktur aufzufüllen.
- Vorbereiten der Analyse der Audiodatei.
- Auffüllen von XAudio2-Strukturen mit dem Inhalt von CSV-Blöcken.
Vorbereiten der Analyse der Audiodatei
Audiodateien, die von XAudio2 unterstützt werden, verwenden das Resource Interchange File Format (DOSSIER). DER ABSCHNITT WIRD in der Übersicht über das Resource Interchange File Format (CSV) beschrieben. Audiodaten in einer CSV-Datei werden geladen, indem sie den CSV-Block suchen und dann den Block durchlaufen, um einzelne Blöcke zu finden, die im SEGMENT-Block enthalten sind. Die folgenden Funktionen sind Beispiele für Code zum Suchen von Segmenten und Laden von Daten, die in den Blöcken enthalten sind.
So suchen Sie einen Block in einer DATEIFORMAT-Datei:
#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; }So lesen Sie Daten in einem Block, nachdem sie gefunden wurden.
Sobald ein gewünschter Block gefunden wurde, können seine Daten gelesen werden, indem der Dateizeiger an den Anfang des Datenabschnitts des Blockes angepasst wird. Eine Funktion zum Lesen der Daten aus einem Block, sobald sie gefunden wurde, könnte wie folgt aussehen.
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; }
Auffüllen von XAudio2-Strukturen mit dem Inhalt von VERSA-Blöcken
Damit XAudio2 Audio mit einer Quellstimme wiedergeben kann, benötigen sie eine WAVEFORMATEX-Struktur und eine XAUDIO2 _ BUFFER-Struktur. Die WAVEFORMATEX-Struktur kann eine größere Struktur wie WAVEFORMATEXTENSIBLE sein, die eine WAVEFORMATEX-Struktur als erstes Element enthält. Weitere Informationen finden Sie auf der WAVEFORMATEX-Referenzseite.
In diesem Beispiel wird WAVEFORMATEXTENSIBLE verwendet, um das Laden von PCM-Audiodateien mit mehr als zwei Kanälen zu ermöglichen.
Die folgenden Schritte veranschaulichen die Verwendung der oben beschriebenen Funktionen, um eine WAVEFORMATEXTENSIBLE-Struktur und eine XAUDIO2 _ BUFFER-Struktur aufzufüllen. In diesem Fall enthält die zu ladende Audiodatei PCM-Daten und enthält nur den Block 'CSV', 'fmt ' und 'data'. Andere Formate können zusätzliche Blocktypen enthalten, wie in RESOURCE Interchange File Format (CSV)beschrieben.
Deklarieren Sie WAVEFORMATEXTENSIBLE- und XAUDIO2 _ BUFFER-Strukturen.
WAVEFORMATEXTENSIBLE wfx = {0}; XAUDIO2_BUFFER buffer = {0};Öffnen Sie die Audiodatei mit 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() );Suchen Sie in der Audiodatei nach dem Block "CSV", und überprüfen Sie den Dateityp.
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;Suchen Sie den Block "fmt", und kopieren Sie dessen Inhalt in eine WAVEFORMATEXTENSIBLE-Struktur.
FindChunk(hFile,fourccFMT, dwChunkSize, dwChunkPosition ); ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition );Suchen Sie den Datenabschnitt, und lesen Sie dessen Inhalt in einen Puffer.
//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);Füllen Sie eine XAUDIO2 _ BUFFER-Struktur auf.
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