【XAudio2】7.如何加载音频数据文件

7.如何加载音频数据文件

本主题描述的步骤来填充所需的结构在XAudio2播放音频数据。以下步骤加载“fmt”和“data”块的一个音频文件,并使用它们来填充WAVEFORMATEXTENSIBLE结构和一个XAUDIO2_BUFFER结构。

  • 准备解析音频文件。
  • 填充XAudio2结构即兴重复的内容块。 

准备解析音频文件。

支持的音频文件XAudio2使用资源文件交换格式(RIFF)。Resource Interchange File Format (RIFF)主题描述了RIFF。音频数据在RIFF文件中是通过遍历加载可用的RIFF块。以下代码展示了查找块并从块中加载数据。

  • 从RIFF文件查找一个块(chunk)

请注意
windows是小端,Xbox 360是大端。音频文件上创建Windows使用Xbox 360需要的部分或全部数据交换字节序在运行时,或音频文件需要被处理在运行时执行字节交换。有关更多信息,请参见音频数据和字节顺序

  • #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”的块。其他格式可能包含额外的块类型在Resource Interchange File Format (RIFF)。

1.定义 WAVEFORMATEXTENSIBLE 和 XAUDIO2_BUFFER结构体。

 

  1. WAVEFORMATEXTENSIBLE wfx = {0};
    XAUDIO2_BUFFER buffer = {0};

2.用CreateFile打开音频文件

  1. #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.在音频文件中定位"RIFF"块,和检查文件类型

  1. 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.定位"fmt" 块,然后复制内容到WAVEFORMATEXTENSIBLE结构体

  1. FindChunk(hFile,fourccFMT, dwChunkSize, dwChunkPosition );
    ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition );

5.定位"data"块,然后读取内容到一个缓存

  1. //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.填充一个XAUDIO2_BUFFER 结构体

  1. buffer.AudioBytes = dwChunkSize;  //buffer containing audio data
    buffer.pAudioData = pDataBuffer;  //size of the audio buffer in bytes
    buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值