确定 MIDI 文件的时间划分

2024-03-04

我正在用Python编写一个脚本来解析MIDI文件(是的,我知道Python存在MIDI解析库,但对于我的用例来说,如果我从头开始制作它是最简单的)。

我遇到的问题之一是时间划分。标头的最后两个字节指定时间划分,但我无法确定文件的时间划分是否以每节拍的滴答数或每秒的帧数表示。经过一番阅读后,似乎顶部字节的顶部位指示了时间划分中的哪一个。我感到困惑的是,一个字节的顶部位是字节的第一位还是最后一位一个字节的位,以及如何完整读取 MIDI 时分。

编辑:例如,我的 MIDI 文件的标头如下:

4d54 6864 0000 0006 0000 0001 0078

0078 are the two bytes that denote the time sig, but I am confused as how to interpret it.

Edit 2:

def openmidi(file):
    tmbr = []
    f = open(file, "rb")#opening the midi in binary mode
    loopfile = True
    while loopfile == True:
        cb = f.read(1)
        if cb != b'':#checking if there are still bytes left to read
            tmbr.append(cb)
        else:
            loopfile = False
    return tmbr

def byteread(num):#will read and return the specified number of bytes
    global bytecounter
    bytehold = b''
    for i in range(0, num):#reads specified number of bytes
        bytehold+=midibytearray[i+bytecounter]#number of increment plus the read position
    bytecounter+=num#after reading is done read position is incremented by the number of bytes read.
    return bytehold#after looping is done the specified bytes are returned.

def timetype(deltatimebytes):#used to determine if the time division is in ticks per beat or frames per second.
    if str(deltatimebytes).replace("b'","").replace("'","")[0:2] == "00":
        return True#if true the time division is in ticks per beat.
    else:
        return False#the time division is in frames per second.


global bytecounter
bytecounter = 0 #keeps track of what position in the file is being read.

midibytearray = openmidi("C:\\Users\\gabep\\Desktop\\Electrorchestrion\\Midis\\BONEY M.Rasputin K.mid") #array that the bytes will be stored in.



header = byteread(4)
chunklength = byteread(4)
formattype = byteread(2)
numofmtrkchunks = byteread(2)
deltatime = byteread(2)#if no tempo is assigned, 120bpm is assumed.
print(deltatime)

print("Header: "+str(header.decode("utf-8")))
print("MThd chunk length: "+str(int(chunklength.hex(), 16)))
print("Midi Format Type: "+str(int(formattype.hex(), 16)))
print("Number of MTrk chunks (number of tracks): "+str(int(numofmtrkchunks.hex(), 16)))



print("Delta time: "+str(int(deltatime.hex(), 16)))
if timetype(deltatime.hex()) == True:
    print("Time signature is in ticks per beat")
else:
    print("Time signature is in frames per second")

也许你不知道官方的 MIDI 规范是可用的,你可以下载文档 https://www.midi.org/specifications/item/the-midi-1-0-specification免费。 (您需要先注册为网站用户)。它包括详细的SMF 格式。

这是标题块的描述。


文件开头的标头块指定了有关文件中数据的一些基本信息。这是完整块的语法:

<Header Chunk> = <chunk type> <length> <format> <ntrks> <division>

如上所述,<chunk type>是四个 ASCII 字符“MThd”;<length>是数字 6 的 32 位表示(高字节在前)。 数据部分包含三个 16 位字,首先存储最高有效字节。 第一个词,<format>,指定文件的整体组织。只有三个值<format>指定:

0=文件包含单个多通道轨道

1=该文件包含一个或多个同步轨道(或 MIDI 输出) 顺序

2=该文件包含一个或多个顺序独立的单轨模式 下面提供了有关这些格式的更多信息。

下一句话,<ntrks>,是文件中轨道块的数量。对于格式 0 文件,它始终为 1。

第三个字, <division>,指定增量时间的含义。它有两种格式,一种用于公制时间,另一种用于基于时间码的时间:

  |bits                                        |
  |15|14        ...         8|7     ...      0 |
  |--|-----------------------|-----------------|
  | 0|         ticks per quarter-note          |
  | 1| negative SMPTE format | ticks per frame |

如果位 15<division>是零,位 14 到 0 代表构成四分音符的增量时间“刻度”的数量。例如,如果<division>是 96,则文件中两个事件之间的八分音符的时间间隔将为 48。如果<division>是一个,文件中的增量时间对应于秒的细分,与 SMPTE 和 MIDI 时间代码一致。位 14 到 8 包含四个值 -24、-25、-29 或 -30 之一,对应于四种标准 SMPTE 和 MIDI 时间码格式(-29 对应于 30 个丢帧),并表示帧数每秒。这些负数以二进制补码形式存储。第二个字节(存储正值)是帧内的分辨率:典型值可能是 4(MIDI 时间码分辨率), 8、10、80(位分辨率)或 100。该系统允许精确指定基于时间码的轨道,但也通过指定 25 帧/秒和每帧 40 个单位的分辨率来允许基于毫秒的轨道。如果文件中的事件以 30 帧时间码的位分辨率存储,则除法字将为 E250 十六进制。


在您的示例中,您的第三个单词(十六进制 0078)意味着<division>每个四分音符 120 个刻度。

文件中事件的增量时间以刻度为单位给出。拍号是另一件完全不同的事情。它是节奏的指示,是一种元事件类型。 (参见规范第 10 页)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

确定 MIDI 文件的时间划分 的相关文章

