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

游戏音效设计:DirectMusic与MIDI音乐的运用 本文详细探讨了DirectMusic音频路径、MIDI与波形音乐的区别,以及如何在游戏中实现背景音乐和声音效果。通过DirectMusic的音量调整、音频路径管理以及MIDI音乐的优势等方面,给出了游戏开发者在音效设计上的实用建议。 阅读详情
(本文对象: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部分)

游戏编程中的音乐:DirectMusic与DirectSound技术 本文探讨了DirectSound和DirectMusic在游戏编程中的应用,特别是DirectMusic如何通过控制音频路径、加载和播放MIDI音乐来增强游戏体验。介绍了DirectMusic的音频路径概念,以及MIDI与.WAV音乐格式之间的对比,强调了MIDI音乐在游戏中的性能和大小优势。文章还详细解析了音乐测试程序的代码,说明如何使用DirectMusic在VB游戏中加载和播放MIDI文件。 阅读详情

相关推荐

使用DirectMusic为VB游戏添加背景音乐

本文介绍了DirectX中DirectMusic组件的使用方法,这一组件能够帮助开发者为他们的Visual Basic游戏添加MIDI格式的背景音乐。通过实例代码的分析,文章解释了如何停止音乐播放以及在程序结束前清理资源。此外,还探讨了MIDI音乐在游戏中的优势,特别是在不降低游戏帧率的情况下。

weixin_29885875的博客 340

用DirectX Audio和DirectShow播放声音和音乐(6)

加载音色库(乐器)DirectMusic 加载器在使用固有文件或者MIDI文件的时候会自动加载默认的音色库。乐器总是被一组一组地使用,很多组乐器音色的集合被称之为DLS音色库(可下载的音乐)。每组乐器使用三个值编号,它们是:最高有效位(most-significant byte,MSB),最低有效位(least-significant byte,LSB)和组编号。通常播放MIDI文件的乐器组是标准

gmq517的专栏 3726

使用DirectX音频编程:深入DirectMusic类

本文介绍了DirectMusic类的实现和如何在Visual Basic中使用它来播放声音和音乐。通过clsDirectMusic8类的代码示例,我们学习了如何控制声音的播放位置、循环播放以及如何管理MIDI序列。

weixin_35906794的博客 374

声音引擎之DirectMusic(1)---重要概念

一、概念     我在我的引擎使用的是DirectMusic,他是高层的audio API,他比DirectSound方便很多,他可以播放WAV文件与MIDI文件,在这里我主要介绍如何播放WAV文件。     首先,所有的声音的播放都要依赖于两个COM对象,一个是IDirectMusicLoader8,他负责从磁盘上读取声音文件;还有一个是IDiretMusicPerformace,他负责播放

ProgramRookie的专栏 1750

DirectMusic组件在游戏开发中的应用

本章深入介绍了DirectMusic组件在游戏开发中的应用,展示了如何在Visual Basic游戏中使用MIDI格式播放背景音乐。通过具体的代码示例,读者可以了解到如何停止音乐播放、释放DirectMusic对象以及在游戏结束时执行清理工作。DirectMusic为游戏提供了高效处理音乐的能力,尤其在不降低游戏帧率的情况下,能够处理复杂的音乐与音效混合。

weixin_32251525的博客 444

使用directMusic播放midi单音

使用directMusic播放midi单音

DirectSound and DirectMusic

DirectSound and DirectMusic are separate components of DirectX with some overlapping functionality. Both play WAV sounds, and DirectMusic ultimately synthesizes all sounds into waveforms that are play

死胖子的专栏 1074

这是一个界面非常友好、拥有16个可调MIDI通道、支持卡拉OK字幕的播放器!推荐!

这是一个界面非常友好、拥有16个可调MIDI通道、支持卡拉OK字幕的播放器!推荐!

用DirectX Audio和DirectShow播放声音和音乐(5)

使用DirectMusic在DirectAudio 中,DirectSound负责数字音频方面的处理,而DirectMusic则负责Midi文件(Musical Instrument Data Interface,数字音乐格式,.mid作为文件扩展名),DirectMusic固有音乐文件(.sgt文件)和数字录音设备录制的波形格式文件(.wav文件)等文件的播放操作。能体现DirectMusic的...

weixin_34378969的博客 233

DirectMusic DirectX VC++有注释

DirectMusic DirectX VC++有注释

HID报告描述符实战解析:从Usage到Item的完整设计流程

本文深入解析了HID报告描述符的设计流程,从核心概念Usage(用途定义)入手,详细阐述了如何通过Item(条目)的三种角色——全局、局部与主干,构建出能被系统正确识别的设备“说明书”。文章以标准USB鼠标和键盘为例进行实战拆解,并介绍了使用Report ID与自定义设备等进阶设计方法,帮助开发者掌握这一实现USB设备即插即用的关键技术。

weixin_29230865的博客 282

使用DirectMusic

// include dsound, dmusic #include #include #include #include #include // direct music globalsI DirectMusicPerformance *dm_perf = N

1000

aruco_ros实战:从USB摄像头到Marker位姿检测全流程解析

本文详细解析了使用aruco_ros从USB摄像头实现ArUco Marker检测与位姿估计的全流程。内容涵盖环境搭建、核心launch文件配置、可视化调试、位姿数据解析以及深度优化技巧,帮助开发者快速掌握ROS下的视觉定位关键技术,并集成到机器人项目中。

weixin_29230805的博客 265

Windows编程 DirectSound DirectMusic 音效和音乐

版本:VS2015 语言:C++   最近项目遭遇变故,公司随意开人,导致原本要出包的项目现在乱七八糟。现在不知道未来会怎么样……   我们Windows上2D的编程今天是最后一课了,没有听错,2D完结,接下来就是3D了,书已经准备好了,就等我回去去取,有没有点小兴奋呢?嘛,我现在是还没有接触过3D引擎啦,不过等学完再去看看Unreal岂不也是美哉。   今天要讲的是在dx中演奏音乐和

暗光之痕的博客 3323

Dify插件离线部署全攻略:从下载到安装的完整流程

本文详细介绍了Dify插件离线部署的完整流程,针对企业内网等无网络环境需求。核心步骤包括在联网环境下载插件包、在特定Python 3.12.9环境下使用专用工具进行离线重打包,以及最终在离线Dify环境中安装验证。重点解决了离线安装的核心难题,并提供了环境配置、批量处理和故障排查等实用技巧,帮助用户实现Dify插件的顺利离线部署。

seed的博客 657

智驾系统分层架构:从传感器到执行器的全链路解析

本文深入解析了智能驾驶系统的分层架构,从传感器数据采集融合、应用层决策到车辆管理层执行,完整呈现了从感知到控制的全链路工作流程。文章重点阐述了架构设计的核心优势在于接口标准化与模块解耦,以ACC和LKA协同场景为例,说明了各层级如何通过清晰分工与高效协作,实现复杂系统的可靠、灵活与易于升级。

weixin_29219189的博客 399
下一篇: string.h的误解
thinkinnight
博客等级 码龄21年 3粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值