正在上传图片(0/1)

#S1歌舞大赛#勃拉姆斯的摇篮曲--乐谱简易录入方法

 5
手机看帖 6 3402
孩子小时候,我哼得最多的曲子,最多三遍,一定睡着

S1新加入了播放音符的功能,看了一些机友的视频,大家都用scratch写的吧,逐个音符输入很累吧。
本程序用python编写,采用了一些技术手段,可以把你从繁琐的输入中解放出来,轻轻松松播放各种曲子

首先,那个长长的define非常不友好,rm_define.media_sound_solmization_1C,一个音符就这么长,敲键盘要敲多久啊。那个1C,要想一想才知道是低音1。要是看简谱录入,你还是要反应一下,用scratch的话,你还要人工做唱名到钢琴键之间的映射,太麻烦了

其次,一句一句地写media_ctrl.play_sound(),太累了,用scratch的话,一个一个调用播放音符模块,同样太累了,要是输错了一个音符,你就慢慢找吧

于是,我先定义了一个编码,11-17表示低音1-7,21-27表示中音1-7,31-37表示高音1-7,至于升半音,那就加0.5,比如23.5表示中音3#,特别地,0表示休止符。代码如下

global note
note = [\
rm_define.media_sound_solmization_1C,rm_define.media_sound_solmization_1CSharp,\
rm_define.media_sound_solmization_1D,rm_define.media_sound_solmization_1DSharp,\
rm_define.media_sound_solmization_1E,\
rm_define.media_sound_solmization_1F,rm_define.media_sound_solmization_1FSharp,\
rm_define.media_sound_solmization_1G,rm_define.media_sound_solmization_1GSharp,\
rm_define.media_sound_solmization_1A,rm_define.media_sound_solmization_1ASharp,\
rm_define.media_sound_solmization_1B,\
rm_define.media_sound_solmization_2C,rm_define.media_sound_solmization_2CSharp,\
rm_define.media_sound_solmization_2D,rm_define.media_sound_solmization_2DSharp,\
rm_define.media_sound_solmization_2E,\
rm_define.media_sound_solmization_2F,rm_define.media_sound_solmization_2FSharp,\
rm_define.media_sound_solmization_2G,rm_define.media_sound_solmization_2GSharp,\
rm_define.media_sound_solmization_2A,rm_define.media_sound_solmization_2ASharp,\
rm_define.media_sound_solmization_2B,\
rm_define.media_sound_solmization_3C,rm_define.media_sound_solmization_3CSharp,\
rm_define.media_sound_solmization_3D,rm_define.media_sound_solmization_3DSharp,\
rm_define.media_sound_solmization_3E,\
rm_define.media_sound_solmization_3F,rm_define.media_sound_solmization_3FSharp,\
rm_define.media_sound_solmization_3G,rm_define.media_sound_solmization_3GSharp,\
rm_define.media_sound_solmization_3A,rm_define.media_sound_solmization_3ASharp,\
rm_define.media_sound_solmization_3B]

def play_note(x):
    a = x // 10 - 1
    b = x * 2 % 20 - 2
    if b > 5:
        b -= 1
    n = int(a * 12 + b)
    if x != 0:
        media_ctrl.play_sound(note[n])
函数play_note(x) 直接播放我定义的编码对应的音符,至于这个函数怎么写的,比较难说明白,大家当黑匣子就好

然后,定义一个数组,用两个数表示一个音,第一个数就是上述编码,第二个数是音长,简单粗暴一点,1表示四分音符,0.5表示八分音符,0.25表示十六分音符,1.5表示附点四分音符,呵呵,总之就是1代表1拍,对应实际时间1秒。比如勃拉姆斯的摇篮曲,代码如下,直接照着简谱抄,童叟无欺:
music = [\
23,0.5, 23,0.5, 25,1.5, 23,0.5, 23,1, 25,1, 0,1, 23,0.5, 25,0.5, 31,1, 27,1.5, 26,0.5, 26,1, 25,1, 22,0.5, 23,0.5,\
24,1, 22,1, 22,0.5, 23,0.5, 24,1, 0,1, 22,0.5, 24,0.5, 27,0.5, 26,0.5, 25,1, 27,1, 31,1, 0,1, 21,0.5, 21,0.5,\
31,2, 26,0.5, 24,0.5, 25,2, 23,0.5, 21,0.5, 24,1, 25,1, 26,1, 23,0.25, 25,1.75, 21,0.5, 21,0.5,\
31,2, 26,0.5, 24,0.5, 25,2, 23,0.5, 21,0.5, 24,0.5, 25,0.25, 24,0.25, 23,1, 22,1, 21,2]
我写的时候,故意把两个数写得紧凑,而每两个数之间加了一个空格,这样有什么问题好查

