从图书馆借来的书上摘抄下来的,打字手好酸啊,:-)
用底层设备接口函数回放声音
采样点:就是声音的一个采样数据,按采样位数的不同,可能占1,2,4个字节。采样数据为16位时,一个采样点是一个短整型数,占两字节,取值范围-32768~32767.采样数据为8位或更少时,一个采样点是一个无符号字符型数据,取值范围0至255。
立体声声音有左声道和右声道两个 通道 。
单声道声音只有一个 通道 。
采样帧:立体声左声道的第一个采样点和右声道的第一个采样点构成一个采样帧;同理他们的第二个采样点又构成一个采样帧。如果是单声道,一个采样点就是一个采样帧。
所用函数需要包含头文件mmsystem.h,并且在编译连接时加入库文件winmm.lib。
1.打开音频设备
用waveOutOpen,调用时要指定:
设备ID,通常用WAVE_MAPPER,即标准音频设备;
采样数据格式,如采样率,采样位数等;
回调方式。
如果调用成功,我们将得到一个设备句柄,以后的函数调用需要这个句柄。
在打开音频设备时,用户可以向系统传递一个 函数地址 或 一个事件 或 窗口句柄。
2.传送采样数据
首先用waveOutPrepareHeader准备采样数据,然后用waveOutWrite把准备好的数据发给设备开始回放,回放完毕后用waveOutUnprepareHeader取消采样数据的准备。
3.关闭设备
用函数waveOutClose实现。
下面是一段用底层函数回放的代码,假设采样数据已经从WAV文件中取出,放在指针lpwavedata指向的内存,大小为wavesize,声音格式为PCM,立体声,采样频率44.1kHz,采样位16:
//打开音频设备
HWAVEOUT hWave;
PCMWAVEFORMAT fmt = {{1, //PCM
2, //通道数
44100, //采样频率
4*44100 //每秒数据量(字节)
4}, //采样帧大小
16}; //采样位
HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
waveOutOpen(&hWave,WAVE_MAPPER,(LPWAVEFORMATEX)&fmt,(DWORD)hEvent,0,CALLBACK_EVENT);
//准备数据
WAVEHDR whdr;
memset(&whdr,0,sizeof(WAVEHDR));
whdr.lpData=lpwavedata;
whdr.dwBufferLength=wavesize;
waveOutPrepareHeader(hWave,&whdr,sizeof(WAVEHDR));
//输出
waveOutWrite(hWave,&whdr,sizeof(WAVEHDR));
//等待回放完毕
WaitForSingleObject(hEvent,INFINITE);
//取消准备
waveOutUnprepareHeader(hWave,&whdr,sizeof(WAVEHDR));
//关闭设备
waveOutClose(hWave);
WaitForSingleObject(hEvent,INFINITE);
CloseHandle(hEvent);