在windows下用waveout接口播放音频
2013-07-09 11:09
330 查看
首先需要定义几个对象:
lpData:Pointer to the waveform buffer.dwBufferLength:Length, in bytes, of the buffer.dwUser:User data.dwFlags:Flags supplying information about the buffer. The following values are defined,其中包含了一个WHDR_PREPARED ,Set by Windows to indicate that the buffer has been prepared with the waveOutPrepareHeader function.
hwo:Handle to the waveform-audio output device.pwh:Pointer to a WAVEHDR structure containing information about the data block.cbwh:Size, in bytes, of the WAVEHDR structure.
HWAVEOUT hWaveOut; /* device handle */ WAVEFORMATEX wfx; /* look this up in your documentation */ MMRESULT result;/* for waveOut return values */ 然后需要设置音频流的参数信息,一下只是给出了我在使用过程中的参数,可以根据个人需求自行调节: wfx.nSamplesPerSec = 8000; /* sample rate */ wfx.wBitsPerSample = 16; /* sample size */ wfx.nChannels = 1; /* channels*/ 另外,还有一些额外的参数需要设置: wfx.cbSize = 0; /* size of _extra_ info */ wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; /*WAVE_MAPPER是一个在mmsystem.h中定义的常数,总是指向系统的默认流设备*/ 通过函数waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL)打开一个流设备,设置wfx音频流参数, 并使得hWaveOut为该设备的handle,可以通过判断函数返回值是否等于MMSYSERR_NOERROR)判断设备是否打开成功了 相应的可以通过调用waveOutClose(hWaveOut)来关闭一个流设备。
以上几步声明一个流设备对象,完成了打开、关闭一个流设备,并设置音频流参数接下来完成基本语音播放功能,播放语音需要做两个工作:语音数据写语音数据到流设备中
writeAudioBlock. To write audio data you use up to three functions. These are waveOutPrepareHeader,waveOutWrite, and waveOutUnprepareHeader and are called in the order I have listed them.
void writeAudioBlock(HWAVEOUT hWaveOut, LPSTR block, DWORD size);函数实现如下说明:
声明一个WAVEHDR对象:WAVEHDR header,结构如下
typedef struct wavehdr_tag { LPSTR lpData; DWORD dwBufferLength; DWORD dwBytesRecorded; DWORD_PTR dwUser; DWORD dwFlags; DWORD dwLoops; struct wavehdr_tag * lpNext; DWORD_PTR reserved; } WAVEHDR, *LPWAVEHDR;
lpData:Pointer to the waveform buffer.dwBufferLength:Length, in bytes, of the buffer.dwUser:User data.dwFlags:Flags supplying information about the buffer. The following values are defined,其中包含了一个WHDR_PREPARED ,Set by Windows to indicate that the buffer has been prepared with the waveOutPrepareHeader function.
然后初始化header为0,并传入参数数据大小、数据指针。 ZeroMemory(&header, sizeof(WAVEHDR)); header.dwBufferLength = size; header.lpData = block; 准备播放数据块: waveOutPrepareHeader(hWaveOut, &header, sizeof(WAVEHDR)); 写数据块到流设备中: waveOutWrite(hWaveOut, &header, sizeof(WAVEHDR)); 等待数据流播放完,释放header 调用函数waveOutUnprepareHeader(hWaveOut, &header, sizeof(WAVEHDR)) 释放掉header,在释放data前一定要调用waveOutUnprepareHeader() 可以根据返回值是否等于WAVERR_STILLPLAYING判断是否播放完毕
函数定义说明:
MMRESULT waveOutPrepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
MMRESULT waveOutWrite(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
MMRESULT waveOutUnprepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh);
hwo:Handle to the waveform-audio output device.pwh:Pointer to a WAVEHDR structure containing information about the data block.cbwh:Size, in bytes, of the WAVEHDR structure.
至此,将带播放的数据通过传入数据大小、数据指针给函数writeAudioBlock(HWAVEOUT hWaveOut, LPSTR block, DWORD size)就完成了基本的播放功能。[b]接下来完成播放一个音频流:[/b]
在上个播放语音实现中有一个大问题就是,每次只能播放一次读取数据,如果文件小的话,可以一次全部读取然后播放,但如果大文件就无法这样做了心所以需要寻找一种方法, 能够像流媒体一样,语音数据能一块一块顺序播放。 面临的另一个问题是,如果是单纯的顺序读取-播放,回会造成在两次播放之间有一个时间间隔,使得语音出现不连续的现象。解决方法是定义多个buffer,在播放的时候也能 够进行读数据到buffer里,这样每次一个buffer播放完,会有其他buffer已经准备好数据以供播放。 (由于最近事情比较多,回头补全这部分)
相关文章推荐
- 使用waveOut接口在Windows中播放声音
- 使用waveOut接口在Windows中播放声音
- 使用waveOut接口在Windows中播放声音
- 使用waveOut接口在Windows中播放声音(非常实用,转载)
- 使用waveOut接口在Windows中播放声音
- 使用waveOut接口在Windows中播放声音
- 使用waveOut接口在Windows中播放声音
- 使用waveOut接口在Windows中播放声音
- c# 使用windows自带winmm.dll 播放音频
- C++切换windows默认音频设备 (播放或录制)
- VS2010MFC对话框程序中使用Windows Media Player播放音频或视频文件
- Windows下播放WAV音频文件
- 音频播放处理(openal、dsound、waveout)
- Windows 下音频数据采集和播放
- Windows基础-使用XAudio2播放音频(本质是WASAPI)
- (二)DirectShow接口播放Mp3音频文件
- Windows和Linux下播放采集wave格式音频文件的简单记录
- 使用WaveOut接口播放WAV文件
- 一个使用WINDOWS媒体库的WAV音频文件播放的示例
- EasyPlayerPro windows播放器本地音频播放音量控制实现