arduino(14):使用ESP8266加蜂鸣器,自己动手做歌曲,使用python 程序,做简单的五线谱转换。直接把音节和节拍转换,然后转换成数据,用蜂鸣器播放歌曲《下山》。。

前言


相关arduino 全部分类:
https://blog.csdn.net/freewebsys/category_8799254.html

本文的原文连接是:
https://blog.csdn.net/freewebsys/article/details/104586650

未经博主允许不得转载。
博主地址是:http://blog.csdn.net/freewebsys

1,关于 蜂鸣器例子


官方提供一个例子:

https://www.arduino.cc/en/Tutorial/ToneMelody?from=Tutorial.Tone

但是在使用的CDEFGAB 标示的,而网络上搜到的大多数都是简谱的。
还是使用简谱的比较好。其中 NTDL1 标示低音 Do , NTD1 标示 Do, NTDH1 表示高音 Do。
然后使用Python程序转换。

下山的歌谱如下
在这里插入图片描述
需要将这样的简谱,转换成 蜂鸣器能识别的频率和时间。也就是音阶和节拍。
需要两个数组的数据才可以进行转换。

2,使用 Python 程序转换


melodys,需要直接输入 12 3456 这样的音节。
durations 需要输入节拍,规定下,4 4 拍的,

对应简谱进行处理,为了方便录入,五线谱上的节拍是这样转换成数字的:
在这里插入图片描述
4*4 拍的,转换成 8 ,为了保证 32 分音符等于 1 ,当然,也可以规定 4 分音符 = 4 。
如果规定 4 分音符 = 8 ,那么先用,相应的节拍 每小结就是 == 32 。这样数据句就转换了。
防止出现小数,剩下的就是计算了。
找到五线谱后需要把上面的音符都转换下。:

扫描二维码关注公众号,回复: 9520515 查看本文章

在这里插入图片描述
程序支持,普通 Do = 1 ,低音 Do = L1 , 高音Do = H1。
这样就可以录入数组了。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# https://www.runoob.com/python/python-tutorial.html

# 输出 Python 的每个字母
melodys = [
    "06 653 5556 0553", #要想练就绝世武功
    "55 553 556 553", #就要忍受常人难忍受的痛。师傅
    "66 653 5556 653",#喜欢喝的荼叫做乌龙
    "55 556 50 00",#衣服爱穿中国红。(嘿,师傅。
    "06 653 5556 0553",#无论是炎夏或寒冬
    "55 553 556 555",#我都很向往山门外的天空,还在
    "6H3 H266 6H3 H266",#南方等我下山的我
    "6H3 H2H16 6 03",#的人叫小落。我
    "35 655 6553 3",#左手式太极拳
    "23 533 556 53",#右手剑刺身前
    "35 655 6553 3",#扫腿这招叫清雪
    "23 556 3 03",#破轻功飞燕
    "35 655 6553 3",#奇筋异脉力破天
    "23 533 556 53",#身正气荡人间
    "35 655 6553 3",#除暴安良我心愿
    "223 21L6 L6 0",#老师傅再见
]

durations = [
    "44 422 2222 2222", #要想练就绝世武功
    "44 422 242 422", #就要忍受常人难忍受的痛。师傅
    "44 422 2222 422",#喜欢喝的荼叫做乌龙
    "44 242 62 26",#衣服爱穿中国红。(嘿,师傅。
    "44 422 2222 2222",#无论是炎夏或寒冬
    "44 422 242 422",#我都很向往山门外的天空,还在
    "44 224 44 224",#南方等我下山的我
    "44 422 8 62",#的人叫小落。我
    "62 224 2222 8",#左手式太极拳
    "62 224 422 44",#右手剑刺身前
    "62 224 2222 8",#扫腿这招叫清雪
    "44 422 8 62",#破轻功飞燕
    "62 224 2222 8",#奇筋异脉力破天
    "62 224 422 44",#身正气荡人间
    "62 224 2222 8",#除暴安良我心愿
    "422 422 8 8",#老师傅再见
]

