VC++ 声音处理

转载地址:http://wwww.ahtvu.ah.cn/jxc/40vc/student1/zhixin/ch9/a22.htm 

VC++ 开发工具中声音的处理

1、利用高级音频函数播放波形音频文件

Windows 提供了三个播放声音的高级音频函数: MessageBeep 、 PlaySound 和 sndPlaySound 。

(1)MessageBeep() 函数:

函数原型: BOOL MessageBeep(UINT uType);

函数功能:播放系统报警声音。

说明:①系统报警声音是由用户在控制面板中的声音程序定义的,或在 WIN.INI 的 [sound] 段中定义的。

② uType 说明了报警级别,参数值如下:

-1:从机器的扬声器中发出蜂鸣声

MB_ICONASTERISK :播放由 SystemAsterisk 定义的声音

MB_ICONEXCELAMATION: 播放由 SystemExclamation 定义的声音。

MB_ICONHAND :播放由 SystemHand 定义的声音。

MB_ICONQUESTION :播放由 SystemHand 定义的声音。

MB_OK :播放由 SystemDefault 定义的声音。

(2) PlaySound() 函数:

  函数原型: BOOL PlaySound(LPCSTR pszSound,HMODULE hmod,DWORD fdwSound);

  函数功能:播放音频文件

  说明:①该函数有两个限制:必须将声音数据完整地载入物理内存;数据格式必须被所配置的某一音频驱动器的支持。

    ② PlaySound() 通常用于100 K 以下的文件。

           ③参数说明: pszSound :指定了要播放声音的字符串,该参数可以是 WAVE 文件的名字或 WAV 资源的名字,或是内存中声音数据的指针,或是在系统注册表 WIN.INI 中定义的系统事件的声音。

  hmod :是应用程序的实例句柄,当播放 WAV 资源时要用到该参数。

  fdwSound :是标志的组合,参数值如下:

  SND_APPLICATION: 用应用程序指定的关联来播放声音。

  SND_ALIAS:pszSound 参数指定了注册表或 WIN.INI 中的系统事件的别名。

  SND_FILENAME:pszSound 参数指定了 WAVE 文件名。

  SND_LOOP: 重复播放声音,必须与 SND_ASYNC 标志一起使用。

  SND_MEMORY: 播放载入到内存中的声音,此时 pszSound 是指向声音数据的指针。

  SND_SYNC: 同步播放声音,在播放完后 PlaySound 函数才返回。

例如:在 C:\WINDOWS|MEDIA 目录下有一名为 data.wav 的声音文件,调用 PalySound() 函数播放声音文件的方法有:

方法1:直接播出声音文件:代码如下:

PlaySound(“C:\\windows\media\data.wav”,NULL,SND_FIMENAME|SND_ASYNC);

方法2:把声音文件加入到资源中,然后从资源中播放。假定声音资源的 ID 为: IDR_DATA ,则代码为:

PlaySound((LPCTSTR)IDR_DATA,AfxGetInstanceHandle(),SND_RESOURCE|SND_ASYNC);

另外用 PlaySound 还可以播放系统声音,代码如下:

PlaySound(“SystemStart”,NULL,SND_ALIAS|AND_ASYNC);

(3)sndPlaySound() 函数:

函数原型: BOOL sndPlaySound(LPCSTR lpszSound,UINT fuSound);

功能:播放声音文件。

说明:除了不能指定资源名字之外,其他参数功能和 PlaySound() 函数一样。

例如: sndPlaySound(“data.wav”,SND_ASYNC);

例 1:EX3_1: 编写一个 SDI 程序测试 MessageBeep,PlaySound,sndPlaySound 三个函数。

步骤:(1)拷贝一个波形文件 tada.wav 到刚创建的工程目录下。

(2)在工程中加入多媒体组件。选择 Project|Add to Project|Compents and Controls 菜单项,在弹出的 Compents and Control Gallery 对话框中选择 Visual C++Compents 文件夹,然后选择 Windows Multimedia library 选项,将其插入工程中。