随机推荐

  • 它不是将数据插入数据库

    我想将数据插入到Image Question桌子 但它不会执行插入操作Image Question Table 我收到两个错误 注意 未定义的偏移量 0 in 第 305 行 注意 未定义的偏移量 第 305 行上的 3 in 这是您可以使
  • 如何解决“无法解析某些模块 oracledb”?

    我已经设置了一个流星项目并导入了oracledb节点包 https github com oracle node oracledb 但是在通过启动项目后meteor run我收到控制台构建错误 说明Unable to resolve som
  • 将任何数据类型序列化为向量 - 使用reinterpret_cast?

    我在搜索中没有找到任何直接相关的内容 所以如果这是重复的 请原谅 我想要做的是通过网络连接序列化数据 我的方法是将我需要传输的所有内容转换为std vector lt uint8 t gt 并在接收端将数据解包到适当的变量中 我的方法如下
  • 方法可以变成静态的,但是应该吗?

    ReSharper 喜欢指出每个 ASP NET 页面的多个可以静态化的函数 如果我将它们设为静态会对我有帮助吗 我应该将它们设为静态并将它们移至实用程序类吗 在我看来 性能 命名空间污染等都是次要的 问问自己什么是合乎逻辑的 该方法在逻辑
  • xsl:如何选择节点中的前x个字符?

    我在 XML 文档中有以下节点
  • Android,我可以使用 putExtra 传递多个值吗

    我想将两个值传递给另一个活动 我可以用 putExtra 来做到这一点 还是必须以更复杂的方式来做到这一点 从我的阅读看来 例如 这样的东西可以工作吗 public final static String ID EXTRA com fnes
  • 删除 Firefox 中的默认选择框箭头

    我必须删除 Firefox 中的默认选择框箭头 我使用了下面的代码 webkit appearance none moz appearance none background rgba 0 0 0 0 它在 Chrome 中运行良好 但它在
  • 保存照片并立即使用

    我有以下用于拍照并将其保存到相机胶卷的代码 我需要能够在保存后使用它 而不必返回图库并选择它 我还没有找到任何关于如何执行此操作的示例 IBOutlet weak var imagePicked UIImageView IBAction f
  • 为 webRTC 使用特定端口

    当使用 webRTC 创建点对点音频连接时 如果用户位于路由器后面 我们使用的 STUN 服务器将返回公共 IP 现在在 ICE 对象中 我可以看到 rport 始终介于 50000 及以上 有没有办法使用特定端口 以便用户不必打开所有这些
  • Servlet 3.1 - 多部分异步处理

    我正在测试 Servlet 3 1 API 来处理多部分请求 我对同步处理某些部分 文本字段 和异步处理其他部分 文件字段 感兴趣 乍一看 它似乎在 Servlet 3 1 中不可用 要么在异步上下文中通过 request getInput
  • 使用adapter-static时如何在sveltekit上使用获取参数?

    我在构建时收到错误消息 无法访问url searchParams在启用预渲染的页面上 如何加载和使用get参数 svelte config js import adapter from sveltejs adapter static imp
  • Twitter bootstrap - 单击时聚焦于模式内的文本区域

    刚刚开始使用 bootstrap 这真是太棒了 我正在尝试解决这个问题 我在模式窗口内有一个用于反馈的文本区域 效果很好 但我希望当您单击按钮激活模式时 焦点位于文本区域上 而且我似乎无法让它发挥作用 这是一个小提琴 http jsfidd
  • 如何更改 Grafana 中的背景颜色?

    我想修改 Grafana 中的深色主题 以便它使用 000000作为背景颜色 我见过 如何更改Grafana的默认黑色 https stackoverflow com questions 41006070 how to change def
  • 使用 msbuild 从 VS 2008 升级到 2010 时未保留构建顺序和依赖项

    我正在升级 VS 2008 解决方案以在 VS 2010 上运行我成功地在 VS 2010 中构建 我现在的下一步是配置运行 TFS 2008 的构建机器每当我开始构建时 它都会按字母顺序执行我的项目 而不考虑依赖关系 我用谷歌搜索了很多
  • 用于检查文件大小是否比之前的检查有所增加的 VB 脚本

    我需要一个 VB 脚本来检查文件大小并捕获它 并在下一次检查中将其与上一次检查进行比较 如果大小增加 则应提示文件大小增加 你可以尝试一下这个vbscript Option Explicit const bytesToKb 1024 Dim
  • 如何将画布内容转换为图像?

    from Tkinter import root Tk cv Canvas root cv create rectangle 10 10 50 50 cv pack root mainloop 我想将画布内容转换为位图或其他图像 然后执行其
  • R 中生存数据的左删失

    我想对左右删失的数据进行生存分析 Kaplan Meier 和 Cox PH 建模 我正在研究特定基因 基因 0 或 1 存在与不存在时发生心律失常 AF 的时间 然而 一些受试者在招募时被发现已经存在心律失常 因此应该进行审查 我已阅读生
  • Twisted 中的多重响应

    我正在尝试开发简单的TCP 使用 Twisted 和 Pygame 进行客户端 服务器游戏 但我在向客户端发送数据时遇到困难 Twisted 不允许我连续发送多个响应 这就是我想做的 我有方法处理玩家状态更改并将其重新发送给其他客户端 de
  • ASP.NET Core 中 Mongodb 数据存储的基于简单令牌的身份验证/授权

    我需要实现非常简单的身份验证机制 基本上有两个角色 Owners and Users 我认为拥有 Enum 就足够了 应用程序本身是SPA 通过Asp net core实现webapi 我看到文章 如何使用 EF Identity 实现它
  • 确定 MIDI 文件的时间划分

    我正在用Python编写一个脚本来解析MIDI文件 是的 我知道Python存在MIDI解析库 但对于我的用例来说 如果我从头开始制作它是最简单的 我遇到的问题之一是时间划分 标头的最后两个字节指定时间划分 但我无法确定文件的时间划分是否以