DirectMusic™ 是DirectX® API的音乐部分。与DirectSound® API对数字音频采样的捕获和回放不同, DirectMusic 处理基于消息机制的、在硬件或软件合成器中转换为波形样本的音乐数据。
DirectMusic
这篇文档包括了以下的Microsoft® DirectMusic™
应用程序接口 (API)的
主题:
* 关于 DirectMusic
* 为什么使用DirectMusic?
* DirectMusic 基本要素
* DirectMusic 教程
* DirectMusic 参考手册
* DirectMusic 例程
关于DirectMusic
默认的软件实现是使用Microsoft® Software Synthesizer 创建波形样本然后由DirectSound 输出。乐器的声音依照the downloadable sounds (DLS)标准来合成。
由于支持 MIDI格式, DirectMusic 可实现实时作曲。这种音乐不是由什么算法生成的,而是有基于由人类作曲家作出的自然风格。它的曲风多变,且可对程序事件动态响应。
如同其他的DirectX组件,DirectMusic 提供了一套基于对象组件模型— Component Object Model (COM)的API。
DirectMusic 兼容于 Windows® 95,
Windows 98, 和
Windows 2000.
为什么使用 DirectMusic?
DirectMusic API 满足了在
计算机平台上传递音乐的基本要求:
* 回放效果一致性。由于使用DLS标准,一个应用可以使其中的乐器声在所有不同的机器上听起来都是这件乐器本身不变的声音。
* Jitter-free timing. 基于MIDI的音乐的回放可以精确到两毫秒。
* 可扩展性。DirectMusic 没有把开发商限制在一个基础特性集之中。
还有,DirectMusic 为简化程序开发和丰富用户的体验提供了重要的特性:
* 简单的读入和播放音乐机制,与具体的实现技术细节无关。DirectMusic 支持标准的MIDI 文件,音乐段, 以及第三方技术。
* 多重播放机制。多个音乐片段可以用完全独立的时间片、乐器集等同时播放。
* 超过16个MIDI 通道。通过把播放通道映射到通道组,DirectMusic 突破了16 通道的限制,可以同时播放任意数量的声音,只取决于合成器的上限。.
* 对DLS 的自动管理。
* 动态、交互的回放。在DirectMusic Producer的帮助下,DirectMusic播放引擎可被用来生成动态音乐音轨和储存创作素材。而且乐曲直到在被播放才会确认它的最终格式,在这以前都可以对程序时间作响应。
* 通过使用一个主时钟控制,可以使所有的乐曲回放同步。
这一节介绍DirectMusic的各部分:
* 核心层和Performance层
* DirectMusic 对象和接口综述
* DirectMusic 数据流综述
* DirectMusic 消息
* DLS
* Microsoft 软件合成器
想获知如何在应用中使用这些部件的信息,见DirectMusic 基本要素部分。
核心层和Performance层
DirectMusic 核心层管理时间分片和端口,以及为管理DLS collection提供服务。它支持缓冲的、被分为时间片的MIDI 输入和输出。缺省情况下,DirectMusic 可以自己对MIDI数据序列化。
核心层包括Microsoft Software Synthesizer,它使用DLS标准从序列化的MIDI 数据中合成波形输出。
DirectMusic performance层负责更高级的音乐回放,包括读入、回放 MIDI 文件和对基于用DirectMusic Producer 或别的类似的软件的音乐的组合。
核心层的接口和相应的API 成员可在Dmusicc.h中找到,performance层的,可在Dmusici.h 中找到。
DirectMusic 对象和接口综述
在 DirectMusic 中,把对象和它们的COM接口作一下区别是有好处的,因为许多对象有多个接口。例如,支持IDirectMusicCollection 接口的对象也支持标准的COM IPersistStream 接口和IdirectMusicObject。
在这篇文档里,DirectMusic 对象通过它们主要的或唯一的名字被提及,但没有打头的“I”;这样IDirectMusicCollection 表示的对象被称为DirectMusicCollection 对象。对象也可能用短名表示,例如collection, performance, segment, 和 track.
接口
指针通常被当作指向它们的对象的指针来使用,这样那些对象就可以通过别的接口的方法来访问到。例如,有个 IdirectMusicDownloadedInstrument 接口,自己没有一个方法而只是被当作别的接口的方法的一个参数来使用。
DirectMusic 由许多互相之间联系相当复杂的对象和接口组成。然而,还可以根据它们的功能来分成几类,如下所示:
* 核心对象和接口
* 载入对象和接口
* 乐器(Instrument)对象和接口
* Tool对象和接口
* Performance对象和接口
* Composition对象和接口
* 合成器对象和接口
DirectMusic 对象
DirectMusic 对象由 IDirectMusic 接口表示,用来创建端口和缓冲、与DirectSound 联系和设置一个主时钟。每个应用只能有此对象的一个实例。
许多应用从不需要直接使用IDirectMusic 接口。这点它与别的DirectX 基础接口不同。例如, IDirectSound 是所有的 DirectSound 应用的起始点,完成一些基本的任务如设置协作优先级和创建声音缓冲。而在DirectMusic中,大多数初始化工作由别的对象如DirectMusicPerformance 来做,而这些对象通过直接对CoCreateInstance的调用来独立创建。
端口
每个发送和接收音乐数据的设备都被一个DirectMusicPort 对象封装起来。IDirectMusicPort 接口的方法允许直接对端口操作,但大多数应用是用不到这些方法的,因为端口由performance对象来管理。例如,你通过DirectMusicPerformance对象为一个端口分配了一个通道,那么在这通道内的数据就会被正确处理。
缓冲
IDirectMusicBuffer 接口表示了当前正准备从一个端口播出(或读入)的数据。大多数的应用不直接处理缓冲对象,但它的方法能直接操纵其中的内容。
Thru
IDirectMusicThru 接口被用来建立从一个捕获端口到另一个端口的数据直接传输。
参照时钟
实现IReferenceClock接口的对象表示了对所有DirectMusic 活动进行同步的主时钟和某个端口的隐含时钟。
载入对象和接口
有些特定类型的对象,比如DirectMusicCollection 和DirectMusicStyle,必须在它们被组合进 一段音乐演奏之前载入(或从文件中读入)。另一些,比如DirectMusicSegment,可能要即时地载入和构造。这一节介绍的是关于载入的基本接口。
载入
DirectMusicLoader 对象,通过IDirectMusicLoader 接口管理对象的枚举、高速缓冲和载入。
流
从某个文件或资源中正在读的数据用一个流对象表示。大多数应用不需要直接地处理流,因为它们由载入程序创建和管理。流对象实现了下列接口:
* IStream 让数据从文件或某个资源流向正被载入的对象,它通过自己的IPersistStream接口实现来分析这个被载入的对象。
* IDirectMusicGetLoader 只有一个返回指向创建流的DirectMusicLoader对象的指针的方法。它在一个流中发现了对其他对象的一个参照时被使用,正被载入的对象需要调用载入程序载入这个参照对象。
要更详细地知道这些接口在载入过程中的使用,见 DirectMusic 载入程序。
对象
每个DirectMusic 对象代表了一个支持IDirectMusicObject接口的文件或资源,这些都被载入程序当作一个普通
指针来使用。当应用获得一个指向此接口的
指针后,IDirectMusicObject::QueryInterface 方法会被用来去获得指向对象自己的接口如IdirectMusicCollection 或IDirectMusicStyle的指针。然而,你通常能通过调用IDirectMusicLoader::GetObject来获得你想要的接口。
IDirectMusicObject 的方法被载入程序在其内部用来区分诸对象。
乐器 (instrument)对象和接口
instrument就是代表了一种基本音色或别的声音的一种对象。除了已定义的硬件MIDI 端口,每个instrument都与它自己的Downloadable Sounds (DLS)集合相联系,这个集合必须在instrument 对象被使用前就下载到端口上。
DLS可以在三个抽象层上处理。在最高层,你从某个文件装入一个band并让这个band对象处理为此instrument下载的DLS。接下去的一层,可以直接访问在一个collection对象中的独立的instrument并把它们下载到端口上。最低一层,只与DLS数据本身打交道。
下面的对象和接口用来管理instrument:
collection
instrument被存放在DirectMusicCollection 对象中,此对象表示了一个 DLS 文件的实例。当DirectMusicCollection 对象被载入时,IDirectMusicCollection 接口可以被用来枚举collection中的instrument和得到一个指向有给定的MIDI patch 数的instrument对象的
指针。
Instrument
一个collection中的某个instrument由指向IDirectMusicInstrument接口的一个指针来表示。这个指针可被传送到IDirectMusicPerformance::DownloadInstrument 或 IDirectMusicPort::DownloadInstrument方法为一个端口下载DLS 数据。
当一个instrument被下载后,由一个IDirectMusicDownloadedInstrument接口
指针表示,这个指针只在调用IDirectMusicPort::UnloadInstrument反下载instrument时被用到。
需要为一个instrument下载自己的DLS数据的应用(比如collention 编辑工具)使用IDirectMusicPortDownload接口的方法(由端口对象实现)来把那些数据送往合成器。当这个接口被用来为vinstrument 数据申请缓冲时,一个 IDirectMusicDownload 接口指针被返回。这个接口的唯一一个方法是用来获得指向缓冲自身的指针。
Band
DirectMusicBand 对象表示了一个instrument 集合和一个音乐段的MIDI program的变化。
IDirectMusicBand 接口可被用来下载和反下载 band。它还有一个从一个band中创建一个二级段的方法,这个段可被播放以用来影响MIDI program变化。
Collection对象和band 对象的主要区别如下:
* Collention是一组在任何段的回放中都能使用的instrument。Band是一组演奏特定段的instrument。
* Collection中的instrument包括了定义自身音色的DLS数据。Band中的instrument没有这些数据但与一个或多个collection中的instrument相联系。
* Collection中的instrument并不是固有地和某个段的所有特定performance 通道(P通道)相联系。一个band为在段中的每个P通道分配了instrument的patch 数和一个声音优先权。
* Collection并不包括instrument如何演奏的信息。Band包含了每个instrument的音量、均衡、移位的设置。
Tool对象和接口
Tool是那些截取音乐信息并在它们被传送到端口之前进行处理的对象。所有的tool(除了DirectMusic自带的输出tool)是应用定义的。
Tool
IDirectMusicTool 接口代表了一个tool。此接口的方法由应用或DLL来完成以做到tool的通用性。
Graph
Tool被集中在一个Graph内,用IDirectMusicGraph 接口表示,这个接口由segment和performance对象共同完成。此接口被用来从一个tool到下一个指示消息、往graph中加入tool、为独立的tool取回指针,和关闭graph。
Performance对象和接口
下面的对象和接口用来对音乐数据的回放。拥有总数超过75个的方法,这一组的接口在任意一个DirectMusic应用中都起重要作用。
Performance对象
DirectMusicPerformance对象是音乐回放的总管理者。它通过IDirectMusicPerformance 接口、添加或删除端口、下载instrument、连接graph (tool的集合)、管理众多segment的通告事件、以及播放segment。
Segment对象
一个DirectMusicSegment 对象代表了一块数据(通常是一个音乐片段,包括在一个或多个track中)。通常一个segment由文件装入或是由DirectMusicComposer 对象实时创建。播放segment时,应用往IDirectMusicPerformance::PlaySegment 方法传递IDirectMusicSegment 接口的指针。
IDirectMusicSegment 接口的方法用来管理时间分片和循环、事件通告、graph、和别的各种segment的参数。
一个正在播放的segment的实例由IDirectMusicSegmentState接口表示。这个接口的方法返回有关回放状态的信息,指向此接口的指针被performance对象用来停止或删除segment实例。
Track
一块已被分时的特殊类型的数据由DirectMusicTrack 对象表示,可更简单地被叫做track。IDirectMusicTrack 接口的方法用来设置和获取数据、播放数据、以及设置通告。大多数应用并没有直接使用到这个接口,因为通常track对象是由包含它们的DirectMusicSegment对象的方法来处理的。
注意
DirectMusicTrack 与一个instrument的track是不同的,DirectMusicTrack 可表示任意种类的分好时间片的数据,比如MIDI 消息,一段chord progression(和音?)或band的变化。
Composition对象和接口
这一组的对象和接口用来进行乐曲的即时写作。除去作曲者自身,它们表示了从如DirectMusic Producer那样的软件生成的文件中载入的数据。想获得每个对象的更详细的信息,参见乐曲写作(Music Composition)部分。
Composer
IDirectMusicComposer 接口的方法允许一个应用去作出乐曲段和过渡,同时使用到chordmap,style,和一个人类作者创建的摸板。
style
style包括了一段乐曲的基本信息,Styles 通常成为了segment 的一部分,在幕后做大多数的事。它们也能被用来即时作出全新的segment。Style用IDirectMusicStyle 接口来表示。
Chordmap
DirectMusicChordMap 对象表示了一个和音(chord)的集合,以及DirectMusicComposer 在在一段乐曲中判断chord progression时用到的路径。
IDirectMusicChordMap 接口由DirectMusicChordMap对象从一个文件中载入时获得。一个指向此接口的指针被传如IDirectMusicComposer 以便一个段或乐曲过渡能实时地使用chordmap作出。你还能通过应用一个新的chordmap 来改变一个已存在的段的和音模式。
摸板
摸板是一种特殊的DirectMusicSegment 对象。它们从不被直接播放但被DirectMusicComposer 在实时构建基于style和chordmap的段时使用。
合成器对象和接口
合成器负责把MIDI信息转化为波形格式数据并输出到波形
输出设备上去。虽然DirectMusic有自带的软件合成器,它也允许自定义合成器。而且它允许输出到指定的不同设备。有关此主题的信息包含在DirectX Device Driver Kit(DDK)中。
合成器
一个由应用实现的合成器由IDirectMusicSynth 接口来表示。大多数应用没有使用到这个接口,
合成槽(Synth Sink)
合成器把数据送入的波形流,例如 DirectSound 或 Win32 的波形格式音频,用IDirectMusicSynthSink 接口表示。大多数应用并不使用此接口,所以DirectX 开发人员参考中也没有提供它的文档。
DirectMusic 数据流综述
通常一个DirectMusic 应用从以下的一个或多个资源中获得音乐数据:
* MIDI 文件。
* 诸如DirectMusic Producer 等应用中创作的段文件。
* 诸如DirectMusic Producer 等应用中的创作的组件文件并用DirectMusicComposer对象转化成一个完整的乐曲 。
从这些资源来的
数据封装在DirectMusicSegment 对象中。每个segment 对象代表了从一个单独的资源中来的数据。在演奏的任一刻可能有一个或多个segment在播放:一个主segment(primary segment)或可能有的多个次segmennt(secondary segments)。
资源文件可以被混合,例如,一个基于MIDI 文件的次segment可以和一个基于segment文件的主segment一同播放。
每个segment包括多个track ,每个track含有某中特定类型的数据,如节拍的变化。
大多数 track在当segment被performance对象播放时产生消息。而performance 对象向所有应用定义的tool发送这些消息,让它们能有机会对消息进行修改、传送和删除消息、传递新的消息。Tool 根据各个segment graphs 只处理从它们自己的segment发来的消息来分组,一个 performance graph 可以接受从所有的segment发来的消息。
最后,消息被传递到输出tool,它把数据在送往端口前转化为MIDI格式。Channel-specific(专有通道?) 的MIDI 消息被直接指向指定的以端口分组的通道。端口把把它们组合为一个声音波形流向波形
输出设备(通常是一个DirectSound 缓冲)。
下面的图是音乐数据是如何从文件到波形输出设备经过的概况。为简单起见,只显示了一个segment。 注意这个segment 只从三个可能的资源中得到数据: MIDI 文件、或一个写好的segment文件、或是由DirectMusicComposer 对象组合拢的component 文件。
更详细的在performance中的消息的流程,参见DirectMusic 消息部分
有关怎样实现上述图表所示的过程的信息,参见DirectMusic 基本要素章节,特别是DirectMusic 载入程序 和 播放音乐部分
关于segment 和 component file 更多的信息,见 Music Composition 部分。
DirectMusic 消息
音乐数据以消息的形式通过DirectMusic performance 引擎传递。大多数的 DirectMusic 应用不必直接去处理消息,但知道消息的一些基本知识能帮助你了解DirectMusic 是如何工作的。
DirectMusic 工作时用到两类不同的消息:
* Performance 消息,基于DMUS_PMSG 结构。所有有序的数据都以这种格式通过performance 引擎。此类消息包含了数据的分时(timing)和路由(routing)的详细信息。
* 标准 MIDI 消息。它们可以从MIDI文件或设备中读出并被直接传送到另一个设备或在被传送到performance 时转化为DMUS_PMSG 格式。最终输出到合成器的仍然是MIDI 消息的格式。
* 通道(Channels)
* 消息创建和传递( Creation and Delivery )
* Performance 消息类型
* MIDI 消息
Channels
Channel对一个指定到performance的消息来说是它的目的地(destination)。例如,一个 channel 可能接收到一个note-on 消息,此消息引起在此channel上的instrument产生一个声音;或者是一个
程序变换(program change)消息为它指派了一个别的instrument。(见MIDI Channel 消息)
按照MIDI 1.0 标准,可以有16个MIDI channels,以为意味着可以同时演奏有多于16个的instrument,为了支持这个标准且可同时为应用提供更多的channel,DirectMusic提出 channel组(channel groups )。最多可同时有 65,536 个channel 组,每个组可包括16个channel ,这样总共可以有超过一百万个channel。一个特定的端口(port)可以分配任意多个channel组而只受它的支持能力限制。传统(legacy)的 MIDI 硬件端口只支持一个channel组。
系统独占(System exclusive)消息可在一个channel组内访问所有的16 个channel,但不能访问别的channel组。
在DirectMusic performance对象中的每个instrument都拥有一个单独的performance channel, 或者说是 PChannel。 PChannel 表示了在一个特定(particular)的端口上的特定的组内的特定的MIDI channel。当一个band 被performance所选择时,在band中的每个instrument 都被单独映射到一个channel。
实际可以同时被演奏的note数目受到端口的可用的voice数的限制。(这个数字可以由DMUS_PORTPARAMS结构的dwVoices成员来决定。) Voice 其实是一个用于对在一个channel上正被演奏的note的合成(synthesis )的资源的集合。当有超过可行的note数的note演奏时,一个或多个的note不得不被合成器取消。这取决于当前演奏note的voice的优先权,而这又基于channel的优先权。默认的是,channel 是根据它们的索引值来排列的,除了channel 10,MIDI percussion channel,被赋予最高。然而应用和合成器可以设置自己的channel 优先权。
更多的channel 优先权的信息,见IDirectMusicPort::GetChannelPriority的说明,也可见DMUS_CHANNEL_PRIORITY_PMSG。
消息的创建和传递
当一个segment 演奏时, 它的大多数track 会生成包含在回放过程中发生的事件的信息的消息。(更多的信息,见Tracks。)
有些track 能发送不止一种的消息。例如, style track 可发送note 消息和time signature (
时间戳)消息。这种情况下,应用可以禁用track中的一些消息。更多的信息,见设置与获取Track 参数。
应用也可以直接往
队列中放入消息。例如你可以这样做来改变节拍(tempo)。例子源码可见IDirectMusicPerformance::SendPMsg。
Performance 引擎决定了每个消息何时将被实时地处理。对于channel 消息,performance 还决定了此消息指向哪个Pchannel。Message 结构的DMUS_PMSG 成员存放了有关消息的信息,包括消息类型、它的track来源、接收此消息的第一个graph和tool的指针。
普通的消息,如tempo 和 time signature 消息,能立即被performance处理和释放掉。另一些消息,如note 和 patch change 消息,被放到队列中,按
时间戳顺序处理。
注意
Tempo 消息(DMUS_TEMPO_PMSG) 告知 performance怎样把music time转化为 reference time(译者注:tempo 有“节拍”的意思,大概是告知performance 节拍与真实时间的比值关系)。 Time signature 消息(DMUS_TIMESIG_PMSG) 是纯信息的,因为time signature 建在segment里面而不能被改变。
消息首先被送往segment的graph中的每个tool 中,然后是performance 的graph中的每个tool中。(应用会负责创建着两个graph或其中之一,并定义号tool。没有缺省的graph。)
Graph中的第一个tool 处理消息后,如果要继续把它传下去,graph 把指向下一个tool的
指针给此消息。 (向对此过程了解更清楚,见教程2:使用tool 。)
此时graph 还为这个消息作上一个“递送类型”的标志,它决定了此消息何时被递送到下一个tool去。这个标志取决于tool 希望得到何种递送类型:
* DMUS_PMSGF_TOOL_IMMEDIATE,立即递送到下个tool 。
* DMUS_PMSGF_TOOL_QUEUE,消息将刚好在它要被播放之前递送,这个时间是考虑适当的延时而推测出来的。(见延时和碰撞时间(Bumper Time))。
* DMUS_PMSGF_TOOL_ATTIME ,消息将被确定在被处理时递送。通告消息就被赋予此种标志,因为处理通告消息不需要延时。
当前的tool 有在graph 往消息上贴标志后再改变递送类型的机会。
最后,除非消息被取消,它会到达DirectMusic 输出 tool,它会把所有接收到的数据都转化为标准的MIDI消息并通过端口缓冲传送到合成器(synthesizer)。
Performance消息类型
消息被存放在几个从DMUS_PMSG派生而来的结构中。因为C 语言不支持继承,DMUS_PMSG的成员以DMUS_PMSG_PART 宏的形式被包含在对每种消息类型的定义中。这些成员包含了所有消息的普通数据,包括消息类型、
时间戳、消息被送往的Pchannel、以及接下来要对它进行处理的是哪个graph 和tool。还有一些成员包含了某种消息所特有的数据。
下面是定义的消息结构:
DMUS_PMSG 简单消息,无额外参数。
DMUS_CHANNEL_PRIORITY_PMSG Channel 优先权改变。
DMUS_CURVE_PMSG Curve。
DMUS_MIDI_PMSG 任意的不属于特殊消息类的MIDI 消息,例如控制改变消息。
DMUS_NOTE_PMSG Music note。( MIDI note-on 与 note-off消息也结合在这种消息里。)
DMUS_NOTIFICATION_PMSG 通告。
DMUS_PATCH_PMSG MIDI patch 改变。
DMUS_SYSEX_PMSG MIDI 系统独占消息。
DMUS_TEMPO_PMSG Tempo 改变。
DMUS_TIMESIG_PMSG Time signature 改变。
DMUS_TRANSPOSE_PMSG 传输。
MIDI 消息
这里大致讲一下标准的MIDI消息以及它们如何从一个MIDI文件中获取并被DirectMusic所处理。多数应用直接处理MIDI消息,因为 loader(载入程序)和performance 管理了所有的回放的细节。(见教程1:播放一个 MIDI 文件。)
MIDI 输入在被performance 路由到tool之前转化成performance 消息格式 (使用基于DMUS_PMSG的结构)。输出tool 在把数据在传送到synthesizer 前转化为标准的MIDI消息格式。
注意
不能保证MIDI消息将以它们在文件中的顺序被处理。DirectMusic 消息以时间戳顺序传递,两个有相同时间戳的MIDI消息可能会不按照预定的次序传递。应该小心不要让顺序发生的事件得到相同的时间戳,
MIDI 消息通常在一或两个数据
字节后有一个状态字节。系统独占MIDI消息的状态
字节是不定长的。状态
字节指出了消息的类型,有些时候,还有接收消息的channel。当文件中顺序有多个相同类型的事件时,状态
字节被省略,这称为 running status。数据
字节仍然是可以识别的,因为字节的高位总是清空的,而状态字节的高位总是被置位。
MIDI事件从文件中流出的时间是由一个位于每个消息前的
数字控制的,这个数字表示了最多可以等待多少个tick 一个 tick 的真正的时间依赖与文件头部的时间格式。
MIDI 消息分为主要的两类:
* MIDI Channel Messages (MIDI 通道消息)
* MIDI System Messages (MIDI
系统消息)
MIDI 通道消息
通道消息被
寻址到一个特定的、对应于乐曲中的一部分的MIDI通道。通道消息既可是一个mode消息,也可是一voice消息。
Mode消息决定了通道将如何处理随后的voice消息。例如,一个mode消息可以通知通道保持沉默,忽略所有的note-on 消息直到下一个通知。
大多数通道消息为voice消息:它们指挥通道开始和停止播放一个note或以某种方式修改这个note,或者通过为通道分配不同的MIDI patch数来改变 instrument。
Voice 消息有下面几类:
Voice 消息 用途
Note-on 播放一个note。
Note-off 停止播放 note。
Control change 用取自pedal,lever等的
数据修改音调(tone);页用来作各种诸如音量和bank选择的控制。
Program patch) change 通过指派以patch数来为channel选择一个 instrument。
Aftertouch 根据一个键(key)值的Aftertouch修改一个独立的note,或是通道上的所有的note。
Pitch bend change 让音调作一个以pitch作平滑的过度。
记住这些都只适用于标准的MIDI 消息,而非已转化成performance消息格式的MIDI 数据。例如,一对启动和停止播放note 的MIDI消息会被DirectMusic 结合在一个独立的DMUS_NOTE_PMSG 结构里。DirectMusic 消息同时也包含了许多额外的关于timing 和 routing 的信息。
MIDI notes
Note-on消息的数据字节描述了pitch 与 速率。大多数时候,pitch值为0表示subcontra C以下的C (用 MIDI 符号表示为C0), 12 表示subcontra C (或 C1), 60 是中(middle)C (或 C5), 等等。对 drum kits 来说(译者注:drum kits是什么?不懂!drum 意思是‘鼓’,这里大概是在说打击乐器), 数据字节表示了一个特殊的drum 声音, 例如,只要遵照General MIDI (GM) 打击乐器值映射,值60 表示一个高的 bongo 音。通道10 是为drum kits 保留的,所以synthesizer 知道在此通道上的note-on 消息将被与在其它通道上的不同对待。
关于DirectMusic 如何转化与形成MIDI note 的信息,见 Music Values 与 MIDI Notes。
Program changes
Program changes 和 patch 数在MIDI的回放以及DirectMusic中 都是一个重要的概念。一个 program change 为一个通道指派了特定的instrument (也称作program 或 timbre(音质)) ,所以发送到此通道上的note 能以适当的声音播放出来。Instrument 用 patch数来鉴别。如果载入的是GM instrument 集,一个指定 patch数为1 的program change 将始终使通道象类似与三角钢琴的声音播放它的note 。(当然,在喇叭中产生的声音依赖于这个 instrument 使如何被合成的。)
Bank selection
因为在一个program change中只用一个
字节来选择 patch 数,而且在MIDI 消息中的每个字节只有7位是有意义的,一个 program change 最多可以从128 个 instrument中选择。为提供更多的选择,MIDI 规范里允许最多使用16,384个instrument bank,每个都包含128 个instruments。
为了从不同的bank 中选出一个instrument , MIDI 序列器(sequencer)必须先发送一个称为bank select 的控制改变消息(control change message)。此消息的两字节分别叫作最大意义字节(most significant byte (MSB))和(最小意义字节least significant byte (LSB)), 它们一起确定了一个 bank。一旦选定了这个bank,随后的program change 就从此bank里选instrument 。
DirectMusic patch 数
在DirectMusic 中,instrument patch 数不同于7位的MIDI patch 数而是一个32位值,它把选择bank 时的 MSB、LSB以及为drum kit 而设的一个1 位标志于 MIDI patch 数均包括在一起。这个扩展的patch 数可由IDirectMusicCollection::EnumInstrument、IDirectMusicCollection::GetInstrument、 和 IDirectMusicInstrument::GetPatch 方法返回。对摸个instrument可以通过使用IDirectMusicInstrument::SetPatch方法来改变。
DirectMusic patch 值如下组织:
位 用途
0-7 MIDI patch 数(位 7 总是 0)
8-15 LSB (位 15 总是 0)
16-23 MSB (位 23 总是 0)
24-30 没使用
31 drum kit 的标志
系统消息对任一通道都不是独占的。共有三类,如下所示:
消息类型 用途
系统独占消息 设备指定的命令和数据。
系统实时消息 使基于时钟的MIDI设备同步。
不象别的MIDI消息,系统独占消息可以包含多个数据字节。在发送好数据之后,
音序器会发出一个称为EOX的系统通用消息,表示系统独占消息的结束。在DirectMusic中, DMUS_SYSEX_PMSG 结构包含了数据的长度和指向数据字节阵列的
指针。
Downloadable Sounds
一直以来,大多数电脑音乐以两种根本不同的方法中的一种来制作,这两种方法各有优缺点:
*波形格式从数字采样中复制,通常存放在 .wav 文件里,或者以标准的 CD 音轨存放。数字采样可以复制所有的声音,在所有的声卡上的输出也非常相似。然而,它们需要大量的
存储空间和资源。
*乐器声效常常是硬件合成的,通常来自于MIDI文件。MIDI 文件很紧凑而且需要很少的资源,但输出受限于General MIDI 集合和合成器中的可用的乐器的数量,而且在不同的系统上听到的效果可能完全不一样。
一个结合了数字采样的优点和MIDI的紧凑与灵活性的方法是
波表合成器,从数字采样中得到乐器音效的合成。这些采样由记录真实的乐器声得到并储存在硬件中。这些采样被循环和调整以产生有不同音调和音量的任意长度的声音。
波表W合成可以产生比调频算法合成真实得多得音质,但它仍受限于固定的乐器集。而且,一种乐器会因为不同的硬件厂商对其的实现不同,从而听起来因硬件而异。
DLS( downloadable sounds 不知如何译) 标准由MIDI Manufacturers Association(MIDI 生产商协会)制订。DLS 基本上是一种基于实时采样启动波表合成而不是把它固化在系统中的方法。描述乐器的数据被下载(download)到合成器中,然后这个乐器就完全能象别的MIDI乐器一样演奏。因为 DLS 数据可以被作为应用的一部分,所以开发者们就能确信他们的音轨在任何一个系统上都能保持一致,而且,能不受限于他们所选择的乐器。
DLS 乐器根据一个或多个数字采样创建,典型地代表了一个音调(pitch),这个音调即将被合成器所修改以生成别的音调。使用多次采样来使乐器能在大范围的音调里听起来都真实。当 DLS 乐器被下载后,每个采样都对应于一定范围的音调,叫做音区(region)。通常不会超过16个音区。
另外,采样还需给出发音信息(articulation),它定义了譬如爆发(attach)(一个音符可多快达到最高音量),衰减(decay)(从最高音量下来可以由多快),和别的使声音听起来更象发自于真实的乐器的特征。
Downloadable sounds 储存在乐器集( instrument collections)中,从这儿它们被下载到合成器中。
DLS 乐器被指派好patch 数并象别的MIDI乐器一样响应MIDI消息。然而,DLS 乐器不用属于通用MIDI集。事实上,它根本就不表示一个具体的乐器,一段语音或是一曲完整的乐曲,都可以变成DLS 乐器。
更多的关于 DLS 集合乐器如何被创建的信息,见DirectMusic Producer的文档。关于如何在应用中使用DLS的信息,见使用Downloadable Sounds。
Microsoft Software Synthesizer(Microsoft软件合成器)
Microsoft Software Synthesizer 由DirectMusic 提供且是缺省的端口。Synthesizer 根据一段MIDI消息流创建波形格式,使用了DSL采样合成的乐器音色。这些采样的缺省值从Roland GS 集中得到,这也是DirectMusic 安装的一部分。
注意
Roland GM/GS 集是不能被修改的。
在当前的DirectMusic发行版本中,合成器通过在一个想DirectSound
混音器发送其输出的DLL实现。
Microsoft软件合成器包含混响功能,默认情况下处于打开状态。Waves TrueVerb混响技术作为SimpleVerb实施授权给Microsoft。
微软的direct music 自带的microsoft synthesizer软件波表合成器,支持win7 64位系统,自带混响功能。虽然在win7下面已经不支持选择波表,但是估计微软默认也把这个软件波表带进win7 系统中。奇怪的是,早期的midi播放软件,甚至是win95和win31下面的播放软件,可以调用这个系统自带的软件波表合成器,而且效果很好。