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文件的持续时间,以毫秒为单位:
{
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;
}