相关arduino 全部分类:
https://blog.csdn.net/freewebsys/category_8799254.html
本文的原文连接是:
https://blog.csdn.net/freewebsys/article/details/104586650
未经博主允许不得转载。
博主地址是:http://blog.csdn.net/freewebsys
官方提供一个例子:
https://www.arduino.cc/en/Tutorial/ToneMelody?from=Tutorial.Tone
但是在使用的CDEFGAB 标示的,而网络上搜到的大多数都是简谱的。
还是使用简谱的比较好。其中 NTDL1 标示低音 Do , NTD1 标示 Do, NTDH1 表示高音 Do。
然后使用Python程序转换。
下山的歌谱如下
需要将这样的简谱,转换成 蜂鸣器能识别的频率和时间。也就是音阶和节拍。
需要两个数组的数据才可以进行转换。
melodys,需要直接输入 12 3456 这样的音节。
durations 需要输入节拍,规定下,4 4 拍的,
对应简谱进行处理,为了方便录入,五线谱上的节拍是这样转换成数字的:
4*4 拍的,转换成 8 ,为了保证 32 分音符等于 1 ,当然,也可以规定 4 分音符 = 4 。
如果规定 4 分音符 = 8 ,那么先用,相应的节拍 每小结就是 == 32 。这样数据句就转换了。
防止出现小数,剩下的就是计算了。
找到五线谱后需要把上面的音符都转换下。:
程序支持,普通 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 程序转换过来的,不是自己输入的。
程序还会对节拍和数组的长度进行对比,防止输入错误。
arduino 现在已经非常的成熟了,是一个非常成熟的解决方案了。
蜂鸣器这个非常特别的组件,还能这样用。后续可以研究下,如何使用 python 进行图片识别。
然后把这个五线谱 自动转换成 蜂鸣器的程序,然后播放出来。
主要是要是录入一段,还是使用不少时间的。网上的有些节拍还是使用的小数,就更加录入的慢了。
有这个Python 程序,自动检查,之后花上半个小数应该能转换一首歌曲。
本文的原文连接是:
https://blog.csdn.net/freewebsys/article/details/104586650
博主地址是:https://blog.csdn.net/freewebsys