播放就很简单了,一个循环,读数组,播音符,over
def start():
    global note
    global music   
    for i in range(0,len(music)//2):
        play_note(music[2*i])
        time.sleep(music[2*i+1])
简单吧,要播放其他音乐,换music数组就好,程序不动,动的只是数据
DJI要是再支持文件读写就更爽了,音乐写在文件里,读文件播放,源代码都可以不动

播放音乐搞定了,现在要加上动作,怎么加呢?很遗憾,DJI还没有支持多线程,需要有一个变通的办法

怎么做呢?就是在上面time.sleep()函数这里做文章。我玩过很多种机器人,对于几乎所有的机器人,sleep,wait之类的函数都非常坑爹,要想编出高级程序,必须放弃这一类函数

具体做法,用计时器,代码框架是这样的
    for i in range(0,len(music)//2):
        play_note(music[2*i])
        t0 = tools.timer_current()
        t = t0
        while t < t0 + music[2*i+1]:
            t = tools.timer_current()
            #这里插入你要做的事情
播放音符是一个非阻塞功能,执行了之后,后台就播放去了,前台交到你手里
这时,用变量t0记录当前时间,再用循环反复检查(当前时间-t0)有没有达到你期望的延迟,就可以实现sleep函数的效果,但是你获得了做你自己的事情的机会

具体到这个曲子,既然是摇篮曲,那就模拟摇摇篮的动作吧,用一个周期函数控制速度,做一个圆弧运动就好。代码如下:
    for i in range(0,len(music)//2):
        play_note(music[2*i])
        t0 = tools.timer_current()
        t = t0
        while t < t0 + music[2*i+1]:
            t = tools.timer_current()
            v = 0.5*math.cos(t*1.5)
            chassis_ctrl.move_with_speed(v,0,v/math.pi*180)
    chassis_ctrl.stop()

再配合一下灯效,用呼吸灯。可惜呼吸灯不能调周期,没法与音乐融为一体,是个遗憾
    led_ctrl.set_bottom_led(rm_define.armor_bottom_all, 69, 215, 255, rm_define.effect_breath)   
    led_ctrl.set_top_led(rm_define.armor_top_all, 69, 215, 255, rm_define.effect_breath)

再让云台摆个姿势,就当是一位父亲抱着小宝宝,哼着摇篮曲,轻轻摇动:D
    robot_ctrl.set_mode(rm_define.robot_mode_free)
    gimbal_ctrl.set_rotate_speed(270)
    gimbal_ctrl.angle_ctrl(90, -15)

视频如下:
这是完整的代码:
global note
note = [\
rm_define.media_sound_solmization_1C,rm_define.media_sound_solmization_1CSharp,\
rm_define.media_sound_solmization_1D,rm_define.media_sound_solmization_1DSharp,\
rm_define.media_sound_solmization_1E,\
rm_define.media_sound_solmization_1F,rm_define.media_sound_solmization_1FSharp,\
rm_define.media_sound_solmization_1G,rm_define.media_sound_solmization_1GSharp,\
rm_define.media_sound_solmization_1A,rm_define.media_sound_solmization_1ASharp,\
rm_define.media_sound_solmization_1B,\
rm_define.media_sound_solmization_2C,rm_define.media_sound_solmization_2CSharp,\
rm_define.media_sound_solmization_2D,rm_define.media_sound_solmization_2DSharp,\
rm_define.media_sound_solmization_2E,\
rm_define.media_sound_solmization_2F,rm_define.media_sound_solmization_2FSharp,\
rm_define.media_sound_solmization_2G,rm_define.media_sound_solmization_2GSharp,\
rm_define.media_sound_solmization_2A,rm_define.media_sound_solmization_2ASharp,\
rm_define.media_sound_solmization_2B,\
rm_define.media_sound_solmization_3C,rm_define.media_sound_solmization_3CSharp,\
rm_define.media_sound_solmization_3D,rm_define.media_sound_solmization_3DSharp,\
rm_define.media_sound_solmization_3E,\
rm_define.media_sound_solmization_3F,rm_define.media_sound_solmization_3FSharp,\
rm_define.media_sound_solmization_3G,rm_define.media_sound_solmization_3GSharp,\
rm_define.media_sound_solmization_3A,rm_define.media_sound_solmization_3ASharp,\
rm_define.media_sound_solmization_3B]

def play_note(x):
    a = x // 10 - 1
    b = x * 2 % 20 - 2
    if b > 5:
        b -= 1
    n = int(a * 12 + b)
    if x != 0:
        media_ctrl.play_sound(note[n])

music = [\
23,0.5, 23,0.5, 25,1.5, 23,0.5, 23,1, 25,1, 0,1, 23,0.5, 25,0.5, 31,1, 27,1.5, 26,0.5, 26,1, 25,1, 22,0.5, 23,0.5,\
24,1, 22,1, 22,0.5, 23,0.5, 24,1, 0,1, 22,0.5, 24,0.5, 27,0.5, 26,0.5, 25,1, 27,1, 31,1, 0,1, 21,0.5, 21,0.5,\
31,2, 26,0.5, 24,0.5, 25,2, 23,0.5, 21,0.5, 24,1, 25,1, 26,1, 23,0.25, 25,1.75, 21,0.5, 21,0.5,\
31,2, 26,0.5, 24,0.5, 25,2, 23,0.5, 21,0.5, 24,0.5, 25,0.25, 24,0.25, 23,1, 22,1, 21,2]
def start():
    robot_ctrl.set_mode(rm_define.robot_mode_free)
    gimbal_ctrl.set_rotate_speed(270)
    gimbal_ctrl.angle_ctrl(90, -15)
    led_ctrl.set_bottom_led(rm_define.armor_bottom_all, 69, 215, 255, rm_define.effect_breath)   
    led_ctrl.set_top_led(rm_define.armor_top_all, 69, 215, 255, rm_define.effect_breath)
    tools.timer_ctrl(rm_define.timer_start)
    global note
    global music   
    for i in range(0,len(music)//2):
        play_note(music[2*i])
        t0 = tools.timer_current()
        t = t0
        while t < t0 + music[2*i+1]:
            t = tools.timer_current()
            v = 0.5*math.cos(t*1.5)
            chassis_ctrl.move_with_speed(v,0,v/math.pi*180)
    chassis_ctrl.stop()

S1如摇篮一般缓缓摇动,配合呼吸灯,轻轻地哼着勃拉姆斯摇篮曲,亲爱的各位小朋友和大朋友,该睡觉了
评论
上传
你需要登录之后才能回帖    登录 | 注册
jatgz020  Spark认证用户 2019-10-26 3#
哈~,s1的编程越来越有意思了,歌曲可以带节奏了,一个个音符输入且带节拍,可能要码字一天吧?一个函数自定义一下,就可以少输入好多行命令?有意思了,有些看头,再搞多些函数自定义出来,看是否可以动作与声音结合起来做更多的复杂的表现?或者更智能地识别一些规程?赞一个!
其实我提的建议就是直接播放MP3文档,或者录制弹奏的音符进行播放。
王生   2019-11-12 5#
楼主真神人也!!
总督  机甲大师 RoboMaster S1认证用户 2019-11-19 6#
这个文章写的好啊,必须点赞
阿阿阿阿阿默   2019-11-21 7#
看完觉得SCRATCH真的太弱了
想把S1玩通透真得要学PYTHON啊
小灰机小谷  FPV System认证用户 2019-12-8 8#
才19点,睡啥呀
取消 点赞 评论
分享至:
回复:
上传
取消 评论
快速回复 返回顶部 返回列表