Bagikan melalui


Cara: Memuat File Data Audio di XAudio2

Catatan

Konten ini hanya berlaku untuk aplikasi desktop dan akan memerlukan revisi untuk berfungsi di aplikasi Bursa Windows. Silakan lihat dokumentasi untuk CreateFile2, CreateEventEx, WaitForSingleObjectEx, SetFilePointerEx, dan GetOverlappedResultEx. Lihat SoundFileReader.h/.cpp dalam sampel BasicSound Windows 8 dari Galeri Sampel Windows SDK.

 

Topik ini menjelaskan langkah-langkah untuk mengisi struktur yang diperlukan untuk memutar data audio di XAudio2. Langkah-langkah berikut memuat potongan 'fmt ' dan 'data' dari file audio, dan menggunakannya untuk mengisi struktur WAVEFORMATEXTENSIBLE dan struktur XAUDIO2_BUFFER .

Bersiap untuk mengurai file audio

File audio yang didukung oleh XAudio2 menggunakan Format File Pertukaran Sumber Daya (RIFF). RIFF dijelaskan dalam gambaran umum Resource Interchange File Format (RIFF ). Data audio dalam file RIFF dimuat dengan menemukan gugus RIFF dan kemudian mengulangi potongan untuk menemukan potongan individual yang terkandung dalam gugus RIFF. Fungsi berikut adalah contoh kode untuk menemukan gugus dan memuat data yang terkandung dalam gugus.

  • Untuk menemukan gugus dalam file 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;
    
    }
    
  • Untuk membaca data dalam gugus setelah ditemukan.

    Setelah gugus yang diinginkan ditemukan, datanya dapat dibaca dengan menyesuaikan penunjuk file ke awal bagian data dari gugus. Fungsi untuk membaca data dari gugus setelah ditemukan mungkin terlihat seperti ini.

    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;
    }
    

Mengisi struktur XAudio2 dengan isi gugus RIFF

Agar XAudio2 dapat memutar audio dengan suara sumber, dibutuhkan struktur WAVEFORMATEX dan struktur XAUDIO2_BUFFER . Struktur WAVEFORMATEX mungkin merupakan struktur yang lebih besar seperti WAVEFORMATEXTENSIBLE yang berisi struktur WAVEFORMATEX sebagai anggota pertamanya. Lihat halaman referensi WAVEFORMATEX untuk informasi selengkapnya.

Dalam contoh ini , WAVEFORMATEXTENSIBLE sedang digunakan untuk memungkinkan pemuatan file audio PCM dengan lebih dari dua saluran.

Langkah-langkah berikut mengilustrasikan menggunakan fungsi yang dijelaskan di atas untuk mengisi struktur WAVEFORMATEXTENSIBLE dan struktur XAUDIO2_BUFFER . Dalam hal ini, file audio yang dimuat berisi data PCM, dan hanya akan berisi gugus 'RIFF', 'fmt ', dan 'data'. Format lain mungkin berisi jenis gugus tambahan seperti yang dijelaskan dalam Format File Pertukaran Sumber Daya (RIFF).

  1. Deklarasikan STRUKTUR WAVEFORMATEXTENSIBLE dan XAUDIO2_BUFFER .

    WAVEFORMATEXTENSIBLE wfx = {0};
    XAUDIO2_BUFFER buffer = {0};
    
  2. Buka file audio dengan 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() );
    
  3. Temukan gugus 'RIFF' dalam file audio, dan periksa jenis file.

    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;
    
  4. Temukan potongan 'fmt', dan salin isinya ke dalam struktur WAVEFORMATEXTENSIBLE .

    FindChunk(hFile,fourccFMT, dwChunkSize, dwChunkPosition );
    ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition );
    
  5. Temukan gugus 'data', dan baca kontennya ke dalam 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);
    
  6. Isi struktur 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
    

Memulai

Cara: Memutar Suara dengan XAudio2

Referensi Pemrograman XAudio2