midi file

4D 54 68 64 
00 00 00 06 
00 01 00 02 00 78 
4D 54 72 6B 
00 00 00 8E 
00 FF 58 04 04 02 18 08 00 FF
51 03 09 27 C0 00 FF 03 08 75 6E 74 69 74 6C 65
64 00 FF 02 1A 43 6F 70 79 72 69 67 68 74 20 3F
20 32 30 31 34 20 62 79 20 C1 F5 D3 EE BF B5 00
FF 01 06 C1 F5 D3 EE BF B5 00 FF 59 02 00 00 00
BF 07 FF 00 BE 07 FF 00 BD 07 FF 00 BC 07 FF 00
BB 07 FF 00 BA 07 FF 00 B9 07 FF 00 B8 07 FF 00
B7 07 FF 00 B6 07 FF 00 B5 07 FF 00 B4 07 FF 00
B3 07 FF 00 B2 07 FF 00 B1 07 FF 00 B0 07 FF AD
14 FF 2F 00 4D 54 72 6B 00 00 01 6A 00 FF 21 01
00 00 FF 03 04 74 65 73 74 00 C0 01 00 90 3C 64
78 80 3C 30 00 90 3C 64 78 80 3C 30 00 90 43 64
78 80 43 30 00 90 43 64 78 80 43 30 00 90 45 64
78 80 45 30 00 90 45 64 78 80 45 30 00 90 43 64
81 70 80 43 30 00 90 41 64 78 80 41 30 00 90 41
64 78 80 41 30 00 90 40 64 78 80 40 30 00 90 40
64 78 80 40 30 00 90 3E 64 78 80 3E 30 00 90 3E
64 78 80 3E 30 00 90 3C 64 81 70 80 3C 30 00 90
43 64 78 80 43 30 00 90 43 64 78 80 43 30 00 90
41 64 78 80 41 30 00 90 41 64 78 80 41 30 00 90
40 64 78 80 40 30 00 90 40 64 78 80 40 30 00 90
3E 64 81 70 80 3E 30 00 90 43 64 78 80 43 30 00
90 43 64 78 80 43 30 00 90 41 64 78 80 41 30 00
90 41 64 78 80 41 30 00 90 40 64 78 80 40 30 00
90 40 64 78 80 40 30 00 90 3E 64 81 70 80 3E 30
00 90 3C 64 78 80 3C 30 00 90 3C 64 78 80 3C 30
00 90 43 64 78 80 43 30 00 90 43 64 78 80 43 30
00 90 45 64 78 80 45 30 00 90 45 64 78 80 45 30
00 90 43 64 81 70 80 43 30 00 90 41 64 78 80 41
30 00 90 41 64 78 80 41 30 00 90 40 64 78 80 40
30 00 90 40 64 78 80 40 30 00 90 3E 64 78 80 3E
30 00 90 3E 64 78 80 3E 30 00 90 3C 64 81 70 80
3C 30 14 FF 2F 00                              

读取文件头

4D 54 68 64 //MThd

str.substr(position, length=4) //读取前四个字节(正好对应ascii码),结果为MThd

读取长度

00 00 00 06 //6
(str.charCodeAt(position) << 24)
+ (str.charCodeAt(position + 1) << 16)
+ (str.charCodeAt(position + 2) << 8)
+ str.charCodeAt(position + 3)

str.charCodeAt(position) //读取指定位置的unicode编码

读取header 数据区

根据上一步读取的长度length=6,读取header的数据部分

00 01 00 02 00 78 

00 01 多音轨
00 02 2个轨道(一个主轨道,一个发声轨道)
00 78 tick数(每个四份音符包含120个tick)

读取header 数据区内部

formatType 00 01 多音轨
trackCount 00 02 2个轨道(一个主轨道,一个发声轨道)
timeDivision 00 78 tick数

readInt16()//每次读取两个字节,分三次读完
(str.charCodeAt(position) << 8)
+ str.charCodeAt(position + 1)

track

event

deltaTime

动态字节
一个字节有8位,最高位做标志位,还有7位0~2^7-1(127),
1)如果表示的数在这个范围内,则标志位(第8位,最高位)为0,比如01111111为127.
2)如果表示的数字超过这个范围,先记录前7位为一个字节,超过7位的数值交给前面的字节,前字节的标志位必须为1(表明该字节是进位的),如果前字节还是超过了127,则继续(交给前前字节),比如11111111一共8位,先记录前7位为一个字节0111111,第8位的1放在前一个字节里,既10000001,所以就表示为10000001 01111111
https://www.jianshu.com/p/31d02765e1ec

	function readVarInt() {
		var result = 0;
		while (true) {
			var b = readInt8();//先读一个字节
			if (b & 0x80) {//比较最高位是否为1
				result += (b & 0x7f);//0x7f 二进制01111111
				result <<= 7;
			} else {
				return result + b;
			}
		}
	}

event

meta event :0xff

meta event的类型是一个字节,它的跟随的数据的长度是可变的varint

下一级分类 代码 描述
sequenceNumber(轨道音序) 0x00
text(文本) 0x01
copyrightNotice(版权) 0x02
trackName(轨道名称) 0x03
instrumentName(乐器名称) 0x04
lyrics(歌词) 0x05
marker(标记) 0x06
cuePoint (开始点) 0x07
midiChannelPrefix() 0x20
音轨开始标识 0x21
endOfTrack(音轨结束标志) 0x2f
setTempo(速度) 0x51 四分音符的微妙数,3个字节
smpteOffset 0x54
timeSignature 0x58 4字节(numerator;分子,denominator:分母,metronome:节拍时钟,thirtyseconds:每个四分音符有多少个三十二分音符)
keySignature(调号) 0x59 2字节(key:大小调,scale:升降)
sequencerSpecific(音序特定信息) 0x7f

system event :0xf0 0xf7

分类 代码 描述
sysEx 0xf0
dividedSysEx 0xf7

channel event

除了meta event 和 system event 剩余的都是channel event
Channel是利用状态字节的低 4 位来表示

分类 代码 描述
noteOff(松开音符) 0x80~0x8F
noteOn(按下音符) 0x90~0x9F 需要先判断velocity,等于0是off,不等于0是on
noteAftertouch(触后音符) 0xA0~0xAF
controller(控制器) 0xB0~0xBF
programChange(改变) 0xC0~0xCF
channelAftertouch(触后通道) 0xD0~0xDF
pitchBend(滑音) 0xE0~0xEF
发布了1794 篇原创文章 · 获赞 582 · 访问量 154万+

猜你喜欢

转载自blog.csdn.net/claroja/article/details/104178799