(3)编辑资源菜单,加入函数测试菜单项,添加如下子菜单的属性和 ID 值。

属性: MessageBeep ID:ID_MESSAGEBEEP

属性: PlaySound ID:ID_PLAYSOUND

属性: sndPlaySound ID:ID_SNDPLAYSOUND

(4)利用类向导为这些消息生成视图类的相应处理函数,并添加代码:

void CMainFrame::OnMessagebeep()

{

// TODO: Add your command handler code here

MessageBeep(MB_OK); // 播放系统默认的声音

}

void CMainFrame::OnPlaysound()

{

// TODO: Add your command handler code here

PlaySound("friendonline.wav",NULL,SND_LOOP|SND_ASYNC);

}

void CMainFrame::OnSndpaysound()

{

// TODO: Add your command handler code here

sndPlaySound("ringout.wav",SND_ASYNC);

}

程序运行图如下:

程序运行结果: 程序代码下载:

2、利用 MCI 播放声音:

应用程序通过向 MCI 发送命令来控制媒体设备。利用 MCI 函数,可以把命令发送到任何设备,每个设备的有效命令取决于设备本身的能力,如发送开始、播放、结束等命令。运用 MCI 函数可以播放 WAV 文件、 MIDI 文件以及视频( AVI )文件等。

MCI 命令接口分命令字符和命令消息两种,两者功能相同,命令字符串具有使用简单的特点,但它的执行效率不如命令消息。

( 1 )用命令字符串访问 MCI 命令接口

所有的 MCI 命令字符串都是通过多媒体 API 函数 mciSendString 传递给 MCI 的,该函数的原型为:

MCIERROR mciSendString

(

LPCTSTR plszCommand, //MCI 命令字符串

LPTSTR lpszReturnString, // 存放反馈信息的缓冲区

UINT cchReturn, // 缓冲区的长度

HANDLE hwndCallback // 回调窗口的句柄,一般为 NULL

); // 若成功返回 0 。否则返回错误码

例如:一个使用 mciSendString 的简单的例子。

Char buf[50];

MCIERROR mciError;

mciError=mciSendString(“open data.wav type waveaudio”,buf,strlen(buf),NULL);

(2)用命令消息访问 MCI 命令接口

与 MCI 命令字符串相比, MCI 命令消息的执行速度更快,所有的 MCI 命令消息都是通过 mciSendCommand 函数发送的 。

函数原型为:

MCIERROR mciSendCommand(

MCIDEVICEID IDDevice, // 设备的 ID ,在打开设备时不用该参数

UINT uMsg ,// 命令消息

DWORD fdwCommand, // 命令消息的标志

DWORD dwParam // 指向包含命令消息参数的结构

); // 若成功返回 0 ,否则返回错误码

功能:播放音频文件。

说明:为使用 MCI 函数 mciSendCommand 来播放一个波形文件,需要数据结构 MCI_PLAY_PARAMS 和 MCI_WAVE_OPEN_PARMS 。

MCI_WAVE_OPEN_PARMS 的数据结构:

typedef struct

{

DWORD dwCallback; // 如果指定 MCI_NOTIFY 标志,为回调的窗口句柄。

MCIDEVICEID wDeviceID;// 返回的设备标识符

LPCSTR lpstrDeviceType;// 指定设备类型

LPCSTR lpstrElementName;// 指向设备元素名称的指针,通常是一个路径。

LPCSTR lpstrAlias;// 设备别名

DWORD dwBufferSeconds;// 指出以秒计量的缓冲区的长度

} MCI_WAVE_OPEN_PARMS;

MCI_PALY_PARAMS 的结构为:

Typedef strut

