从 MIDI 轨道弹出消息
Posted
技术标签:
【中文标题】从 MIDI 轨道弹出消息【英文标题】:Popping Messages from MIDI Tracks 【发布时间】:2020-04-19 21:25:56 【问题描述】:我有类型 0 的 MIDI 文件,包含只有 269 个元消息的轨道,我想保留标题块和文件末尾的最后一个。
for i, msg in enumerate(mid.tracks[0]):
if i > 10 or i < len(mid.tracks[0])-1:
if msg.is_meta:
mid.tracks[0].pop(i)
上面的代码,没有这样做。事实上,它恰好删除了一半的消息(其中 135 条),它还删除了开头和结尾,我必须运行它几次才能让它接近 10 条元消息!
library 说:
pop([index]) → item -- 删除并返回索引处的项目(默认最后一个)。 如果列表为空或索引超出范围,则引发 IndexError。
我也尝试了另一种方法,但同样,每次只删除一半。所以我需要多次运行循环以使其接近我想要的大小:
while len(mid.tracks[0])>16:
for i, msg in enumerate(mid.tracks[0]):
if msg.is_meta and hasattr(msg, 'data'):
if len(msg.data) == 7:
mid.tracks[0].remove(msg)
for i, msg in enumerate(mid.tracks[0]):
if msg.is_meta:
print(i, msg)
请问我做错了什么?
【问题讨论】:
您真的不应该在对象的循环内修改对象。当您致电pop(i)
时,您会遇到麻烦。也许创建一个“删除”列表并单独删除它们。
好像是随机弹出的!我就是这么做的。并编辑了 OP。谢谢你的回答。
您能否也对此发表评论:***.com/questions/61305523/…。我真的很感激。
【参考方案1】:
这样的事情可能会更快。请注意,代码可能与您的数据不完全匹配。如果您发布 mid.tracks[0] 的值,我可以为您提供更好的结果。
t = mid.tracks[0] # shorthand to simplify code
keep = t[:10] + t[-1:] # get first ten and last one
# keep only the non-meta ones
result = [msg for msg in keep if not msg.is_meta]
注:根据评论修改。
【讨论】:
你的第二行:TypeError: can only concatenate list (not "MetaMessage") to list! 尝试t[-1:]
而不是t[-1]
。如果没有,请尝试[t[-1]]
。这完全取决于你的mid.tracks[0]
对象到底是什么。也许您可以发布对象的转储?以上是关于从 MIDI 轨道弹出消息的主要内容,如果未能解决你的问题,请参考以下文章
BLE MIDIMIDI 文件格式分析 ( MIDI 轨道分析 | MIDI 轨道头 | MIDI 轨道长度 | delta-time 间隔 )
BLE MIDIMIDI 文件格式分析 ( MIDI 轨道分析 | MIDI 轨道头 | MIDI 轨道长度 | delta-time 间隔 )
BLE MIDIMIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标识 | MIDI 文件头长度 | MIDI 文件格式 | MIDI 轨道个数 | 基本时间 )
BLE MIDIMIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标识 | MIDI 文件头长度 | MIDI 文件格式 | MIDI 轨道个数 | 基本时间 )(代码