Direct X是微软公司提供给游戏编写人员的一套应用程序编程接口(APIs)它为编写高效实时的应用程序提供了有力的支持因此有必要将这个接口封装到Delphi的组件库中Direct X SDK是面向Visual C/C++和Watcom C/C++的因而使用Object Pascal直接存取Direct X SDK将带来诸多不便但我们可先在VC下将Direct X接口封装成动态链接库然后在Delphi下通过该动态链接库去存取Direct X
本文介绍用Delphi封装Direct Sound的方法这种方法同样也可以应用到Direct Draw(但建议不要使用独占模式否则会带来不少问题)
先简单介绍一下Direct Sound的接口界面Direct Sound的基本对象有两个即IDirectDraw和IDirectDrawBuffer前者代表声卡后者代表声音数据缓沖区
IDirectDraw是整个Direct Sound的基础其建立方法如下
LPDIRECTSOUND lpDS;
HRESULT ErrorCode;
HWND hwnd=Mainhwnd;//窗口句柄
ErrorCode=DirectSoundCreate(NULL &lpDS NULL); //建立对象
if(ErrorCode!=DS_OK)return FALSE; //失败则返回
ErrorCode=lpDS>SetCooperativeLevel(hwnd DSSCL_NORMAL);//设置存取模式
if(ErrorCode!=DS_OK) //失败则返回
{
lpDS>Release();
lpDS=NULL;
return FALSE;
}
IDirectDrawBuffer通过IDirectDraw建立IDirectDrawBuffer有两种基本类型一种被称作基本缓沖区(Primary Buffer) 另一种被称作辅助缓沖区(Secondary Buffer) 基本缓沖区是Direct Sound 混音的基础一般不直接存取这个缓沖区(虽然也可以)但可以通过该缓沖区去存取初始化声卡方法如下
HRESULT ErrorCode;
LPDIRECTSOUND lpDS=lpMainDS;//Direct Sound对象
LPDIRECTSOUNDBUFFER lpDBP;
DSBUFFERDESC dsbds;
ZeroMemory(&dsbdssizeof(dsbds));
dsbdsdwSize=sizeof(dsbds);
dsbdsdwFlags=DSBCAPS_PRIMARYBUFFER;
ErrorCode=lpDS>CreateSoundBuffer(&dsbds&lpDBPNULL);//建立基本缓沖区
if(ErrorCode!=DS_OK)return FALSE;//失败则返回
ErrorCode=lpDBP>Play(DSBPLAY_LOOPING);//初始化
if(ErrorCode!=DS_OK)//失败则返回
{
lpDBP>Release();
lpDBP=NULL;
lpDS>Release();
lpDS=NULL;
return FALSE;
}
lpDBP>Release();//释放基本缓沖区
return TRUE; //初始化成功
辅助缓沖区可以建立任意多个声音数据就放在这种缓沖区内每个缓沖区可被独立播放(IDirectSoundBuffer::Play)Direct Sound会处理这些声音并实现混音的效果其建立方法与基本缓沖区的差不多只是对DSBUFFERDESC的填写有些不一样
ZeroMemory(&dsbufferdescsizeof(dsbufferdesc));
dsbufferdescdwSize=sizeof(dsbufferdesc);
dsbufferdescdwFlags=DSBCAPS_STATIC|DSBCAPS_CTRLDEFAULT;
dsbufferdescdwBufferBytes=BufferSize;//缓沖区大小
dsbufferdesclpwfxFormat=(LPWAVEFORMATEX)&pcmformat;//wav文件的PCM格式
ErrorCode=lpDS>CreateSoundBuffer(&dsbd&lpSBNULL);
建立该缓沖区后通过IDirectSoundBuffer::Lock锁定内存即可写入数据数据可以用普通MCI的多媒体函数读取由于篇幅所限这里不再详述读者可以参考Win SDK手册和Direct X SDK的联机帮助值得注意的是Direct Sound的缓沖区是循环的Lock返回两个指针数据必须分成两部分写入
数据进入DirectSoundBuffer后就可以调用IDirectSoundBuffer的声音控制方法来控制声音的播放停止频率声道等特性但要注意的是因为Win是多任务的设备有可能被别的程序占用所以IDirectSoundBuffer的功能调用可能会引发DSERR_BUFFERLOST错误此时如果要确保你的请求一定会得到响应则必须调用IDirectSoundBuffer::Restore以重新获得设备
掌握了这些基本概念后就可以在C++中编写Direct Sound的控制程序了但Delphi无法直接存取上面提及的数据结构为了解决这个问题我们可以定义一个数组分别代表不同的辅助缓沖区Dephi通过该数组的索引来使用多个缓沖区因此我们的DLL中至少包括以下的接口函数
CreateDSoundInterface(HWND hwnd)//初始化
LoadWave(int index char *filename)//装入wav数据
Play(int Index) //播放
Stop(int Index)//停止
Clear(int Index)//释放缓沖区
当然还可以加入其它控制例如对频率声道等的控制
有了动态链接库后在Delphi中编写混音器组件的方法就比较简单了与其它组件基本上没什么区别
首先新建一个组件(New Component)设定其祖先类型为TComponent然后编写相应的方法初始化设备实现DLL中提供的功能这里只作两点说明
不要在继承的Create函数中加载DLL和初始化设备不在构造方法中初始化设备是明智的做法因为这样做较安全
因为DLL是用C编写的所以接口函数说明必须是C的调用标准例如可以像下面这个样子
Var
DllFunction :
function(Parametre : ParaType) : RusultType; cdecl;
LibraryHandle=LoadLibrary(DllFiledll);
@DllFunction:=GetProcAddress(LibHandleDllFunction_Name);
组件单元编好以后可通过选择Component|Install Component菜单来将组件装入Delphi的组件库即可使用它
本文所介绍的程序在Visual C++ Delphi Direct X SDK下通过但程序功能只需VC Delphi Direct X (Visual C 内置Direct X SDK)支持即可若要确保程序能够正常运行则必须在Win下安装Direct X并将DLL文件放到\Windows\System目录下