{

DWORD dwCallback; // 如果指定 MCI_NOTIFY 标志,为回调的窗口句柄。

DWORD dwFrom; // 开始播放的文件位置

DWORD dwTo; // 结束播放的文件位置

}MCI_PLAY_PARAMS;

用命令消息控制播放波形文件的机制:

(1)打开波形音频设备

UINT wDeviceID;

DWORD dwReturn;

MCI_OPEN PARMS OpenParms;

OpenParms.lpstrDeviceType=(LPCSTR)MCI_DEVTYPE_WAVEAUDIO; // 波形音频类型

OpenParms.lpstrElementName=(LPCSTR)Filename;

OpenParms.wDeviceID=0;

mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_TYPE|MCI_OPENELEMENT,(DWORD)(LPVOID)&OpenParms);

(2)关闭波形音频设备

mciSendCommand(m_wDeviceID,MCI_CLOSE,NULL,NULL);

(3)播放

MCI_PLAY_PARMS PlayParms;

PlayParms.dwFrom=0;

mciSendCommand(m_wDeviceID,MCI_PLAY,MCI_FROM,(DWORD)(LPVOID)&PlayParms));

(4)暂停

MCI_PLAY_PARMS PlayParms;

mciSendCommand(m_wDeviceID,MCI_PAUSE,0,(DWORD)(LPVOID)&PlayParms);

(5)停止

mciSendCommand(m_wDeviceID,MCI_STOP,NULL,NULL);

例 2 : Ex3_2 :编写一个应用程序,利用 mciSendString 函数和 mciSendCommand 函数来对波形音频文件的播放进行控制。

步骤:( 1 )利用 MFC AppWizard(EXE) 生成一个基于对话框的应用程序,项目名为 Ex2_2 。

( 2 )选择资源视图,编辑对话框 IDD_Ex2_2_DIALOG 。

删除对话框上原有的按钮和静态文本控件,从控制面板上选择 4 个按钮控件加入对话框中,并用 group 控件将它们编为一组,如下设置这些控件的 ID 和标题。

标题( Caption ) ID 值

Open IDC_BUTTON_OPEN

Play IDC_BUTTON_PLAY

Pause IDC_BUTTON_PAUSE

Stop IDC_BUTTON_STOP

MciSendCommand(group 控件 ) IDC_STATIC

mciSendStringTest IDC_STATIC

CommandString IDC_STATIC

Edit 无标题 IDC_COMMANDSTRING

Play IDC_BUTTON_STR_PLAY

(3)利用类向导为对话框上的控件添加相应的成员函数和成员变量。

对象 ID 消息处理函数

IDC_BUTTON_OPEN OnButtonOpen()

IDC_BUTTON_PLAY OnButtonPlay()

IDC_BUTTON_PAUSE OnButtonPause()

IDC_BUTTON_STOP OnButtonStop()

IDC_BUTTON_STR_PLAY OnButtonStrPlay()

IDOK OnOK()

(4)为了响应 MCI 消息 MM_MCINOTIFY ,需要手工添加相应的消息函数的声明:

在 Ex3_2Dlg.h 文件中添加红体语句:

//}}AFX_MSG

afx_msg LRESULT OnMciNotify(WPARAM wParam,LPARAM lParam);

DECLARE_MESSAGE_MAP()

在 Ex3_2Dlg.cpp 文件中加入消息映射部分红体代码:

BEGIN_MESSAGE_MAP(CEx3_2Dlg, CDialog)

//{{AFX_MSG_MAP(CEx3_2Dlg)

ON_WM_SYSCOMMAND()

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

ON_BN_CLICKED(IDC_BUTTON_OPEN, OnButtonOpen)

ON_BN_CLICKED(IDC_BUTTON_PAUSE, OnButtonPause)

ON_BN_CLICKED(IDC_BUTTON_PLAY, OnButtonPlay)

ON_BN_CLICKED(IDC_BUTTON_STOP, OnButtonStop)