def print_melody(melody):
    strNum = ""
    for num in melody:
        strNum += " NTD%s," % num
    # 特殊处理高低音节,保证一致。
    strNum = strNum.replace("H, NTD","H").replace("L, NTD","L")
    print(strNum)

def print_duration(duration):
    strNum = ""
    for num in duration:
        strNum += " %s," % num
    print(strNum)

def check_duration(duration):
    sum = 0
    for x in duration:
        sum += int(x)
    if(sum != 32):
        return False
    else:
        return True


for i in range(len(melodys)):
    #print(i)
    #替换掉高低特殊字符。
    melody = melodys[i].replace(" ","").replace("H","").replace("L","")
    duration = durations[i].replace(" ","")
    if(len(melody) != len(duration)):
        print("len melody : " + str(len(melody)))
        print("len duration : " + str(len(duration)))
        print("error ! line : " + str(i))
        exit(0)
    check = check_duration(duration)
    if(not check):
        print("check duration error ! " + durations[i])
        print("check duration error ! " + str(i))
        exit(0)
    #包括高低音字符。
    melody = melodys[i].replace(" ", "")
    print_melody(melody)

print("#########################")

for i in range(len(durations)):
    #print(i)
    duration = durations[i].replace(" ","")
    print_duration(duration)

print("############  all ok  #############")

为了加快转换,可以直接通过百度 ai,扣出图片的音节:可惜节拍不行呢。

https://ai.baidu.com/tech/ocr/general
在这里插入图片描述

最终下山的歌曲效果:


#define NTD0 0

// low
#define NTDL1 262 // NOTE_C4  262  L1
#define NTDL2 294 // NOTE_D4  294  L2
#define NTDL3 330 // NOTE_E4  330  L3
#define NTDL4 349 // NOTE_F4  349  L4
#define NTDL5 392 // NOTE_G4  392  L5
#define NTDL6 440 // NOTE_A4  440  L6
#define NTDL7 494 // NOTE_B4  494  L7

#define NTD1 523 // NOTE_C5  523   1
#define NTD2 587 // NOTE_D5  587   2
#define NTD3 659 // NOTE_E5  659   3
#define NTD4 698 // NOTE_F5  698   4
#define NTD5 784 // NOTE_G5  784   5
#define NTD6 880 // NOTE_A5  880   6
#define NTD7 988 // NOTE_B5  988   7

// high 
#define NTDH1 1047 // NOTE_C6  1047  H1
#define NTDH2 1175 // NOTE_D6  1175  H2
#define NTDH3 1319 // NOTE_E6  1319  H3
#define NTDH4 1397 // NOTE_F6  1397  H4
#define NTDH5 1568 // NOTE_G6  1568  H5
#define NTDH6 1760 // NOTE_A6  1760  H6
#define NTDH7 1976 // NOTE_B6  1976  H7


