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

原作者By Kylinx, 2003-5-15 ,E-mail:game-diy@163.com

整理:风里有梦

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

在DirectX8~9 SDK 中,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全称是DownLoadable Sounds

MSDN中这样解释:

A standard for synthesizing wave sounds from digital samples stored in software. The DLS level 1 and level 2 standards are published by the

MIDI Manufacturers Association.

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

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

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

IDirectMusicLoader8* g_pDMLoader=NULL;

IDirectMusicPerformance8* g_pDMPerformance=NULL;

IDirectMusicSegment8* g_pSegment=NULL;

首先,初始化COM

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

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

HRESULT hr = 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_OBJECTDESC ObjDesc;

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_TIME mtime;//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中的文档和例子吧!

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

[收藏]播放MIDI音乐——使用DirectMusic相关推荐

  1. java channel midi_为Java程序中添加播放MIDI音乐功能

    下载本文示例代码 Java在多媒体处理方面的确优势不大,但是我们在程序中有些时候又需要一些音乐做为点缀,如果播放的音乐是wav等波形音频文件,又挺大,所以背景音乐最好就是MIDI了,可是网上很多播放M ...

  2. MIDI应用: 播放midi音乐文件的方法 [Win32版本+ C语言版本]

    播放midi音乐文件的方法 背景说明: 在游戏编程中,给程序增加音效几乎是必须的;在普通程序中增加音效也会给使用者带来更好的体验;而mid格式的音效文件体积最小(大约1k到数十k),效果却不亚于MP3 ...

  3. 游戏编程入门(11):播放MIDI 音乐

    MIDI音乐是将音乐结合到游戏的最佳方式之一,本章就将介绍究竟如何使用相对较少的代码播放MIDI音乐. 本章内容包括: 如何使用MCI播放MIDI音乐 如何向游戏添加MIDI音乐 接上文 游戏编程入门 ...

  4. linux centos fedora rosegarden 播放 midi 音乐

    linux fedora32 播放midi音乐 其实这个日志,没想记那么多,只是为了在linux下找一个midi的播放器,默认播放器只能播放普通格式,不支持midi格式. 最终找到一个类似winamp ...

  5. Java 添加播放MIDI音乐

         Java 在多媒体处理方面的确优势不大,但是我们在程序中有些时候又需要一些音乐. 如果播放的音乐是wav等波形音频文件,又很大的话,所以背景音乐最好就是MIDI了. 网上很多播放MIDI的教 ...

  6. midi java_Java程序中添加播放MIDI音乐功能的实现方法详解

    JAVA在多媒体处理方面的确优势不大,但是我们在程序中有些时候又需要一些音乐,如果播放的音乐是wav等波形音频文件,又很大的话,所以背景音乐最好就是MIDI了,可是网上很多播放MIDI的教程都是简单的 ...

  7. 嵌入式(stm32)学习之路---MIDI音乐播放器

    STM32用蜂鸣器播放MIDI音乐(可以基于这个基础上开发简单电子琴/魔音盒),经典程序代码,程序代码注释简明,易懂,便于移植开发. 无源蜂呜器引脚定义 #define BUZZERPORT GPIO ...

  8. 【Win 10 应用开发】MIDI 音乐合成——音符消息篇

    在上一篇中,老周介绍了一些乐理知识,有了那些常识后,进行 MIDI 编程就简单得多了.尽管微软已经把 API 封装好,用起来也很简单,但是,如果你没有相应的音乐知识基础,你是无法进行 MIDI 编程的 ...

  9. 《电脑音乐制作实战指南:伴奏、录歌、MTV全攻略》——1.4 用电子琴软件弹奏MIDI音乐伴奏...

    本节书摘来自异步社区<电脑音乐制作实战指南:伴奏.录歌.MTV全攻略>一书中的第1章,第1.4节,作者 健逗,更多章节内容可以访问云栖社区"异步社区"公众号查看. 1. ...

最新文章

  1. BIML 101 - ETL数据清洗 系列 - BIML 快速入门教程 - 序
  2. sdn主要包含哪些接口_SDN 是什么?
  3. 四、【线性表】线性表的顺序表示和实现
  4. docker web程序本地化_Docker-01-Docker介绍
  5. webpack2入门概念
  6. 深度剖析数据中台提供的数据服务
  7. linux7自动挂载怎么做,CentOS7 Virtual Box 开机自动挂载共享文件夹
  8. 什么是Dropthings
  9. IIS6 下的Asp.net服务器安全配置
  10. 编程基本功:以输入法为例,谈谈测试案例的设计
  11. 计算机音乐广东爱情故事,改编自网易云音乐——广东十年爱情故事热评
  12. MATLAB的cat函数
  13. 学计算机科学与技术的考研方向,计算机科学与技术考研方向?
  14. 用计算机和电视机组成家庭影院,用电脑组建家庭影院:  最方便最实惠的玩法...
  15. AAAI2020论文列表(中英对照)
  16. 博士入坑必读教材-A-Z博士(PhD)顺利毕业必读指南
  17. VIN码识别/车牌识别:是入口,是门面
  18. 快排算法的针对重复键值的优化
  19. 推特开发者账号【推特开发者文档系列3】——推特标准接口API的请求频率限制说明
  20. session与登录机制

热门文章

  1. 计网复习——物理层习题
  2. 直播代码开发者发布的直播代码搭建教程
  3. Java - Stream
  4. 最简单的PS安装教程
  5. 名片自动录入系统的实现(转载)
  6. 父连杆、子连杆及关节
  7. 四川大学计算机综合实践报告,四川大学计算机综合实践报告完整版.pdf
  8. 城市轨道交通运营管理属于什么院系_城市轨道交通运营管理是什么
  9. 机器学习入门-提取文章的主题词 1.jieba.analyse.extract_tags(提取主题词)
  10. b级计算机考试在线试题及答案,全国计算机一级考试试题及答案