layout: post comments: true title: 【巧妇难为无米之炊】为机甲大师从MusicXML提取乐谱之卡农 description: date: 2019-11-06 00:00:00 -0700
一声部(忍过开头20秒就还好,以我外行来听): 机甲大师演奏卡农一声部
二声部(感觉比较平): 机甲大师演奏卡农二声部
上文 【日常】Python读取解析xml文件,顺便转换为大疆机甲大师可以演奏的乐谱 既然摆开了铺子,评论区的请求就得有求必应。结果,传说中的卡农,果然是个烫手山芋。
先按照前文的脚本跑了一下,音符所在音阶分布如下:
2: 109 3: 349 4: 305 5: 320 6: 1
因为机甲只能演奏三个八度,自(很)然(二)地首先按照音阶范围来过滤音符,比如把2,6音阶的音符删除,留下3-5(因为占的多),试了几种范围,白耗一个多钟头只得到很烂的效果。
最后还是静下心来仔细分析MusicXML第一小节,对比过滤后的音符总是对不上号(细节略去):
<measure number="1" width="300.40">
。。。
<note default-x="78.02" default-y="-40.00">
<pitch>
<step>E</step>
<octave>4</octave>
</pitch>
<duration>8</duration>
<voice>1</voice>
<type>half</type>
<stem>up</stem>
<staff>1</staff>
</note>
<note default-x="188.24" default-y="-45.00">
<pitch>
<step>D</step>
<octave>4</octave>
</pitch>
<duration>8</duration>
<voice>1</voice>
<type>half</type>
<stem>up</stem>
<staff>1</staff>
</note>
<backup>
<duration>16</duration>
</backup>
<note default-x="78.02" default-y="-130.00">
<pitch>
<step>C</step>
<octave>3</octave>
</pitch>
<duration>8</duration>
<voice>5</voice>
<type>half</type>
<stem>up</stem>
<staff>2</staff>
</note>
<note default-x="188.24" default-y="-145.00">
<pitch>
<step>G</step>
<octave>2</octave>
</pitch>
<duration>8</duration>
<voice>5</voice>
<type>half</type>
<stem>up</stem>
<staff>2</staff>
</note>
</measure>
根据五线谱(上次这么看谱大概还是小学初中的时候?)
后两个音在下面一部分。这才注意到<voice>5</voice>这个属性。看了MusicXML貌似是不同声部。原来如此( ⊙ o ⊙ )啊!
因为第二声部(voice=5)没有和弦,因为机甲现在不支持和弦,于是决定先生成这个声部。但效果听起来比较平淡,于是坚持把第一声部也做了,规避和弦的方法就是只演奏和弦中的一个音 :< 最后用于提取乐谱的PC端运行的脚本仍在此处,写的比较乱,是卡农专用,需要的请自改。
又花了一个钟头,最后大疆机甲的Python代码大体如下(完整在此处):
def start(): 单位间隔 = 0.12 一声部乐谱 = [ 常量.咪2, 8, 常量.来2, 8, 常量.哆2, 8, 常量.西1, 8, 常量.啦1, 8, 常量.嗦1, 8, 常量.啦1, 8, 常量.西1, 8, (此处省去70行) 常量.咪2, 16 ] 五声部乐谱 = [ 常量.哆2, 8, 常量.嗦1, 8, 常量.啦1, 8, 常量.咪1, 8, 常量.发1, 8, 常量.嗦1, 8, 常量.发1, 8, 常量.嗦1, 8, (此处省去60行) 常量.嗦2, 16 ] 。。。
乐谱 = 一声部乐谱
for 序号 in range(0, len(乐谱) // 2):
if 乐谱[序号 * 2]:
多媒体.演奏(乐谱[序号 * 2])
时间.睡眠(乐谱[序号 * 2 + 1] * 单位间隔)
后感
每个声部500个音符,生成上面一百多行的乐谱数据,虽然提取脚本能省去不少功夫(没有的话我是绝然不会自己手工翻的),但还是不禁感叹 -- ”WHAT‘S THE POINT??"
这条音乐合成的路,有点看不出走向何方。如果是类似“两只老虎”或者“粉刷匠”这样的儿歌,现在的接口貌似足够了。
但只要是想更进一步,就要往专业音乐合成软件的方向走。对开发者来说比较省力和通用的,是机甲开发组提供一个接受类似MusicXML格式的乐谱描述文件的接口,能够自行演奏。
不然,至少要支持和弦,以及更广的音域。
但是.......前几天我在乐呵呵地给小小的演示机甲演奏《彩云追月》时,领导一句话“哦?这是它自带的吧?”给我上了严酷的现实一课:合成的再好,好的过播放现成的mp3吗?
以我有限的眼界,只能看到现有机甲的演奏功能是少儿音乐+编程教育的一个交集。(虽然我是宁愿小的学个简单乐器,而不是对着机器人模拟弹琴效果)大概会有希望一箭双雕的家长吧。
而对于不知就里的旁人,仅从听觉效果来说,这个功能的实用性恐怕还不及支持播放mp3文件,尤其在现在的少儿教育产品早就普及了播放功能的今天。
从这个角度说,最好有个接口能直接接受输入乐曲名”卡农“,然后就直接播放内置的乐曲。
要么,就是向之前提到的往专业音乐合成方向走。虽然我是非常希望机甲开发组省下功夫加强人机交互功能,尤其是语音识别和合成,往R2-D2的科幻效果冲刺!会聊天的机器人,毕竟比会(看起来像)放mp3的高不止一点点。
在此声明:不再无偿生成机甲乐谱。欢迎自行修改已开源的乐谱数据或者生产脚本进行乐谱生成。如果真的真的(很难想象会有)需要我的定制,请私下联系并准备好红包 :]