[收藏]播放MIDI音乐——使用DirectMusic
( 本文对象: 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相关推荐
- java channel midi_为Java程序中添加播放MIDI音乐功能
下载本文示例代码 Java在多媒体处理方面的确优势不大,但是我们在程序中有些时候又需要一些音乐做为点缀,如果播放的音乐是wav等波形音频文件,又挺大,所以背景音乐最好就是MIDI了,可是网上很多播放M ...
- MIDI应用: 播放midi音乐文件的方法 [Win32版本+ C语言版本]
播放midi音乐文件的方法 背景说明: 在游戏编程中,给程序增加音效几乎是必须的;在普通程序中增加音效也会给使用者带来更好的体验;而mid格式的音效文件体积最小(大约1k到数十k),效果却不亚于MP3 ...
- 游戏编程入门(11):播放MIDI 音乐
MIDI音乐是将音乐结合到游戏的最佳方式之一,本章就将介绍究竟如何使用相对较少的代码播放MIDI音乐. 本章内容包括: 如何使用MCI播放MIDI音乐 如何向游戏添加MIDI音乐 接上文 游戏编程入门 ...
- linux centos fedora rosegarden 播放 midi 音乐
linux fedora32 播放midi音乐 其实这个日志,没想记那么多,只是为了在linux下找一个midi的播放器,默认播放器只能播放普通格式,不支持midi格式. 最终找到一个类似winamp ...
- Java 添加播放MIDI音乐
Java 在多媒体处理方面的确优势不大,但是我们在程序中有些时候又需要一些音乐. 如果播放的音乐是wav等波形音频文件,又很大的话,所以背景音乐最好就是MIDI了. 网上很多播放MIDI的教 ...
- midi java_Java程序中添加播放MIDI音乐功能的实现方法详解
JAVA在多媒体处理方面的确优势不大,但是我们在程序中有些时候又需要一些音乐,如果播放的音乐是wav等波形音频文件,又很大的话,所以背景音乐最好就是MIDI了,可是网上很多播放MIDI的教程都是简单的 ...
- 嵌入式(stm32)学习之路---MIDI音乐播放器
STM32用蜂鸣器播放MIDI音乐(可以基于这个基础上开发简单电子琴/魔音盒),经典程序代码,程序代码注释简明,易懂,便于移植开发. 无源蜂呜器引脚定义 #define BUZZERPORT GPIO ...
- 【Win 10 应用开发】MIDI 音乐合成——音符消息篇
在上一篇中,老周介绍了一些乐理知识,有了那些常识后,进行 MIDI 编程就简单得多了.尽管微软已经把 API 封装好,用起来也很简单,但是,如果你没有相应的音乐知识基础,你是无法进行 MIDI 编程的 ...
- 《电脑音乐制作实战指南:伴奏、录歌、MTV全攻略》——1.4 用电子琴软件弹奏MIDI音乐伴奏...
本节书摘来自异步社区<电脑音乐制作实战指南:伴奏.录歌.MTV全攻略>一书中的第1章,第1.4节,作者 健逗,更多章节内容可以访问云栖社区"异步社区"公众号查看. 1. ...
最新文章
- BIML 101 - ETL数据清洗 系列 - BIML 快速入门教程 - 序
- sdn主要包含哪些接口_SDN 是什么?
- 四、【线性表】线性表的顺序表示和实现
- docker web程序本地化_Docker-01-Docker介绍
- webpack2入门概念
- 深度剖析数据中台提供的数据服务
- linux7自动挂载怎么做,CentOS7 Virtual Box 开机自动挂载共享文件夹
- 什么是Dropthings
- IIS6 下的Asp.net服务器安全配置
- 编程基本功:以输入法为例,谈谈测试案例的设计
- 计算机音乐广东爱情故事,改编自网易云音乐——广东十年爱情故事热评
- MATLAB的cat函数
- 学计算机科学与技术的考研方向,计算机科学与技术考研方向?
- 用计算机和电视机组成家庭影院,用电脑组建家庭影院: 最方便最实惠的玩法...
- AAAI2020论文列表(中英对照)
- 博士入坑必读教材-A-Z博士(PhD)顺利毕业必读指南
- VIN码识别/车牌识别:是入口,是门面
- 快排算法的针对重复键值的优化
- 推特开发者账号【推特开发者文档系列3】——推特标准接口API的请求频率限制说明
- session与登录机制