本人蒟蒻,初学 Ardunio ,如有错误,请指正,感谢各路大佬。
最近上“早期工程实践”的时候,从老师那拿到了一块蜂鸣器,还有几页教人怎么用蜂鸣器的PPT。在PPT的结尾,老师布置了一个简单的实践任务:用蜂鸣器,演奏一首时长较短、旋律简单的儿歌。
这首歌很短,代码长度还好,难度不高,但是完成这个任务后,我有所思考
先给出一张PPT的截图
按照老师所教的方法,每次发出蜂鸣,都要调用一遍 tone() 和 delay() 。想要让蜂鸣器准确发出音调,还要查这个音调对应的频率
当要播放的乐谱变长之后,将会非常痛苦
所以我在想,能不能写一个函数,只需要输入乐谱,就能按照乐谱播放音乐
说干就干,于是乎有了下面这段代码
int pinMusic = 0; // 定义蜂鸣器占用的针脚,这里默认0号
// 定义三维整型数组,用于存乐谱
// 第一维度存放音调,第二维度用于提升或降低8度,第三维度存放一个音的持续时间
int music[][3] = {{1,1,4}}; // 像这样定义一个乐谱
int S, T;
void playMusic(int music[][3], int length) // 用于演奏的函数
{
for (int i=0; i<length; i++)
{
int note[3] = {music[i][0], music[i][1], music[i][2]};
if (note[0] == 0) // 休止符
{
T = 2500 / note[2];
delay(T);
}
else // 音符
{
readNotes(note[0],note[1],note[2]);
tone(pinMusic,S);
delay(T);
noTone(pinMusic);
}
delay(100); // 两个音之间的短暂间隔
}
}
// 把 1 - 7 映射到 音调频率表
int noteTable[7][3] = {{262,523,1046},{294,587,1175},{330,659,1318},{349,698,1397},
{392,784,1568},{440,880,1760},{494,988,1967}};
void readNotes(int sound, int jump, int time) // 用于读谱的函数
{
S = noteTable[sound-1][jump+1]; // 解析当前音符的音调,转换成蜂鸣器对应的频率
T = 2500 / time; // 解析当前音符的持续时间
}
// 示例:两只老虎
int twoTiggers[][3] = {{1,1,4},{2,1,4},{3,1,4},{1,1,4},{1,1,4},{2,1,4},{3,1,4},
{1,1,4},{3,1,4},{4,1,4},{5,1,2},{3,1,4},{4,1,4},{5,1,2},
{5,1,8},{6,1,8},{5,1,8},{4,1,8},{3,1,4},{1,1,4},{5,1,8},
{6,1,8},{5,1,8},{4,1,8},{3,1,4},{1,1,4},{2,1,4},{5,-1,4},
{1,1,3},{0,1,4},{2,1,4},{5,-1,4},{1,1,3}};
void setup()
{
Serial.begin(9600);
Serial.println("start");
delay(1000); // 开机缓冲1s
// 演奏方法:
// 先定义 int num = sizeof(乐谱名)/sizeof(乐谱名[0]);
// 然后调用 playMusic(乐谱名, num);
int num = sizeof(twoTiggers)/sizeof(twoTiggers[0]);
playMusic(twoTiggers, num); // 演奏 两只老虎
}
void loop() // 用不上loop,但是没有它会报错
{
}
在这段程序中,只需要以三维数组的形式,编写想要演奏的乐谱,即可调用 playMusic() 函数为您演奏。其中,编写的乐谱要遵守如下规则:
一个音符包含三个维度,以 {1,1,4} 为例
第一维:
do - si 用 1 - 7 表示
0 为休止符, 其他符号均非法
第二维:
0 不改变音域
1 = 升8度; -1 = 降8度
第三维:
8表示8分音符的持续时间
4表示4分音符的持续时间
其余同理
要制作不同时间的休止符,请用{0,1,time}
改变 time 的值以制作不同的休止符
程序中音调与频率的对应关系,来自老师给出的一个表格
不知道准不准确,本人乐理知识欠缺。(如果代码中有一些音乐术语的错误,请原谅)
接下来,就开始愉快地编曲吧!这里给出一段简单的示范
// 示例:两只老虎
int twoTiggers[][3] = {{1,1,4},{2,1,4},{3,1,4},{1,1,4},{1,1,4},{2,1,4},{3,1,4},
{1,1,4},{3,1,4},{4,1,4},{5,1,2},{3,1,4},{4,1,4},{5,1,2},
{5,1,8},{6,1,8},{5,1,8},{4,1,8},{3,1,4},{1,1,4},{5,1,8},
{6,1,8},{5,1,8},{4,1,8},{3,1,4},{1,1,4},{2,1,4},{5,-1,4},
{1,1,3},{0,1,4},{2,1,4},{5,-1,4},{1,1,3}};
由于我的编程能力欠缺,本人的代码还有很多欠完善的地方,希望多多谅解,也欢迎大神改进!