midi解码实例.docx
《midi解码实例.docx》由会员分享,可在线阅读,更多相关《midi解码实例.docx(20页珍藏版)》请在冰豆网上搜索。
midi解码实例
MIDI解码实例(myE-MAIL148398720qq.)
/*****headerchunk********/
0x4D,0x54,0x68,0x64,
//MTHD
0x00,0x00,0x00,0x06,
//theactualheaderinformationwillalwaysbe6bytes.
0x00,0x00,
//thefileformat.thereare3formats:
0-single-track
1-multipletracks,synchronous
2-multipletracks,asynchronous
0x00,0x01,
//thenumberoftracksinthemidifile.
0x00,0x78,
//thenumberofdelta-timeticksperquarternote.(delta-timeconsistsofticks)
1.adeltatimeisthenumberofticks,anditsMSBis0.WhenMSBis1,itisanotherformat..
2.thenumberofticksperquarternote
3.theentiredelta-timeshouldbeatmost4byteslong.anditsMSBis0.WhenMSBis1,itisanotherformat.
/*******trackchunks*********/
0x4D,0x54,0x72,0x6B,
//MTRK
0x00,0x00,0x00,0x57,
//thelengthofthetrack(notincludingthetrackheader)inbytes.
0x00,0xFF,0x03,
//trackname
0x08,
//lengthofname
0x75,0x6E,0x74,0x69,0x74,0x6C,0x65,0x64,
0x00,0xFF,0x01,
//texteventname
0x02,
//lengthofname
0x51,0x51,
0x00,0xFF,0x58,0x04,0x04,0x02,0x18,0x08,
//timesignature拍子符号
0x00,0xFF,0x59,0x02,0x00,0x00,
//keysignature音调符号
0x00,0xFF,0x51,0x03,0x07,0xA1,0x20,
//settempo(microseconds/quarternote)
0x00,0xC0,0x50,
0x00,0xB0,0x07,0x78,
0x00,0x90,0x5E,0x78,
0x0F,0x5E,0x00,//stop0x90isomittedbecauseofthesameformat.
0x0F,0x5E,0x78,//play
0x0F,0x5E,0x00,//stop.Here,0x0F,0x90,0x5E,0x00doesthesameworkas0x0F,0x80,0x5E,0x78.
0x0F,0x5E,0x78,//play
0x0F,0x5E,0x00,
0x0F,0x5E,0x78,
0x0F,0x5E,0x00,
0x0F,0x5E,0x78,
0x0F,0x5E,0x00,
0x0F,0x5E,0x78,
0x0F,0x5E,0x00,
0x00,0xFF,0x2F,0x00
//thetrack(consistofmidievents).
1.amidieventisprecededbyadelta-time.
2.themidieventwillconsistofadelta-timeandtheparametersthatwouldgotothecommandifitwereincluded.
Time=delta-time*tempo/ticks
Time:
thecostofthetimeperquarternote.
delta-time:
Thenumberofticksperquarternotewillbeplayed,justlike0x0F.
tempo:
microsecondsperquarternote,justlike0x07,0xA1,0x20.
ticks:
thenumberofdelta-timeticksperquarternote,justlike0x00,0x78.
Attention:
delta-timeisavariable-lengthencodedvalue.thisformat,whileconfusing,allowslargenumberstouseasmanybytesastheyneed,withoutrequiringsmallnumberstowastebytesbyfillingwithzeros.thenumberisconvertedinto7-bitbytes,andthemost-significantbitofeachbyteis1exceptforthelastbyteofthenumber,whichhasamsbof0.thisallowsthenumbertobereadonebyteatatime,andwhenyouseeamsbof0,youknowthatitwasthelast(leastsignificant)byteofthenumber.
Addition:
baike.baidu./view/7969.htm
MIDI文件格式
MIDI文件结构
Chunks
MIDI文件由chunks组成:
每个chunk的组成:
类型
长度
数据
4字节
4字节
(前面规定的)长度
∙A4-字节chunk类型(ASCII)
∙A4-byte长度(32位,msbfirst)
∙(前面规定的)长度数据
有两种类型的chunks:
HeaderChunks
有一个chunk标志“MThd”
TrackChunks
有一个chunk标志“MTrk”
一个MIDI文件由一个headerchunk和紧接的一个或多个trackchunks组成。
在chunks结构中,自长度区以后是严格规定好的。
它可能容纳的chunks除了“MThd”或“MTrk”其它的将被忽略。
MIDI说明书要求软件能够处理意想不到的chunk,并忽略掉整个chunk。
<---Chunk--->
类型
长度
数据
MIDI
文件
:
MThd
6
<格式>
MTrk
<长度>
...
:
MTrk
<长度>
...
数值表示法
在MIDI文件中,除了基本的MIDI数据,还有一个变化的数据(类型)。
如:
delta-times和meta-events。
这里有一些关于这样的数的一些资料,它们有通常有下面1~2种格式:
∙二进制数
∙可变长度数
二进制数
二进制数的存贮:
∙每个字节8位
∙MSBfirst(最左方的字节权(或数位)大)
(除非其它的描述)
可变长度数
这个可变长度数是为了方便表示任意大的整数,而不必创建固定宽度的整数。
一个可变长度数被表示为连续的7位数据。
从最高位到最低位,最后一个字节bit7等于0,前面的字节bit7等于1。
例:
数
可变长度数
十进制
十六进制
二进制
二进制
十六进制
-
abcd
aaaabbbbccccdddd
100000aa1aabbbbc0cccdddd
-
0
:
127
00
:
7F
00000000
:
01111111
00000000
:
01111111
00
:
7F
128
:
16383
80
:
3FFF
0000000010000000
:
0011111111111111
1000000100000000
:
1111111101111111
8100
:
FF7F
1000
03E8
1111101000
1000011101101000
8768
100000
0F4240
11110100001001000000
101111011000010001000000
BD8440
如此,你可以从上面的例子发现:
小的数(0~127)可以用一个字节表示。
而(比较)大的数也可以表示出来。
在MIDI文件中,最大的数是0FFF,FFFF。
这个规定了可变长度数允许利用32位整数。
HeaderChunks
Headerchunk数据部分包括3个16位(数据)区。
这个区域描述:
(MIDI文件)格式、track的数量和MIDI的时间设置。
Headerchunk的长度是6个字节。
无论如何软件必须遵循这个原则。
即使它大于预期的,任何意料外的数据被忽略。
HeaderChunk
Chunk类型
长度
数据
4字节
(ASCII)
4字节
(32位二进制数)
<--长度(=6字节)-->
16位
16位
16位
MThd
<长度>
<格式>
<长度>
Chunk数据部分的长度。
这是一个32位二进制数,MSBfirst.
这在MIDI 1.0文件说明书中规定为6。
不过,考虑到将来的扩充,(希望)任何MIDI文件的作者能够应付大的Headerchunks。
<格式>
MIDI文件的格式。
这是一个16位二进制数,MSBfirst。
有效的格式是:
0、1和2。
MIDI文件中trackchunk的数量。
这是一个16位二进制数,MSBfirst。
这个定义在MIDI文件中(一个)单位的delta-time数。
这是一个16位二进制数,MSBfirst。
有下列两者之一的的格式,依赖于最高位值。
位:
15
14...8
7...0
0
1/4音符tick数
1
-帧/秒
ticks/帧
bit15=0:
bits0-14
每个1/4音符的delta-time数。
bit15=1:
bits0-7
每个 SMTPE帧的delta-time数。
bits8-14
负数,表示每秒中SMTPE帧的数量。
有效数应符合MTCQuarterFrame消息。
-24=24帧/秒
-25=25帧/秒
-29=30帧/秒,dropframe
-30=30帧/秒,non-dropframe
MIDIFileFormats
MIDI文件有3种变化:
∙格式0
…容纳单一的Track。
∙格式1
…容纳一个和多个同步的Track(所有的Track同时播放)。
∙格式2
…容纳一个和多个独立的Track(所有的Track独立播放)。
MIDI文件格式0
格式0MIDI文件包括一个Header-Chunk和一个Track-Chunk。
这个Track-Chunk包括所有的音符和节拍消息。
MIDI文件格式1
格式1MIDI文件包括一个Header-Chunk和多个Track-Chunk,所有的Track同时播放。
格式1中第一个Track是专用的。
它看成“TempoMap”。
它包括所有的meta-event:
拍子记号、拍子、音序/Track名称、音序号、标记、SMTPE偏移量。
在格式1中(这些)将放入在第一个track中。
MIDI文件格式2
格式2MIDI文件包括一个Header-Chunk和多个Track-Chunk,每个Track表现出独立的次序。
TrackChunks
Trackchunk的数据部分由一对和多对组成。
是必须的,0是有效的delta-time。
TrackChunk
类型
长度
数据
4字节
(ASCII)
4字节
(32位二进制数)
<--长度-->
(二进制数)
MTrk
<长度>
...
相对于前一个事件的“tick”,是一个可变长度数。
下列之一:
∙
∙
∙
事件
注意:
在和之间,没有明确的分隔符。
这个是因为delta-times和event有一个长度定义。
∙Delta-time定义最后一个字节的最高位等于0。
∙MIDIChannel消息有一个长度定义。
∙Sysex-events和meta-events有一个清楚的长度区。
MIDI事件
MIDIChannel消息包含:
∙ChannelVoicemessages
∙ChannelModemessages
Runningstatus通常应用于MIDI文件中的同一状态的表示。
Runningstatus也可以被取消。
Sysex事件
(系统高级消息的详细描述)是令人满意的,相对于MIDIchannel消息。
可以被使用。
Sysex-events流行两种风格:
SysexEvents
F0<长度>
F0SysexEvent
这个导致F0(消息的开头)被发送。
接着是。
<长度>
一个可变长度数,表示的长度
F0
作为MIDI消息发送。
F7<长度>
F7SysexEvent(or'escape')
这个导致被发送,没有其它的附加数。
<长度>
一个可变长度数,表示 的长度
作为MIDI消息发送。
在上面的案例中,消息的结束F7,没有自动的发送。
它必须明确的列入or.中。
大多数系统高级消息非常简单,且作为一个单一的包被发送。
开始于F0,结束于F7。
这个是非常容易的应用于的F0形式。
可是,一些系统高级消息习惯于实时控制设备。
怎样合成一个存在适当的延时的由一连串的‘零件’组成的系统高级消息。
因为,能够深入到事件中中断一个消息,就有一定的延时。
这个是可以应用的F7形式。
实际上,在MIDI流中F7SysexEvent习惯于包含any_data。
例如MIDI系统实时消息(尽管它并不令人满意的)。
例1:
一般的消息:
F07E09030101F7
(SampleDumpRequest-Device9,samplenumber257)
可以:
F0067E09030101F7
或者交替:
F707F07E09030101F7
例2:
MIDI系统实时消息“停止”用F701FC,当“继续”用F701FB。
假设:
你想停止一个外部设备——鼓,发送一个“停止”,接着48个delta-time单元后“继续”。
完整的delta-tem事件序列象下面这样:
00F701FC30F701FB
Meta事件
MetaEvents是用来表示象track名称、歌词、提示点等,它并不作为MIDI消息被发送,但是它仍然是MIDI文件的(有用的)组成部分。
MetaEvents的基本形式:
FF<类型><长度><数据>
<类型>
一个字节描述meta-event的类型。
可能的围是00-7F。
并不是所有的值都在这个围,但是程序能够应付意想不到的值,并诊断这个长度和忽略预期外的数据部分。
<长度>
紧跟的数据的长度。
这是一个可变长度(数)。
0是一个有效<长度>
<数据>
0或更多的字节数据。
MetaEvents
FF0002ssss
音序号
这是一个可选的事件,它只能产生在第一个track,并且在非零时刻之前。
格式2文件中,这个用来识别每个track,如果忽略,这个序列号从而用track出现的次序表示。
.
格式1文件中,这个事件只能产生在第一个track。
ssss
SequenceNumber,16bitbinary
FF01<长度><数据>
文本事件
这个事件是用来注释track的文本。
独立的8位数据(其它的ASCII文本)也是允许的。
<长度>
<文本>的长度(可变长度数)
<文本>
<长度>个字节的 ASCII文本或8位二进制数
FF02<长度><数据>
版本通告
这个事件是用ASCII文本表示的通告。
这个是制定的形式“(C)1850J.Strauss”
这个事件用于第一个track,第一个事件。
FF03<长度><数据>
音序/Track名称
音序或track的名称。
FF04<长度><数据>
乐器名称
描述这个track使用的乐器。
这个用来详细的记述(这个)MIDIchannel在(这个)track里使用的乐器。
FF05<长度><数据>
歌词
歌曲的歌词。
通常每个音节都有自己的歌词,在这个时候歌词将被唱起来。
FF06<长度><数据>
标记
通常用于格式0或格式1的第一个track。
标记有意义的点(如:
“诗篇1”)
FF07<长度><数据>
暗示
用来表示舞台上发生的事情。
如:
“幕布升起”、“退出,台左”等。
FF2001cc
MIDIChannel前缀
关联紧跟的meta-events 和sysex-events的MIDIchannel。
直到下一个(必须包含MIDIchannel信息)
cc
MIDIchannel1-16
围:
00-0F
FF2F00
Track结束
这个事件是必须的。
它用来扫除定义的长度。
它的本质信息是这个track是循环还是连接另一个track。
FF5103tttttt
拍子
这个设定1/4音符的速度,用微妙表示。
这个意味着改变一个delta-time的单位长度。
(注意1)
如果没有指出,缺省的速度为120拍/分。
这个相当于tttttt=500,000。
tttttt
新的拍子,表示1/4音符
24位二进制数
FF5405hhmmssfrff
SMTPE偏移量
可选择的的事件,描述track开始时的SMTPE时间。
这个事件必须发生在非零delta-time之前,且在第一个事件之前。
在格式1中,这个事件必须在第一个track中(thetempomap)。
hhmmssfr
小时/分/秒/帧用 SMTPE格式。
这个必须与消息 MIDITimeCodeQuarterFrame一致(细节,时间编码必须介绍 hh)
ff
Fractionalframe,inhundreth'sofaframe
FF5804nnddccbb
拍子记号
拍子记号的形式:
nn/2^dd
如:
6/8用nn=6,dd=3表示。
这个参数cc是表示每个MIDI时钟的节拍器的tick数目。
通常24个MIDI时钟为一个1/4音符。
可是一些软件允许用户自己设置这个值。
参数bb定义:
24MIDI时钟(这个“一般”(表示)1/4音符)中1/32音符的数目。
nn
拍子记号,分子
dd
拍子记号,分母表示为2的(dd次)冥。
例:
一个分母4用dd=2表示。
cc
每个MIDI时钟节拍器的tick数目。
bb
24个MIDI时钟中1/32音符的数目(8是标准的)。
FF5902sfmi
音调符号
音调符号,表示升调或降调值,大调或小调的标志。
0表示C调,负数表示“降调”,正数表示“升调”。
sf
升调或降调值
-7=7升调
0= C调
+7=7降调
mi
0=大调
1=小调
FF7F
音序器描述 Meta-event
这个在MIDI文件中等同于系统高级事件。
在