// notes in the melody:
int melody[] = {
 NTD0, NTD6, NTD6, NTD5, NTD3, NTD5, NTD5, NTD5, NTD6, NTD0, NTD5, NTD5, NTD3,
 NTD5, NTD5, NTD5, NTD5, NTD3, NTD5, NTD5, NTD6, NTD5, NTD5, NTD3,
 NTD6, NTD6, NTD6, NTD5, NTD3, NTD5, NTD5, NTD5, NTD6, NTD6, NTD5, NTD3,
 NTD5, NTD5, NTD5, NTD5, NTD6, NTD5, NTD0, NTD0, NTD0,
 NTD0, NTD6, NTD6, NTD5, NTD3, NTD5, NTD5, NTD5, NTD6, NTD0, NTD5, NTD5, NTD3,
 NTD5, NTD5, NTD5, NTD5, NTD3, NTD5, NTD5, NTD6, NTD5, NTD5, NTD5,
 NTD6, NTDH3, NTDH2, NTD6, NTD6, NTD6, NTDH3, NTDH2, NTD6, NTD6,
 NTD6, NTDH3, NTDH2, NTDH1, NTD6, NTD6, NTD0, NTD3,
 NTD3, NTD5, NTD6, NTD5, NTD5, NTD6, NTD5, NTD5, NTD3, NTD3,
 NTD2, NTD3, NTD5, NTD3, NTD3, NTD5, NTD5, NTD6, NTD5, NTD3,
 NTD3, NTD5, NTD6, NTD5, NTD5, NTD6, NTD5, NTD5, NTD3, NTD3,
 NTD2, NTD3, NTD5, NTD5, NTD6, NTD3, NTD0, NTD3,
 NTD3, NTD5, NTD6, NTD5, NTD5, NTD6, NTD5, NTD5, NTD3, NTD3,
 NTD2, NTD3, NTD5, NTD3, NTD3, NTD5, NTD5, NTD6, NTD5, NTD3,
 NTD3, NTD5, NTD6, NTD5, NTD5, NTD6, NTD5, NTD5, NTD3, NTD3,
 NTD2, NTD2, NTD3, NTD2, NTD1, NTDL6, NTDL6, NTD0,
  
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 4, 4, 4, 2, 2, 2, 4, 2, 4, 2, 2,
 4, 4, 4, 2, 2, 2, 2, 2, 2, 4, 2, 2,
 4, 4, 2, 4, 2, 6, 2, 2, 6,
 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 4, 4, 4, 2, 2, 2, 4, 2, 4, 2, 2,
 4, 4, 2, 2, 4, 4, 4, 2, 2, 4,
 4, 4, 4, 2, 2, 8, 6, 2,
 6, 2, 2, 2, 4, 2, 2, 2, 2, 8,
 6, 2, 2, 2, 4, 4, 2, 2, 4, 4,
 6, 2, 2, 2, 4, 2, 2, 2, 2, 8,
 4, 4, 4, 2, 2, 8, 6, 2,
 6, 2, 2, 2, 4, 2, 2, 2, 2, 8,
 6, 2, 2, 2, 4, 4, 2, 2, 4, 4,
 6, 2, 2, 2, 4, 2, 2, 2, 2, 8,
 4, 2, 2, 4, 2, 2, 8, 8,
};

int tonepin=3;

void common_play() {
  
  // iterate over the notes of the melody:
  for (int thisNote = 0; thisNote < sizeof(melody)/4; thisNote++) {
    
    // to calculate the note duration, take one second divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = ( 1000 / 8 ) * noteDurations[thisNote];
    tone(tonepin, melody[thisNote], noteDuration);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    //int pauseBetweenNotes = noteDuration * 1.3;
    delay(noteDuration);
    // stop the tone playing:
    noTone(tonepin);
  }
}

void setup() {
  Serial.begin(9600);
  Serial.print(" init ...");
  Serial.print(sizeof(melody));
  Serial.print(sizeof(noteDurations));
  pinMode(tonepin,OUTPUT);
}

void loop() {
  common_play();//Play the music.
  delay(3000);//Pause for a while.
}

其中音阶的部分是通过 Pyhton 程序转换过来的,不是自己输入的。
程序还会对节拍和数组的长度进行对比,防止输入错误。

3,总结


arduino 现在已经非常的成熟了,是一个非常成熟的解决方案了。
蜂鸣器这个非常特别的组件,还能这样用。后续可以研究下,如何使用 python 进行图片识别。
然后把这个五线谱 自动转换成 蜂鸣器的程序,然后播放出来。
主要是要是录入一段,还是使用不少时间的。网上的有些节拍还是使用的小数,就更加录入的慢了。
有这个Python 程序,自动检查,之后花上半个小数应该能转换一首歌曲。

本文的原文连接是:
https://blog.csdn.net/freewebsys/article/details/104586650

博主地址是:https://blog.csdn.net/freewebsys

发布了639 篇原创文章 · 获赞 260 · 访问量 211万+

猜你喜欢

转载自blog.csdn.net/freewebsys/article/details/104586650
今日推荐