700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > [收藏]播放MIDI音乐——使用DirectMusic

[收藏]播放MIDI音乐——使用DirectMusic

时间:2020-02-27 22:17:45

相关推荐

[收藏]播放MIDI音乐——使用DirectMusic

( 本文对象: DirectMusic 初学者,想快速知道使用 DirectMusic 播放音乐的人 )

原作者ByKylinx, -5-15 ,E-mail:game-diy@

整理:风里有梦

(转载请保证文档的完整性)

在DirectX8~9SDK中,DirectMusic增加了很多新特性,我在这里单单讲用它播放Midi的部分

DirectMusic主要有下面几个部分组成:

IDirectMusicLoader8

IDirectMusicPerformance8

IDirectMusicSegment8

IDirectMusicSegmentState8

你也许会问:为什么没有IDirectMusic8?这个是因为在DirectMusic中,Microsoft把IDirectMusic8“隐藏”起来了,也就是说,我们不需要使用这个接口,

可以通过其他方式轻松实现

IDirectMusic8

IDirectMusicLoader8

IDirectMusicPerformance8

IDirectMusicSegment8

AudioPath

IDirectMusicSegmentState8

IDirectMusicLoader8,加载器。用于加载Mid文件等等

IDirectMusicPerformance8用来控制DirectMusic的接口

IDirectMusicSegment8音乐数据段,加载音乐后存放的位置

IDirectMusicSegmentState8音乐段状态

顺便说一下DLS

我们知道,mid文件纪录的只是“乐器”,音调和实践。在播放的时候,声卡对mid文件进行编码,而每种声卡上的“波表”都有差别,所以在编码的时候,播放出来的声音

就与声卡有关。打个比方,你在A机子直接播放和B机子直接播放同一个mid文件,如果A的声卡和B的声卡不同的话,听起来的音质完全不一样(我们耳朵能听到的只能

是模拟的声音而不是数字化的声音数据)。正因为如此,Microsoft在DirectMusic中使用了DLS,很好的解决了这个问题

DLS全称是DownLoadableSounds

MSDN中这样解释:

Astandardforsynthesizingwavesoundsfromdigitalsamplesstoredinsoftware.TheDLSlevel1andlevel2standardsarepublishedbythe

MIDI ManufacturersAssociation.

原理就是在DLS文件中通过使用乐器的单音采样来处理这个问题。所以在DirectMusic中

使用默认的DLS文件,把mid音乐转化为数字化的音乐。数字化的声音就可以通过数字——〉模拟(D/A)转换,随后播放出来的声音听起来都是一样的(因为不需要再声卡上重新编码了啊!)

好了,说了这么多,该开始应用了

IDirectMusicLoader8*g_pDMLoader=NULL;

IDirectMusicPerformance8*g_pDMPerformance=NULL;

IDirectMusicSegment8*g_pSegment=NULL;

首先,初始化COM

(这个东西博大精深,推荐一本:com本质论!看过这本书后,包你对DirectX的认识有新的飞跃!)

========================================================================

HRESULThr = CoInitialize(NULL);

If( FAILED(hr) )

{; //处理错误}

以下为了方便,省了错误处理

//下面创建加载器

CoCreateInstance(CLSID_DirectMusicLoader,//组件的GUID

NULL,//不是创建集合

CLSCTX_INPROC,//创建的环境

IID_IDirectMusicLoader8,//接口的GUID

(void**)&g_pDMLoader);//被创建的接口指针

//创建控制器

CoCreateInstance(CLSID_DirectMusicPerformance,//组件的GUID

NULL,//不是创建集合

CLSCTX_INPROC,//创建的环境

IID_IDirectMusicPerformance8,//接口的GUID

(void**)&g_pDMPerformance);//被创建的接口指针

//初始化声音通道

g_pDMPerformance->InitAudio(

NULL,//DirectMusic对象的指针,因为不需要我们管理,所以让它自动进行

NULL,//DirectSound对象的指针,同上

hWnd,//窗口句柄

DMUS_APATH_SHARED_STEREOPLUSREVERB,//声音通道(AudioPath)类型:立体声+混响

64,//音乐通道数

DMUS_AUDIOF_ALL,//声卡的所有特性

NULL//DMUS_AUDIOPARAMS对象的指针

);

// get current working directory

wchar_t wszDir[MAX_PATH];

if ( NULL == _wgetcwd( wszDir,MAX_PATH) )

return(-1);

//MULTI_TO_WIDE(wszDir, szDir);

// tell the loader were to look for files

hr = g_pDMLoader->SetSearchDirectory( GUID_DirectMusicAllTypes, wszDir, FALSE );

//好了,初始化Dmusic完成

//下面读入mid文件

//g_pDMLoader->LoadObjectFromFile(

CLSID_DirectMusicSegment,//组件的GUID

IID_IDirectMusicSegment8,//接口的GUID

file;//文件名,注意用Unicode

(void**)&g_pSegment//音乐要装到的段

);

