这个真的是费了好大好大好的的劲才弄出来。。。

格式

头区块 (Head Chunk)

MThd + +

头区块字符长度 一般为 6

轨道区块 (Track Chunk)

Track Chunk = MTrk + +

区块字符长度 是 4 byte 的无符号长整型

= + ( | | )

时间戳 为用 VLQ 表示的相对于上一个数据点的时间变化量 (delta time)

= \xFF + + +

类型 为 1 byte 的字节,对照表在下文

数据长度 为用 VLQ 表示的数据块的字符数

例子

比如下面这段 bwv806a.mid 的前 200 字节:

MThd\x00\x00\x00\x06\x00\x01\x00\x04\x00\xf0MTrk\x00\x00\x00G\x00\xff\x03\x08untitled\x00\xffT\x05`\x00\x03\x00\x00\x00\xffX\x04\x0c\x03\x0c\x08\x00\xffY\x02\x00\x00\x00\xffQ\x03\x06EO\x83\x97h\xffQ\x03\x07\xa1 \x82h\xffQ\x03\t\xa3\x1b\x82h\xffQ\x03\x0c\xe5\x0e\x00\xff/\x00MTrk\x00\x00\n\xd9\x00\xff!\x01\x00\x00\xff\x03\x1bEnglish Suite 1, 1. Prelude\x00\xc0\x00\x00\xb0\x07d\x00\n@\x90p\x90Qk\x81pLkxIk\x82hEk`Q\x00\x18PkHL\x00\x00E\x00\x00I\x00\x18P\x00\x18Nk`N\x00\x18Lk`L\x00\x18Nk`N\x00\x18

翻译后如下:

MThd

\x00\x00\x00\x06

\x00\x01 \x00\x04 \x00\xf0

0, 0, Header, 1, 4, 240

MTrk

\x00\x00\x00 G # length of track

1, 0, Start_track

\x00 \xff \x03 \x08 untitled

1, 0, Title_t, "untitled" # Time0, METAEVENT, Type3, len8, data

\x00 \xff T \x05 `\x00\x03\x00\x00

1, 0, SMPTE_offset, 96, 0, 3, 0, 0

\x00 \xff X \x04 \x0c\x03\x0c\x08

1, 0, Time_signature, 12, 3, 12, 8

\x00 \xff Y \x02 \x00\x00

1, 0, Key_signature, 0, "major"

\x00 \xff Q \x03 \x06EO

1, 0, Tempo, 410959

\x83\x97 h \xff Q \x03 \x07\xa1 # 注意这里结尾\xa1后还有一个空白字符 ' '

1, 52200, Tempo, 500000

\x82 h \xff Q \x03 \ t \xa3

1, 52560, Tempo, 631579

\x1b\x82 h \xff Q \x03 \x0c\xe5\x0e

1, 52920, Tempo, 845070

\x00 \xff / \x00

1, 52920, End_track

MTrk

\x00\x00 \n \xd9

2, 0, Start_track

\x00 \xff ! \x01 \x00

2, 0, MIDI_port, 0

\x00 \xff \x03 \x1b English Suite 1, 1. Prelude

2, 0, Title_t, "English Suite 1, 1. Prelude"

\x00 \xc0 \x00

2, 0, Program_c, 0, 0

\x00 \xb0 \x07 d

2, 0, Control_c, 0, 7, 100

\x00 \n @

2, 0, Control_c, 0, 10, 64

\x90 p \x90 Q k

2, 2160, Note_on_c, 0, 81, 107

\x81 p LkxIk

2, 2400, Note_on_c, 0, 76, 107

\x82 h Ek

2, 2520, Note_on_c, 0, 73, 107

.......

程序

from struct import unpack

import time

def read_vlq(f):

result = ''

buffer = unpack('B', f.read(1))[0]

length = 1

while buffer > 127:

print(buffer)

result += '{0:{fill}{n}b}'.format(buffer-128, fill='0', n=7)

buffer = unpack('B', f.read(1))[0]

length += 1

result += '{0:{fill}{n}b}'.format(buffer, fill='0', n=7)

return int(result, 2), length

def parse_event(evt, param):

if 128 <= evt <= 143:

print('Note Off event.')

elif 144 <= evt <= 159:

print('Note On event.', unpack('>BB', param))

elif 176 <= evt <= 191:

print('Control Change.')

elif 192 <= evt <= 207:

print('Program Change.')

with open('bwv806a.mid', 'rb') as f:

print(f.read(200))

# HEADER

if f.read(4) != b'MThd':

raise Exception('not a midi file!')

print(f.read(4))

header_info = f.read(6)

print(unpack('>hhh', header_info))

''' ================================== '''

while True:

track_head = f.read(4)

if track_head != b'MTrk':

if track_head != b'':

print(f.read(20))

raise Exception('not a midi file!')

else:

break

# length of track

len_of_track = unpack('>L', f.read(4))[0]

# print('len_of_track ', len_of_track)

counter = 0

t = 0

last_event = None

while True:

delta_t, len_ = read_vlq(f)

counter += len_

t += delta_t

# print('T ', t, end='')

event_code = f.read(1)

event_type = unpack('>B', event_code)[0]

counter += 1

# print(' event_type ', event_type, end='')

if event_type == 255:

meta_type = f.read(1)

counter += 1

# print(' - meta_type ', meta_type, end='')

data_len, len_= read_vlq(f)

counter += len_

data = f.read(data_len)

counter += data_len

