DirectSound 包装类
一篇关于多媒体的文章 - 使用 DirectSound 组件播放 Wave 文件。
引言
Microsoft DirectX 是一个庞大的系统,没有合适的工具很难驾驭。DirectX 的每一个部分都值得开发者单独关注。深入了解这些组件非常困难。但是,要正确使用它们,一个人必须知道自己在做什么或想要做什么……
但如今技术发展迅速,它们使开发者不必处理工作中的许多“技术”方面,从而可以专注于他们关心的核心问题。这些辅助工具之一,也是面向对象语言(当然包括 C++)的核心概念,就是类。
类是面向对象编程的基石。你越明智地使用它们,晚上睡得就越好。我不深入 C++ 的理论,我想向您介绍几个我的类,它们可以帮助您在应用程序中使用 MS DirectSound 组件。特别是,我将讨论如何通过 DirectSound 播放 .wav(wave)文件。
本次更新新增内容
本文的主要新功能是 CDSoundPlay
现在支持通知机制;它使用 IDirectSoundNotify
接口来处理。CWave 类的源代码可在下载的源代码中找到。此外,还有对上一篇文章代码的一些更正。
背景
首先,我想说 .wav 文件不仅可以用 DirectSound 播放,还可以用 MMIO、MCI 等播放。问题在于,这些设备不会立即响应用户,播放延迟很大。在某些情况下,这可能至关重要,例如在游戏中,当玩家想要枪声(并射击)尽快响起时。这时 DirectSound 可以提供帮助。
DirectSound 提供低延迟播放和即时响应用户。
为了最大程度地减少使用 DirectSound 所需的工作量,我创建了四个类:可以说是包装类。其中两个是辅助类,不打算直接使用,但您仍然可以使用它们。以下是这些类:
CWave
(辅助类)CDSBuffer
(辅助类)CDSound
CDSoundPlay
CWave
帮助我们打开 .wav 文件。该类被 CDSBuffer
使用。我将 CWave
放在一个 DLL 中,以隐藏不必要的内容(相信我,有很多丑陋的代码)。不过,您可以在本文的下载包中找到 CWave
的源代码。
CDSound
是您系统中的主要实体。它代表 DirectSound 对象。在给定应用程序中,应该只有一个此类实例。该类被 CDSBuffer
使用。
CDSBuffer
是一个低级类,代表 DirectSound 缓冲区。该类被 CDSoundPlay
使用。
CDSoundPlay
是一个高级类,代表用于播放、停止… Wave 的接口。
这些类使用 MFC,并且离不开 MFC。例如,我将 CWave
放在一个 MFC 扩展 DLL 中;这意味着客户端应用程序也必须是基于 MFC 的。
使用代码
现在让我们看看如何使用它们。您可以在视图类、对话框类或主框架类中声明这些类的对象;换句话说,任何具有 HWND
的窗口(实际上我还没见过没有 HWND
的窗口)。我将选择一个对话框。
声明
#include "DirectSound.h" using namespace DirectSound; class CMyDialog : public CDialog { CDSound m_dsound; // only once CDsoundPlayer m_player; // any number // ... };
接下来在 OnInitDialog
中构造相应的 DirectSound 对象
BOOL CMyDialog::OnInitDialog() { // ... m_dsound.Create(); m_dsound.SetCooperativeLevel(GetSafeHwnd()); return FALSE; }
现在您可以加载文件了。假设您有一个 Load 方法来执行此操作
BOOL CMyDialog::Load(LPCTSTR lpszFileName) { m_player.Destroy(); // guarantee multiple loads BOOL fOk = m_player.Create(&m_dsound, lpszFileName); return fOk; }
让我们播放和停止 Wave 文件。假设您有 OnPlay
和 OnStop
处理程序来执行此操作
void CMyDialog::OnPlay() { Load(TEXT("flowers.wav")); m_player.Play(); } void CMyDialog::OnStop() { m_player.Stop(); }
CDSoundPlay
中添加了几个新函数,用于处理通知:CDSounfPlay::SetNotifyFuction
和 CDSoundPlay::SetNotificationPositions
。前者接受一个 PNOTIFYFUNC
类型的参数,这是一个回调函数的类型定义。
typedef LONG (*PNOTIFYFUNC) (LONG );
这意味着回调应该接受一个 LONG
参数并返回一个 LONG
值。这个类型是我定义的,您可以根据需要更改为您的约定。
第二个函数如下所示:
BOOL SetNotificationPositions(DWORD dwOffsets[], SIZE_T nSize);
它接受一个整数数组,表示要考虑的位置,以及一个整数,表示第一个参数中有多少个位置。
例如,演示应用程序调用这些函数来在 Wave 开始和结束时接收通知:
m_player.SetNotifyFunction(CSounderDlg::NotifyCallback); DWORD dwOffset[] = { 0, DSBPN_OFFSETSTOP }; m_player.SetNotificationPositions(dwOffset, 2);
CSounderDlg::NotifyCallback
是一个静态函数,其类型为 PNOTIFYFUNC
LONG CSounderDlg::NotifyCallback(LONG f) // static function { // ... return 0; }
这就是播放 Wave 文件所需的一切。但 CDSoundPlay
还有其他功能;其中包括:循环、音量设置/获取、全景设置/获取、频率设置/获取。我创建了一个演示应用程序,展示了其中大部分功能。这是一个简单的应用程序,我不会详细介绍它。只需看看它的界面,您就会自己明白。