Como: Carregar arquivos de dados de áudio no XAudio2
Observação
Esse conteúdo se aplica somente a aplicativos da área de trabalho e exigirá revisão para funcionar em um aplicativo da Windows Store. Consulte a documentação de CreateFile2, CreateEventEx, WaitForSingleObjectEx, SetFilePointerEx e GetOverlappedResultEx. Consulte SoundFileReader.h/.cpp no exemplo Windows 8 BasicSound da Galeria de Exemplos do SDK do Windows.
Este tópico descreve as etapas para preencher as estruturas necessárias para reproduzir dados de áudio no XAudio2. As etapas a seguir carregam as partes 'fmt' e 'data' de um arquivo de áudio e as usam para preencher uma estrutura WAVEFORMATEXTENSIBLE e uma estrutura XAUDIO2_BUFFER .
- Preparando-se para analisar o arquivo de áudio.
- Preenchendo estruturas XAudio2 com o conteúdo de partes RIFF.
Preparando-se para analisar o arquivo de áudio
Os arquivos de áudio compatíveis com o XAudio2 usam o RIFF (Formato de Arquivo de Intercâmbio de Recursos). O RIFF é descrito na visão geral do RIFF (Resource Interchange File Format ). Os dados de áudio em um arquivo RIFF são carregados localizando a parte RIFF e, em seguida, executando um loop pela parte para localizar partes individuais contidas na parte RIFF. As funções a seguir são exemplos de código para localizar partes e carregar dados contidos nas partes.
Para localizar uma parte em um arquivo 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; }
Para ler dados em uma parte depois que eles tiverem sido localizados.
Depois que uma parte desejada é encontrada, seus dados podem ser lidos ajustando o ponteiro do arquivo para o início da seção de dados da parte. Uma função para ler os dados de uma parte depois que ele for encontrado pode ter esta aparência.
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; }
Preenchendo estruturas XAudio2 com o conteúdo de partes RIFF
Para que o XAudio2 reproduza áudio com uma voz de origem, ele precisa de uma estrutura WAVEFORMATEX e uma estrutura XAUDIO2_BUFFER . A estrutura WAVEFORMATEX pode ser uma estrutura maior, como WAVEFORMATEXTENSIBLE , que contém uma estrutura WAVEFORMATEX como seu primeiro membro. Consulte a página de referência WAVEFORMATEX para obter mais informações.
Neste exemplo, um WAVEFORMATEXTENSIBLE está sendo usado para permitir o carregamento de arquivos de áudio PCM com mais de dois canais.
As etapas a seguir ilustram o uso das funções descritas acima para preencher uma estrutura WAVEFORMATEXTENSIBLE e uma estrutura XAUDIO2_BUFFER . Nesse caso, o arquivo de áudio que está sendo carregado contém dados pcm e conterá apenas uma parte 'RIFF', 'fmt ' e 'data'. Outros formatos podem conter tipos de partes adicionais, conforme descrito em RIFF (Formato de Arquivo de Intercâmbio de Recursos).
Declare WAVEFORMATEXTENSIBLE e XAUDIO2_BUFFER estruturas.
WAVEFORMATEXTENSIBLE wfx = {0}; XAUDIO2_BUFFER buffer = {0};
Abra o arquivo de áudio com 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() );
Localize a parte 'RIFF' no arquivo de áudio e marcar o tipo de arquivo.
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;
Localize a parte 'fmt' e copie seu conteúdo em uma estrutura WAVEFORMATEXTENSIBLE .
FindChunk(hFile,fourccFMT, dwChunkSize, dwChunkPosition ); ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition );
Localize a parte "dados" e leia seu conteúdo em um buffer.
//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);
Preencha uma estrutura de 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
Tópicos relacionados
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de