//填充结构

DMUS_OBJECTDESCObjDesc;

memset((void*)&ObjDesc, 0, sizeof(DMUS_OBJECTDESC));

ObjDesc.dwSize = sizeof(DMUS_OBJECTDESC);

ObjDesc.guidClass = CLSID_DirectMusicSegment;

wcscpy( ObjDesc.wszFileName, pszFile ); // pszFile是UNICODE MIDI 文件路径

ObjDesc.dwValidData =DMUS_OBJ_CLASS|DMUS_OBJ_FILENAME;

//装入MIDI到g_pSegment对象

hr = g_pDMLoader->GetObject(&ObjDesc,IID_IDirectMusicSegment, (void**) &g_pSegment);

hr = g_pSegment->SetParam(GUID_StandardMIDIFile, -1, 0, 0, (void*)g_pDMPerformance);

hr = g_pSegment->SetParam(GUID_Download, -1, 0, 0, (void*)g_pDMPerformance);

//从ASCII转换到UNICODE的函数有

//MultiByteToWideChar(

CP_ACP,//ASCII码

0,//

asciifile,//要转换的ascii字符串

-1,//要转换的字节数,-1表示以’/ 0’ 结尾的字符串

UnicodeFile,//转换后UNICODE存放的地方

MAX_FILE_LENGTH);

//或Runtime

//下面播放mid音乐

g_pSegment->SetRepeats(looptimes);//重复的次数,如果是DMUS_SEG_REPEAT_INFINITE则为无限

g_pSegment->Download(g_pDMPerformance);//使用DLS,把MID数据转换成数字化的音乐数据

g_pDMPerformance->PlaySegmentEx(g_pSegment,//要播放的段

NULL,//保留,必须为NULL

NULL,//pTransiton

0,//播放的标志

0,//开始的位置

NULL,//用与接收段状态的指针,如果不需要,就为NULL

NULL,//使用默认

NULL//默认的AudioPath

);

//暂停播放

MUSIC_TIMEmtime;//MUSIC_TIME就是一个long类型

g_pDMPerformance->GetTime(NULL,&mtime);//得到暂停的位置

//停止播放

g_pDMPerformance->Stop(NULL,//要停止的段,NULL表示全部段都停止

NULL,//段状态

0,//多少时间后停止,0表示立即

0//标志

);

//从暂停点继续播放

g_pSegment->SetStartPoint(mtime);//播放点

//播放

g_pDMPerformance->PlaySegmentEx(g_pSegment,

NULL,

NULL,

DMUS_SEGF_REFTIME,

0,

NULL,

NULL,

NULL

);

g_pSegment->SetStartPoint(0);

//释放DirectMusic

g_pDMPerformance->CloseDown();

g_pSegment->Release();

g_pDMPerformance->Release();

g_pDMLoader->Release();

CoUninitialize();//停止使用COM

好了,整个过程就是这么简单!当你理解后,可以自行把上面的代码封装为一个类

这样,你就可以在你的游戏中实现MID的播放啦!

当然,播放mid只是DirectMusic功能中很小的一部分

它还能播放wav文件,sgt文件,实现3D声音等等,具体内容自己参考MSSDK中的文档和例子吧!

(参考资料: MSDN的DirectMusic部分)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。