python midi_Python | 读取 midi 文件
这个真的是费了好大好大好的的劲才弄出来。。。
格式
头区块 (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 文件相关推荐
- json字段顺序读取 python_如何利用Python批量读取视频文件的时间长度?
本期的主题是利用Python来实现对视频文件时间长度的读取. 在学习编程语言时,相比较于通过书本来学习知识,我更喜欢通过观看学习视频的方式来进行学习,通过主讲老师的讲解,我能很直观且快速的了解一些知识 ...
- python怎么读取txt文件内容然后保存到excel-Python实现读取txt文件并转换为excel的方法示例...
本文实例讲述了Python实现读取txt文件并转换为excel的方法.分享给大家供大家参考,具体如下: 这里的txt文件内容格式为: 892天平天国定都在?A开封B南京C北京(B) Python代码如 ...
- python导入txt文件并绘图-Python实现读取txt文件中的数据并绘制出图形操作示例
本文实例讲述了Python实现读取txt文件中的数据并绘制出图形操作.分享给大家供大家参考,具体如下: 下面的是某一文本文件中的数据. 6.1101,17.592 5.5277,9.1302 8.51 ...
- python读取整个txt文件-python怎么读取txt文件内容
读取文件: 步骤:打开 -- 读取 -- 关闭>>> f = open('/tmp/test.txt') >>> f.read() 'hello python! h ...
- python导入txt文件并绘图-Python实现读取txt文件并画三维图简单代码示例
记忆力差的孩子得勤做笔记! 刚接触python,最近又需要画一个三维图,然后就找了一大堆资料,看的人头昏脑胀的,今天终于解决了!好了,废话不多说,直接上代码! #由三个一维坐标画三维散点 #codin ...
- python读取txt文件代码-Python实现读取txt文件并画三维图简单代码示例
记忆力差的孩子得勤做笔记! 刚接触python,最近又需要画一个三维图,然后就找了一大堆资料,看的人头昏脑胀的,今天终于解决了!好了,废话不多说,直接上代码! #由三个一维坐标画三维散点 #codin ...
- c语言怎么解析midi文件,c – 无法读取midi文件? [扩展规格?]
我正在尝试用C语言读取midi文件而且我遇到了一个错误,这个错误似乎是标准midi规范中未定义的事件(从许多站点检索到包括此: http://www.sonicspot.com/guide/midif ...
- Python数据分析·读取CSV文件转为字典
Python数据分析·读取CSV文件转为字典 1.pandas 读取CSV 2.CSV转为字典 3.CSV转为数组 Python pandas包可以直接读取CSV文件,为了接下来的数据分析,考虑到转为 ...
- 怎么退出python命令行cd找到txt文档_《python怎么读取txt文件》
python怎么创建一个txt文件 python怎么创建txt文件的方法. 如下参考: 1.首用内置的空闲编辑器编辑(单击并选择copy),如下图所示. 2.您可以下载记事本和其他编辑软件,以支持多种 ...
最新文章
- squid一些其它配置
- python面向对象代码示例
- 试试博客园的markdown编辑器
- boost::log::string_literal用法的测试程序
- linux命令chown和chmod什么区别
- 探秘 Dubbo 的度量统计基础设施 - Dubbo Metrics
- 小明交友第五次2018.6.24
- QML如何与C++交互
- 应用Tableau、Vertica的可视化大数据分析框架
- js实现视频时间段拖拽编辑
- 10.31课程.this指向
- 桂林老兵php,中间件解析漏洞
- 蔡义江《红楼梦诗词曲赋评注》下
- [OpenAirInterface实战-5] :OAI支持的5G gNB功能集
- Android CoordinatorLayout之自定义Behavior
- python ansible
- Vue 2.0 升(cai)级(keng)之旅
- Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies 问题解决
- 我的世界 服务器文件ess,求助服务器ess插件报错怎么解
- sql注入预防 [ 光影人像 东海陈光剑 的博客 ]
热门文章
- Java设计模式学习以及底层源码分析
- S曲线C语言实现,利用robomodule+STM32F429+直流伺服电机进行简单验证
- windows下vscode + code runner + cmake + msbuild.exe搭建C++快速编译环境
- JAVA获取excel第一列数据
- 《中庸》开宗明义:天命之谓性,率性之谓道,修道之谓教。
- android 预览和拍照成像方向不一致,Android相机预览方向深入探究
- Algorithm negotiation fail解决
- Multiple keywords with name ‘Capture Page Screenshot‘ found. Give the full name of the keyword you w
- pdf to word android,PDF to Word Converter
- 离散数学(8)——函数