Руководство: загрузка файлов звуковых данных в XAudio2
Примечание
Это содержимое применяется только к классическим приложениям и потребует редакции для работы в приложении Магазина Windows. Ознакомьтесь с документацией по CreateFile2, CreateEventEx, WaitForSingleObjectEx, SetFilePointerEx и GetOverlappedResultEx. См. раздел SoundFileReader.h/.cpp в примере basicSound Windows 8 из коллекции примеров windows SDK.
В этом разделе описываются действия по заполнению структур, необходимых для воспроизведения звуковых данных в XAudio2. Следующие шаги загружают блоки "fmt" и "data" звукового файла и используют их для заполнения структуры WAVEFORMATEXTENSIBLE и структуры 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; }
Заполнение структур XAudio2 содержимым блоков RIFF
Чтобы XAudio2 воспроизводил звук с помощью исходного голоса, ему требуется структура WAVEFORMATEX и структура XAUDIO2_BUFFER . Структура WAVEFORMATEX может быть более крупной, например WAVEFORMATEXTENSIBLE , которая содержит структуру WAVEFORMATEX в качестве первого члена. Дополнительные сведения см. на справочной странице WAVEFORMATEX .
В этом примере используется WAVEFORMATEXTENSIBLE , чтобы разрешить загрузку аудиофайлов PCM с более чем двумя каналами.
Следующие шаги демонстрируют использование описанных выше функций для заполнения структуры WAVEFORMATEXTENSIBLE и структуры XAUDIO2_BUFFER . В этом случае загружаемый звуковой файл содержит данные PCM и будет содержать только фрагменты RIFF, fmt и data. Другие форматы могут содержать дополнительные типы блоков, как описано в разделе Формат файла обмена ресурсами (RIFF).
Объявите структуры WAVEFORMATEXTENSIBLE и 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 и скопируйте его содержимое в структуру WAVEFORMATEXTENSIBLE .
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 Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по