MIDI操作案例
MS提供Midi*开头的函数在程序中操作Midi音乐。为此计算机可以依次调用MIDIOutOpen函数,midiOutShortMsg函数,最后调用midiOutClose函数来发出一个声音。
以下的代码都是midiOutShortMsg函数的代码,因为MIDIOutOpen和midiOutClose函数的代码都一样的,要使用下面的midiOutShortMsg的代码,需要在Load事件和QueryUnload实践中书写如下代码:
DimmidiHandAsLong'窗口级别的全局常数
PrivateSubForm_Load()
MIDIOutOpenmidiHand,MIDI_MAPPER,0,0,0'打开Midi媒体
EndSub
PrivateSubForm_QueryUnload(CancelAsInteger,UnloadModeAsInteger)
midiOutClosemidiHand'关闭Midi媒体
EndSub
并且注意要结束程序必须按窗口的关闭按钮(右上角的叉),不要按IDE上的方形按钮结束程序,否则QueryUnload事件是不会执行的。下次启动程序就会出错。
midiOutShortMsgmidiHand,随后的长度是一个6(高位优先的32位数字表示法)。格式,是指定文件的整体组织。
格式的只有三种值,指定三种格式:
0文件包含一条唯一的多通道音轨
1文件包含一个或更多同时的音轨
2文件包含一个或更多独立的音轨,相继进行播放
音轨数,是文件中音轨块的数量。
分区,是在文件的Δt之中1代表的是一秒的多少分之一。
格式0,多通道的音轨,是最容易转换的数据。应用格式1的MIDI文件可以很容易转换成这种格式。声音是最重要的东西,格式并不重要。这种转换是非常应该的,这可以化繁为简。
MIDI文件有可以表达的节奏和拍号的信息。对于0的文件格式,节奏,将分散的存储;对于格式1,节奏必须(在0.04版起)一起储存,作为第一条音轨。这个规定是合理的。
所有的MIDI文件,应指定节奏和拍号。如果他们不这样做,拍号假设为4/4,节奏和节拍120每分钟。在格式0中,这些元事件应该在开头。在格式1中,这些元事件应包含在第一个音轨中。在格式2中,每一独立的音轨,应至少包含一条拍号和节奏的信息。
不是每个程序,都必须支持每一个元事件。元事件最初的定义包括:
序列数
FF0002ssss
这一类事件,必须发生在音轨的开头,在任何非零时间后发生的事件或可传送的MIDI信息之前,用于指定序列的数目。序列数对应在这条音轨的序列数。在一个格式0或1MIDI文件,其中只包含一个序列,这个数字应包含在第一个音轨。
文字事件
FF01长度文字
任何数量描述任何事情的文字。在音轨开头放上这条音轨的相关的所有信息是很好的,这有助于日后查看。文本事件也可能发生在其他时间,被用来作为歌词。在此事件中文本应用可打印的ASCII字符进行书写。
元事件类型01到0F的是预留给各种类型的文本使用的,但使用的目的各不相同:
版权公告
FF02长度文本
载有版权声明,作为打印ASCII文本。文本中应包含字符(c),版权所有的时间,版权所有者。如果几段音乐是在同一个MIDI文件中,所有的版权声明应放在一起,把它放在文件的开头。这个事件应该是第一个事件,在时间0放在第一条音轨块。
序列/音轨的名称
FF03长度文本
乐器名称
FF04长度文本
说明该类型的乐器将用于在这一条音轨中使用。
歌词
FF05长度文本
写明歌词。一般来说,每个音节将是一行单独的歌词,应该写清时间
标记
FF06长度文本
通常在一个格式0的音轨,或在格式1的第一个音轨。
注释点
FF07长度文本
描述一些在这一点上发生在电影或视频屏幕或舞台的动作或事件
音轨终止
FF2F00
此事件必须的,以便确定的结束点。
设定速度,以毫秒(ms)为单位,是四分音符的时值
FF5103tttttt
这个事件可以精确的写清楚这条音轨的速度。用每拍所占的时间而不是单位时间内的拍数表示速度,使得依据一个基于时间的同步协议(例如SMPTE时间代码或MIDI时间代码)实现时间的绝对同步成为可能。这种准确性使四分钟左右的曲子在每分钟的120拍下结束时,时间误差在500微秒之内。
SMPTE时间同步
FF5405hrmnsefrff
这一事件,如果存在的话,将指定某一个特定事件开始的SMPTE时间。它应出现在音轨的开头,在任何非零时间后发生的事件或可传送的MIDI信息之前。
拍号标记
FF5804nnddccbb
因此,完整的6/8拍号应该表示为
FF580406032408
三十二分音符。
谱号信息
FF5902sfmf
sf指明乐曲曲调中升号、降号的数目。例如,A大调在五线谱上注了三个升号,那么sf=03。又如,F大调,五线谱上写有一个降号,那么sf=81。 也就是说,升号数目写成0x,降号数目写成8x
mf指出曲调是大调还是小调。大调mf=00,小调mf=01
对于序列器的元数据
FF7F长度数据
特殊要求,尤其是时序可能会使用此事件类型:第一个字节或字节的数据是一个制造商的ID。
作为一个例子,把一个MIDI文件摘录如下所示。
内容的MIDI流所代表的这个例子,细分在这里:
Δt(十进制)事件号(十六进制)其他数据(十进制)说明
0FF580404022408
0FF5103500000
0C05通道1,音色5
0C146通道2,音色46
0C270通道3,音色70
0924896通道3开始弹奏C2,用力
0926096通道3开始弹奏C3,用力
96916764通道2开始弹奏G3,用力
96907632通道1开始弹奏E4,钢琴
192824864通道3停止弹奏C2,标准
0826064通道3停止弹奏C3,标准
0816764通道2停止弹奏G3,标准
0807664通道1停止弹奏E4,标准
0FF2F00结束
整个格式0的MIDI文件的内容,首先,文件头块:
4D546864MThd
00000006块长度
0000 格式0
0001 一个音轨
0060 一个MIDI时间间隔等于96分之一秒
接着,音轨块,
4D54726BMTrk
0000003B音轨长度(59字节)
时间事件
00FF580404021808 拍号4/4
00FF510307A120 速度
00C005
00C12E
00C246
00923060
003C60
60914340
60904C20
8140823040
003C40
00814340
00804C40
00FF2F00终止
类似的,可以把这个文件写成1格式。
MIDI格式在网络传送中,通常采用7位数据传送方式,这样可以大大提高传输速度。
MIDI格式由于体积很小,非常便于传送;而且,由于它很有利于创作音乐,是很多作曲家在创作初期的首选。
MIDI格式由于其特殊的记录方式,受硬件影响较大。
MID格式文件很容易被人误解,很多人在电脑上直接播放MID后总会说'MID音质特别差'。这里再次要强调一遍,MID文件不是音频文件,它的作用只相当于一个文本文档,记录了音乐该如何进行。MIDI回放音色完全取决于声卡,之所以在windows系统上播放MID不能取得良好效果是因为系统自带的音色库比较简单。如果需要得到很不错的音色,则另需加装专业软音源插件,一块专业声卡也是必不可少的。
具体实例
4d546864//'MThd'
00000006//长度always6,后面有6个字节的数据
0001//0-单轨;1-多规,同步;2-多规,异步
0002//轨道数,即为'MTrk'的个数
00c0//基本时间格式,即一个四分音符的tick数,tick是MIDI中的最小时间单位
4d54726b//'MTrk',全局轨为附加信息(如标题版权速度和系统码(Sysx)等)
0000003d//长度
00ff03//音轨名称
05//长度
5469746c65//'Title'
00ff02//版权公告
0a//长度
436f6d706f736572203a//'Composer:'
00ff01//文字事件
09//长度
52656d61726b73203a//'Remarks:'
00ff51//设定速度xxxxxx,以微秒(us)为单位,是四分音符的时值
03//长度
07a120//四分音符为500,000us,即0.5s
00ff58//拍号标记
04//长度
04021808//nnddccbb拍号表示为四个数字。nn和dd代表分子和分母。分母指的是2的dd次方,例如,2代表4,3代表8。cc代表一个四分音符应该占多少个MIDI时间单位,bb代表一个四分音符的时值等价于多少个32分音符。因此,完整的6/8拍号应该表示为FF580406032408。这是,6/8拍号(8等于2的三次方,因此,这里是0603),四分音符是32个MIDI时间间隔(十六进制24即是32),四分音符等于8个三十二分音符。
00ff59//谱号信息
02//长度
0000//sfmf。sf指明乐曲曲调中升号、降号的数目。例如,A大调在五线谱上注了三个升号,那么sf=03。又如,F大调,五线谱上写有一个降号,那么sf=81。也就是说,升号数目写成0x,降号数目写成8x。mf指出曲调是大调还是小调。大调mf=00,小调mf=01。
00ff2f00//音轨终止
4d54726b//'MTrk',普通音轨
00000117//长度
00ff03//00:delta_time;ff03:元事件,音轨名称
06//长度
432048617270//'CHarp'
00b00000//00:delta_time;bn:设置n通道控制器;xx:控制器编号;xx:控制器值。此处为设置0通道0号控制器值为0。
00b02000//此处为设置0通道32号控制器值为0。
00c016//00:delta_time;cn:设置n通道音色;xx:音色值。此处为设置0通道音色值为22Accordion手风琴。
8440b06500//此处为设置0通道101号控制器值为0。
00b06400//此处为设置0通道100号控制器值为0。
00b00618//此处为设置0通道6号控制器值为0。
00b0077e//此处为设置0通道7号控制器(主音音量)值为126。
00e00040//00:delta_time;en:设置n通道音高;xxyy:各取低7bit组成14bit值。此处为设置0通道音高值为64。
00b00a40//此处为设置0通道7号控制器(主音音量)值为126。
00904340//00:delta_time;9n:打开n通道发音;xxyy:第一个数据是音符代号。有128个音,对MIDI设备,编号为0至127个(其中中央C音符代号是60)。第二个数据字节是速度,从0到127的一个值。这表明,用多少力量弹奏。一个速度为零的开始发声信息被认为,事实上的一个停止发声的信息。此处为以64力度发出67音符。
8110804340//8110:delta_time;8n:关闭n通道发音;xxyy:第一个数据是音符代号。有128个音,对MIDI设备,编号为0至127个(其中中央C音符代号是60)。第二个数据字节是速度,从0到127的一个值。这表明,用多少力量弹奏。一个速度为零的开始发声信息被认为,事实上的一个停止发声的信息。此处为以64力度关闭67音符。
00904340
30804340
00904540
8140804540
00904340
8140804340
00904840
8140804840
00904740
8300804740
00904340
8110804340
00904340
30804340
00904540
8140804540
00904340
8140804340
00904a40
8140804a40
00904840
8300804840
00904340
8110804340
00904340
30804340
00904f40
8140804f40
00904c40
8140804c40
00904840
8140804840
00904740
8140804740
00904540
8300804540
00904d40
8110804d40
00904d40
30804d40
00904c40
8140804c40
00904840
8140804840
00904a40
8140804a40
00904840
8300804840
01b07b00//00:delta_time;bn:设置n通道控制器;xx:控制器编号;xx:控制器值。此处为设置0通道123号控制器(关闭所有音符)值为0。
00b07800//00:delta_time;bn:设置n通道控制器;xx:控制器编号;xx:控制器值。此处为设置0通道120号控制器(关闭所有声音)值为0。
00ff2f00//音轨终止