# print(' - ', data)

elif event_type <= 127:

parse_event(last_event, event_code+f.read(1))

counter += 1

else:

if 128 <= event_type <= 143:

# print(' Note Off event.', end='')

parse_event(event_type, f.read(2))

counter += 2

elif 144 <= event_type <= 159:

# print(' Note On event.', end='')

parse_event(event_type, f.read(2))

counter += 2

elif 176 <= event_type <= 191:

# print(' Control Change.', end='')

parse_event(event_type, f.read(2))

counter += 2

elif 192 <= event_type <= 207:

# print(' Program Change.', end='')

parse_event(event_type, f.read(1))

counter += 1

last_event = event_type

# print(counter)

if counter == len_of_track:

break

参考资料:

python midi_Python | 读取 midi 文件相关推荐

  1. json字段顺序读取 python_如何利用Python批量读取视频文件的时间长度?

    本期的主题是利用Python来实现对视频文件时间长度的读取. 在学习编程语言时,相比较于通过书本来学习知识,我更喜欢通过观看学习视频的方式来进行学习,通过主讲老师的讲解,我能很直观且快速的了解一些知识 ...

  2. python怎么读取txt文件内容然后保存到excel-Python实现读取txt文件并转换为excel的方法示例...

    本文实例讲述了Python实现读取txt文件并转换为excel的方法.分享给大家供大家参考,具体如下: 这里的txt文件内容格式为: 892天平天国定都在?A开封B南京C北京(B) Python代码如 ...

  3. python导入txt文件并绘图-Python实现读取txt文件中的数据并绘制出图形操作示例

    本文实例讲述了Python实现读取txt文件中的数据并绘制出图形操作.分享给大家供大家参考,具体如下: 下面的是某一文本文件中的数据. 6.1101,17.592 5.5277,9.1302 8.51 ...

  4. python读取整个txt文件-python怎么读取txt文件内容

    读取文件: 步骤:打开 -- 读取 -- 关闭>>> f = open('/tmp/test.txt') >>> f.read() 'hello python! h ...

  5. python导入txt文件并绘图-Python实现读取txt文件并画三维图简单代码示例

    记忆力差的孩子得勤做笔记! 刚接触python,最近又需要画一个三维图,然后就找了一大堆资料,看的人头昏脑胀的,今天终于解决了!好了,废话不多说,直接上代码! #由三个一维坐标画三维散点 #codin ...

  6. python读取txt文件代码-Python实现读取txt文件并画三维图简单代码示例

    记忆力差的孩子得勤做笔记! 刚接触python,最近又需要画一个三维图,然后就找了一大堆资料,看的人头昏脑胀的,今天终于解决了!好了,废话不多说,直接上代码! #由三个一维坐标画三维散点 #codin ...

  7. c语言怎么解析midi文件,c – 无法读取midi文件? [扩展规格?]

    我正在尝试用C语言读取midi文件而且我遇到了一个错误,这个错误似乎是标准midi规范中未定义的事件(从许多站点检索到包括此: http://www.sonicspot.com/guide/midif ...

  8. Python数据分析·读取CSV文件转为字典

    Python数据分析·读取CSV文件转为字典 1.pandas 读取CSV 2.CSV转为字典 3.CSV转为数组 Python pandas包可以直接读取CSV文件,为了接下来的数据分析,考虑到转为 ...

  9. 怎么退出python命令行cd找到txt文档_《python怎么读取txt文件》

    python怎么创建一个txt文件 python怎么创建txt文件的方法. 如下参考: 1.首用内置的空闲编辑器编辑(单击并选择copy),如下图所示. 2.您可以下载记事本和其他编辑软件,以支持多种 ...

最新文章

  1. squid一些其它配置
  2. python面向对象代码示例
  3. 试试博客园的markdown编辑器
  4. boost::log::string_literal用法的测试程序
  5. linux命令chown和chmod什么区别
  6. 探秘 Dubbo 的度量统计基础设施 - Dubbo Metrics
  7. 小明交友第五次2018.6.24
  8. QML如何与C++交互
  9. 应用Tableau、Vertica的可视化大数据分析框架
  10. js实现视频时间段拖拽编辑
  11. 10.31课程.this指向
  12. 桂林老兵php,中间件解析漏洞
  13. 蔡义江《红楼梦诗词曲赋评注》下
  14. [OpenAirInterface实战-5] :OAI支持的5G gNB功能集
  15. Android CoordinatorLayout之自定义Behavior
  16. python ansible
  17. Vue 2.0 升(cai)级(keng)之旅
  18. Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies 问题解决
  19. 我的世界 服务器文件ess,求助服务器ess插件报错怎么解
  20. sql注入预防 [ 光影人像 东海陈光剑 的博客 ]

热门文章

  1. Java设计模式学习以及底层源码分析
  2. S曲线C语言实现,利用robomodule+STM32F429+直流伺服电机进行简单验证
  3. windows下vscode + code runner + cmake + msbuild.exe搭建C++快速编译环境
  4. JAVA获取excel第一列数据
  5. 《中庸》开宗明义:天命之谓性,率性之谓道,修道之谓教。
  6. android 预览和拍照成像方向不一致,Android相机预览方向深入探究
  7. Algorithm negotiation fail解决
  8. Multiple keywords with name ‘Capture Page Screenshot‘ found. Give the full name of the keyword you w
  9. pdf to word android,PDF to Word Converter
  10. 离散数学(8)——函数