《2022年播放声音——用C语言》由会员分享,可在线阅读,更多相关《2022年播放声音——用C语言(8页珍藏版)》请在金锄头文库上搜索。
1、播放声音第一次用C 语言做游戏声音是多媒体的一个重要组成部分,在应用程序中加入声音可以使界面更友好。在VC+ 中可以根据不同的应用要求,用不同的方法实现声音的播放。一播放声音文件的简单方法在 VC+ 中的多媒体动态连接库中提供了一组与音频设备有关的函数。利用这些函数可以方便地播放声音。最简单的播放声音方法就是直接调用VC+ 中提供的声音播放函数BOOL sndPlaySound ( LPCSTR lpszSound,UINT fuSound ); 或 BOOL PlaySound( LPCSTR lpszSound, HMODULE hmod, DWORD fuSound );其中参数lpsz
2、Sound是需要播放声音的.WAV 文件的路径和文件名,hmod 在这里为NULL , fuSound是播放声音的标志,详细说明请参考VC+ 中的帮助。 例如播放C:soundmusic.wav可以用sndPlaySound (c:soundmusic.wav,SND_ASYNC);或PlaySound(c:soundmusic.wav, NULL, SND_ASYNC|SND_NODEFAULT );如果没有找到 music.wav 文件,第一种格式将播放系统默认的声音,第二种格式不会播放系统默认的声音。二将声音文件加入到程序中在 VC+ 的程序设计中,可以利用各种标准的资源,如位图,菜单,
3、对话框等。同时VC+ 也允许用户自定义资源,因此我们可以将声音文件作为用户自定义资源加入程序资源文件中,经过编译连接生成EXE 文件,实现无 .WAV 文件的声音播放。要实现作为资源的声音文件的播放,首先要在资源管理器中加入待播放的声音文件(实现过程并不复杂,这里不在叙述)。假设生成的声音文件资源标识符为IDR_WAVE1 。在播放时只需要调用下面的语句:PlaySound(MAKEINTRESOURCE(IDR_WAVE1),AfxGetResourceHandle(), SND_ASYNC|SND_RESOURCE|SND_NODEFAULT|SND_LOOP); 其中 MAKEINTRE
4、SOURCE()宏将整数资源标识符转变为字符串,AfxGetResourceHandle()函数返回包含资源的模块句柄,名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 8 页 - - - - - - - - - SND_RESOURCE是必须的标志。作为资源的声音文件的第二种播放方法是把资源读入内存后作为内存数据播放。具体步骤入下:1获得包含资源的模块句柄:HMODULE hmod=AfxGetResourceHandle(); 2检索资源块信息:HRSRC hSndRe
5、source=FindResource(hmod,MAKEINTRESOURCE(IDR_WAVE1),_T(WAVE); 3. 装载资源数据并加锁:HGLOBAL hGlobalMem=LoadResource(hmod,hSndResource); LPCTSTR lpMemSound=(LPCSTR)LockResource(hGlobalMem); 4播放声音文件:sndPlaySound(lpMemSound,SND_MEMORY);5释放资源句柄:FreeResource(hGlobalMem); 三播放声音文件的高级方法在 VC+ 中提供了一组对音频设备及多媒体文件直接进行操作的
6、函数。利用这些函数可以灵活地对声音文件进行各种处理。首先介绍几个要用到的数据结构。WAVEFORMATEX结构定义了WAVE 音频数据文件的格式。 WAVEHDR结构定义了波形音频缓冲区。读出的数据首先要填充此缓冲区才能送音频设备播放。WAVEOUTCAPS结构描述了音频设备的性能。MMCKINFO结构包含了RIFF 文件中一个块的信息。详细的说明请参考VC+ 中的帮助。下面给出程序流程简图及程序源代码清单,在VC+ 环境下可直接使用:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第
7、2 页,共 8 页 - - - - - - - - - 源程序清单如下:LPSTR szFileName;/声音文件名MMCKINFO mmckinfoParent; MMCKINFO mmckinfoSubChunk; DWORD dwFmtSize; HMMIO m_hmmio;/音频文件句柄DWORD m_WaveLong; HPSTR lpData;/音频数据HANDLE m_hData; HANDLE m_hFormat; WAVEFORMATEX * lpFormat; DWORD m_dwDataOffset; DWORD m_dwDataSize; WAVEHDR pWaveO
8、utHdr; WAVEOUTCAPS pwoc; HWAVEOUT hWaveOut; /打开波形文件if(!(m_hmmio=mmioOpen(szFileName,NULL,MMIO_READ|MMIO_ALLOCBUF) /File open Error Error(Failed to open the file.);/错误处理函数名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 8 页 - - - - - - - - - return false; /检查打开文件是
9、否是声音文件mmckinfoParent.fccType =mmioFOURCC(W,A,V,E); if(mmioDescend(m_hmmio,(LPMMCKINFO)&mmckinfoParent,NULL,MMIO_FINDRIFF) /NOT WAVE FILE AND QUIT /寻找 fmt 块mmckinfoSubChunk.ckid =mmioFOURCC(f,m,t, ); if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK) /Cant find fmt chunk /获得 fmt
10、 块的大小,申请内存dwFmtSize=mmckinfoSubChunk.cksize ; m_hFormat=LocalAlloc(LMEM_MOVEABLE,LOWORD(dwFmtSize); if(!m_hFormat) /failed alloc memory 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 8 页 - - - - - - - - - lpFormat=(WAVEFORMATEX*)LocalLock(m_hFormat); if(!lpForm
11、at) /failed to lock the memory if(unsigned long)mmioRead(m_hmmio,(HPSTR)lpFormat,dwFmtSize)!=dwFmtSize) /failed to read format chunk /离开 fmt 块mmioAscend(m_hmmio,&mmckinfoSubChunk,0); /寻找 data 块mmckinfoSubChunk.ckid=mmioFOURCC(d,a,t,a); if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FI
12、NDCHUNK) /Cant find data chunk /获得 data 块的大小m_dwDataSize=mmckinfoSubChunk.cksize ; m_dwDataOffset =mmckinfoSubChunk.dwDataOffset ; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 8 页 - - - - - - - - - if(m_dwDataSize=0L) /no data in the data chunk /为音频数据分配内存lpDa
13、ta=new charm_dwDataSize; if(!lpData) /faile if(mmioSeek(m_hmmio,SoundOffset,SEEK_SET)0) /Failed to read the data chunk m_WaveLong=mmioRead(m_hmmio,lpData,SoundLong); if(m_WaveLong0) /Failed to read the data chunk /检查音频设备,返回音频输出设备的性能if(waveOutGetDeVCaps(WAVE_MAPPER,&pwoc,sizeof(WAVEOUTCAPS)!=0) 名师资料总
14、结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 8 页 - - - - - - - - - /Unable to allocate or lock memory /检查音频输出设备是否能播放指定的音频文件if(waveOutOpen(&hWaveOut,DevsNum,lpFormat,NULL,NULL,CALLBACK_NULL)!=0) /Failed to OPEN the wave out devices /准备待播放的数据pWaveOutHdr.lpData =(HPS
15、TR)lpData; pWaveOutHdr.dwBufferLength =m_WaveLong; pWaveOutHdr.dwFlags =0; if(waveOutPrepareHeader(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR)!=0) /Failed to prepare the wave data buffer /播放音频数据文件if(waveOutWrite(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR)!=0) /Failed to write the wave data buffer 名师资料总结 - - -精品
16、资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 8 页 - - - - - - - - - /关闭音频输出设备,释放内存waveOutReset(hWaveOut); waveOutClose(hWaveOut); LocalUnlock(m_hFormat); LocalFree(m_hFormat); delete lpData; 说 明: 1)以上使用的音频设备和声音文件操作函数的声明包含在mmsystem.h头文件中,因此在程序中必须用#include mmsystem.h语句加入头文件。同
17、时在编译时要加入动态连接导入库winmm.lib ,具体实现方法是从Developer Studio的 Project 菜单中选择Settings, 然后在 Link 选项卡上的Object/Library Modules控制中加入winmm.lib 。2)在pWaveOutHdr.lpData中指定不同的数据,可以播放音频数据文件中任意指定位置的声音。3) 以上程序均在VC+6.0 中调试通过,在文中省略了对错误及异常情况的处理,在实际应用中必须加入。/*本文来自网易博客“不是兔子”:*/ http:/ - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 8 页 - - - - - - - - -