我正在实现一个应用程序来执行MIDI文件的一些任务,我目前的问题是将我读过的笔记输出到LilyPond文件.
我已经将note_on和note_off事件合并到具有绝对开始和绝对持续时间的单个音符对象,但我真的没有看到如何将该持续时间转换为实际的音乐符号.我已经猜到376的持续时间是我正在阅读的文件中的四分音符,因为我知道这首歌,显然188是八分音符,但这肯定不会推广到所有MIDI文件.
有任何想法吗?
默认情况下,MIDI文件设置为120 bpm的速度,文件中的MThd块将以"每四分音符脉冲数"(ppqn)的形式告诉您分辨率.
例如,如果ppqn是96而不是96蜱的差值是四分音符.
如果您对每个声音的实际持续时间(以秒为单位)感兴趣,您还应该考虑可以通过事件"FF 51 03 tt tt tt"更改的"速度"; 三个字节是四分音符的微秒.
有了这两个值,你应该找到你需要的东西.请注意,midi文件中的持续时间可能是近似的,特别是如果该MIDI文件是人类播放器的录制.
很久以前我已经把一个C库放在一起来读/写midifiles:https://github.com/rdentato/middl 以防它可能有用(很长一段时间我都不看代码,感觉可以自由地询问是否有任何不清楚的地方).
我建议遵循这种方法:
在你的情况下,将1/32作为最小音符,将384作为除法(即48个音符).对于376的音符,你将得到376/48 = 7.8,你可以将其舍入到8(最接近的整数)和8/32 = 1/4.
如果你找到一个持续时间为193个刻度的音符,你可以看到它是1/8音符,因为193/48是4.02(你可以舍入到4)和4/32 = 1/8.
继续这种推理,你可以看到持续671个刻度的音符应该是双点四分音符.
实际上,671应该近似为672(48的最接近的倍数),即14*48.所以你的笔记是14/32 - > 7/16 - >(1/16 + 2/16 + 4/16) - > 1/16 + 1/8 + 1/4.
如果你习惯使用二进制数字,你可能会注意到14 1110和那里,直接导出1/16,1/4和1/8的存在.
作为另一个例子,持续时间为480个刻度的音符是与1/16音符相关联的四分音符,因为480 = 48*10并且10是1010二进制的.
三胞胎和其他团体会让事情变得更加复杂.最常见的除法值是96(3*2 ^ 5),192(3*2 ^ 6)和384(3*2 ^ 7)并非偶然; 这样三元组可以用整数个刻度表示.
在某些情况下,您可能需要猜测或简化,这就是为什么没有"midi到标准符号"程序可以100%准确.