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

【XAudio2】7.如何加载音频数据文件相关推荐

  1. loadmat()函数加载.mat数据文件

    loadmat()函数源码如下: def loadmat(file_name, mdict=None, appendmat=True, **kwargs):variable_names = kwarg ...

  2. ios网络学习------4 UIWebView的加载本地数据的三种方式

    ios网络学习------4 UIWebView的加载本地数据的三种方式 分类: IOS2014-06-27 12:56 959人阅读 评论(0) 收藏 举报 UIWebView是IOS内置的浏览器, ...

  3. 216:vue+openlayers 加载GPX数据,导出geojson文件

    第216个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中加载GPX数据,显示图形, 导出geojson文件. GPX(GPS eXchange Format,GPS交换 ...

  4. PTMs:QLoRA技巧之源码解读(qlora.py文件)—解析命令与加载参数→数据预处理→模型训练+评估+推理

    PTMs:QLoRA技巧之源码解读(qlora.py文件)-解析命令与加载参数→数据预处理→模型训练+评估+推理 目录 QLoRA技巧之源码解读(qlora.py文件)-解析命令与加载参数→数据预处理 ...

  5. MP4 格式:最少加载多少数据就能渲染出视频首帧?优化短视频播放体验必须先了解它丨音视频基础

    (本文基本逻辑:MP4 封装格式概览 → 重要 Box 具体信息介绍 → 实战中对 MP4 Box 信息的使用) MP4 也称为 MPEG-4 第 14 部分,是继承 MPEG-4 第 12 部分的 ...

  6. spark-submit --files 动态加载外部资源文件

    在做spark时,有些时候需要加载资源文件,需要在driver或者worker端访问.在client模式下可以使用IO流直接读取,但是在cluster模式下却不能直接读取,需要如下代码: val is ...

  7. Naigos PNP图无法加载最新数据

    Naigos PNP图无法加载最新数据 前几天IDC断电,设备全部重启,导致nagios pnp图无法正常加载,经过排查发下如下几点状况: 1,查看log日志,并没有报错. 2,npcd没有正常运行, ...

  8. 首次使用Cesium加载3D数据不成功

    接此: https://blog.csdn.net/bcbobo21cn/article/details/110454547 参阅相关教程:Cesium加载3D数据是通过3D Tiles进行: 3D ...

  9. Android中使用WebChromeClient显示Openlayers加载本地GeoJson文件显示地图(跨域问题解决)

    场景 Openlayers中加载GeoJson文件显示地图: Openlayers中加载GeoJson文件显示地图_BADAO_LIUMANG_QIZHI的博客-CSDN博客 上面加载显示GeoJso ...

最新文章

  1. 博士生在没有导师指导的情况下,该如何自己选题发 CVPR ?
  2. JQuery中html()和val()的用法区别
  3. ZendStudio中,缺少gbk gb2312编码的解决办法
  4. 计算机应用技术环境评估,计算机应用教程(第7版)(Windows 7与Office 2007环境)习题解答与上机练习...
  5. 基于fpga的dds函数信号发生器的设计_低频信号发生器
  6. delphi商业源码
  7. Vue 遍历单项选择 答题卡
  8. Flink Table和SQL中Table和DataStream的相互转换(fromDataStream、toChangelogStream、attachAsDataStream)
  9. 随机森林模型sklearn_sklearn中的随机森林
  10. 计算机网络说明文,《Wi-Fi》初中说明文阅读题及答案
  11. JanusGraph入坑笔记(五)- GraphTraversal (Vertex centric)
  12. 访问控制列表之基本ACL、高级ACL 、 高级ACL之ICMP、高级ACL之telnet
  13. 单核CPU仍然存在线程安全问题
  14. 零知识证明在区块链中的应用
  15. 【CSS】画一个扇形
  16. 什么是虚拟机?虚拟机有什么用?虚拟机的特点?
  17. “多巴胺思维”—通往AI秘密的钥匙「AI核心算法」
  18. 函数极限的概念及性质
  19. 【淘宝SEO技巧】淘宝宝贝标题关键字优化
  20. 我们都进入了一个误区,其实面试官 “ 回去等通知 ” 不等于没戏....

热门文章

  1. AHP层次分析法解决用户价值评估
  2. 在贪心学院学习,是一种怎样的体验?
  3. Parameter-Efficient Fine-tuning 相关工作梳理
  4. CIKM 2021 | 自监督学习在社会化推荐系统中的应用
  5. 技术部门Leader是不是一定要技术大牛担任?
  6. GELU的两个初等函数近似是怎么来的?
  7. 从“猿”到“金刚”,机器学习让你在职业生涯超进化!
  8. AIProCon在线大会笔记之华为涂丹丹:华为云EI,行业智能化升级新引擎
  9. POJ1679 Luogu4180 次小生成树
  10. c语言如何获取串口列表,如何通过串口来读写数据,请教达人