• DirectSound学习笔记(5):使用WAV数据


    使用WAV数据

    在Windows 驱动模型(WDM)中,DirectSound硬件缓冲区能够播放任何未压缩或压缩的声音格式,这些格式能够被一个WAVEFORMATEX或 WAVEFORMATEXTENSIBLE结构描述,并由硬件支持。软件缓冲区和非WDM硬件缓冲区只支持8位和16位未压缩格式。

    波形(WAV)数据通常储存在资源交换文件格式(RIFF)的文件或资源中。数据包括一个WAV格式描述,包含如采样率和输出通道数等参数。

    多波段WAV格式

    在WDM驱动器中,DirectSound缓冲区支持拥有两个以上输出通道的WAV格式。对于如5.1的扬声器配置,它在前台左,中,右,后台左,右,以及低频增强器处均有扬声器。

    WAVEFORMATEXTENSIBLE结构描述了一个多通道波形格式。这个结 构是对WAVEFORMATEX的扩展,配置了已经由WAVEFORMATEX中cbSize成员支持的额外字节。当需要WAVEFORMATEX的地 方,WAVEFORMATEXTENSIBLE结构能够被转化为WAVEFORMATEX。

    如果系统配置的物理扬声器比多波段WAV文件中指定的通道数少,音频数据将被适当 混合并输出到现有的扬声器。DirectSound不支持多波段格式的缓冲区的3D处理和效果。企图创建带有DSBCAPS_CTRL3D或 DSBCAPS_CTRLFX标识的缓冲区和一个多波段WAV格式将会失败。

    读取WAV数据

    WAV文件是资源交换文件格式(RIFF),它由若干数量的包含头信息(如声音采样格式)或数据(采样本身)的命名块组成。Win32 API提供了打开和关闭RIFF文件,探索块等函数。这些函数名都以“mmio”开头。

    为了以可执行方式存储WAV声音,将WAV文件作为资源进行导入,并为它们命名。注意CWaveFile类期望这些资源是WAVE或WAV类型,并且是可执行模块而不是一个DLL。

    DirectSound API 不包含载入声音数据的方法。然而,Dsutil.cpp文件被许多SDK例子程序用来实现若干类,这些类能够被用来从文件,资源或一个内存地址创建声音缓冲区。

    使用例子类初始化DirectSound和创建载入缓冲区的步骤包括:
    1. 创建一个CSoundManager例子类的对象。
    2. 调用CSoundManager::Initialize创建设备对象。
    3. 将 一个文件或资源名传给CSoundManager::Create或将一个内存地址传给 CSoundManager::CreateFromMemory。这些方法返回一个CSound例子类的对象,该类表示一个或多个大小恰能容纳数据的静 态缓冲区。(你能够创建多个缓冲区来同时播放多个声音实例)或者,向CStreamingSound例子类传递一个文件或资源名。这个方法返回一个 CStreamingSound例子类的对象,它表示了一个单独的流缓冲区。
    4. 调用先前步骤中获取的对象中的 FillBufferWithSound方法。它将文件,资源或者内存地址中的数据读入缓冲区。对于流缓冲区,它以所能容纳的最大数据为限填充缓冲区,并 使用CStreamingSound::HandleWaveStreamNotification在播放缓冲区的同时更新数据。
    注意实际的数据读取是由一个CWaveFile对象完成,它是CSound或CStreamingSound对象中的一个受保护成员。你通常不必直接使用CWaveFile类;然而,你能够参考这个类的实现来获取分析WAV数据的信息。

    计算一个WAV声音的持续时间

    一个波形将要播放的时间长度取决于数据大小和格式。数据大小和格式能够通过调用DirectSound例子框架中的CWaveFile::GetSize和CWaveFile::GetFormat方法获取。
    以下例子函数,并没有使用例子类,返回了一个WAV文件的持续时间,以毫秒为单位:

    DWORD GetSoundLength(LPSTR strFileName)
    {
      CWaveFile
    * pWav;
      DWORD dwLen 
    = 0;
      DWORD dwSize;
      WAVEFORMATEX
    * wfx;
     
      pWav 
    = new CWaveFile();
      
    if (SUCCEEDED(pWav->Open(strFileName, NULL, WAVEFILE_READ)))
      
    {
        wfx 
    = pWav->GetFormat();
        dwSize 
    = pWav->GetSize();
        dwLen 
    = (DWORD) (1000 * dwSize / wfx->nAvgBytesPerSec);
        pWav
    ->Close();
      }

      
    if (pWav) delete pWav;
      
    return dwLen;
    }
  • 相关阅读:
    hive从入门到放弃(一)——初识hive
    LeetCode 2040. Kth Smallest Product of Two Sorted Arrays
    LeetCode weekly contest 278 (amazon pay)
    LeetCode Weekly Contest 281
    《前端运维》一、Linux基础06Shell流程控制
    《前端运维》一、Linux基础05Shell运算符
    一比一还原axios源码(二)—— 请求响应处理
    一比一还原axios源码(八)—— 其他功能
    一比一还原axios源码(三)—— 错误处理
    《前端运维》一、Linux基础04Shell变量
  • 原文地址:https://www.cnblogs.com/top5/p/1635049.html
Copyright © 2020-2023  润新知