ON_BN_CLICKED(IDC_BUTTON_STR_PLAY, OnButtonStrPlay)

//}}AFX_MSG_MAP

ON_MESSAGE(MM_MCINOTIFY,OnMciNotify)

END_MESSAGE_MAP()

(5)添加 Windows 的多媒体组件:选择 Project|Add to Project|Compents and Control|C++Compents|Windows Multimedia library 。

(6)在 Ex3_2Dlg.h 中添加三个保护类型的成员变量:

protected:

HICON m_hIcon;

BOOL m_bIsPlay; // 指示是否正在播放

BOOL m_bIsPause;// 指示是否处于暂停状态

MCIDEVICEID m_MCIDeviceID; // 设备 ID

编写消息处理函数的代码:

void CEx3_2Dlg::OnButtonOpen()

{

// TODO: Add your control notification handler code here

CString filename;

MCI_OPEN_PARMS mciOpenParam;

DWORD dwError;

static char szFilter[]="waveaudio file(*.wav)|*.wav||";

CFileDialog dlg(TRUE,"wav",NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter);

if(dlg.DoModal()==IDOK)

{

filename=dlg.GetPathName();

if(m_bIsPlay)

{

dwError=mciSendCommand(m_MCIDeviceID,MCI_CLOSE,0,NULL);

}

mciOpenParam.lpstrDeviceType="waveaudio";

mciOpenParam.lpstrElementName=filename;

dwError=mciSendCommand(0,MCI_OPEN,MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciOpenParam);

m_MCIDeviceID=mciOpenParam.wDeviceID;

m_bIsPlay=FALSE;

m_bIsPause=FALSE;

}

}

 

void CEx3_2Dlg::OnButtonPause()

{

// TODO: Add your control notification handler code here

DWORD dwError;

if(m_bIsPlay)

{ dwError=mciSendCommand(m_MCIDeviceID,MCI_PAUSE,0,NULL);

m_bIsPause=!m_bIsPause;

}

if(!m_bIsPlay)

{

m_bIsPause=FALSE;

}

}

 

void CEx3_2Dlg::OnButtonPlay()

{

// TODO: Add your control notification handler code here

MCI_PLAY_PARMS mciPlayParms;

DWORD dwError;

if(!m_bIsPlay)

{

mciPlayParms.dwCallback=(long)GetSafeHwnd();

mciPlayParms.dwFrom=0;

dwError=mciSendCommand(m_MCIDeviceID,MCI_PLAY,MCI_FROM|MCI_NOTIFY,(DWORD)(LPVOID)&mciPlayParms);

}

if(m_bIsPlay&&m_bIsPause)

{

dwError=mciSendCommand(m_MCIDeviceID,MCI_RESUME,0,NULL);

m_bIsPause=!m_bIsPause;

}

m_bIsPlay=TRUE;

 

}

 

void CEx3_2Dlg::OnButtonStop()

{

// TODO: Add your control notification handler code here

DWORD dwError;

dwError=mciSendCommand(m_MCIDeviceID,MCI_STOP,MCI_WAIT,NULL);

mciSendCommand(m_MCIDeviceID,MCI_CLOSE,NULL,NULL);

}

 

void CEx3_2Dlg::OnButtonStrPlay()

{

// TODO: Add your control notification handler code here

UpdateData(TRUE);

DWORD ok=mciSendString("play aa.wav type waveaudio",NULL,0,NULL);

}

 

void CEx3_2Dlg::OnOK()

{

// TODO: Add extra validation here

OnButtonStop();

CDialog::OnOK();

}

//MM_MCINOTIFY

LRESULT CEx3_2Dlg::OnMciNotify(WPARAM wParam,LPARAM lParam)

{

if(wParam==MCI_NOTIFY_SUCCESSFUL)

{

m_bIsPlay=FALSE;

m_bIsPause=FALSE;

return 0;

}

return -1;

}
程序运行结果图:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值