2.3 编程播放歌曲《我和我的祖国》
Arduino Uno开发板能让LED灯一闪一闪的,能不能让小喇叭唱歌呢?如何让小喇叭播放歌曲呢?如果你感兴趣,可以从网上找一首自己喜爱的歌曲简谱,尝试编写一段播放歌曲的程序。
2.3.1 实验描述
(1)让喇叭发出频率为1000Hz的声音,可持续200ms,停止发声1800ms,如此循环。
(2)让喇叭播放歌曲《我和我的祖国》。
AU03的电路原理图、电路板图和实物图如图2.5所示。
图2.5 AU03的电路原理图、电路板图和实物图
2.3.2 知识要点
编程播放歌曲,就是通过编写程序的方式让小喇叭播放歌曲。编程播放歌曲对于普通人而言,能起到娱乐、愉悦的作用;对于喜欢音乐的人而言,则有助于他们准确把握每个音符的音高(音的振动频率高低)与音值(音的持续时间长短)。
歌曲《我和我的祖国》的简谱如图2.6所示。
图2.6 歌曲《我和我的祖国》的简谱
“1=G(52)”表示G调,就是把乐器上音高为G的音唱成1(do),二胡用52弦拉。有的简谱前标“1=C”表示以C音为1(do),而“1=D”表示以D音为1(do),将“1=C”换成“1=D”后,乐曲整体音调变高。现在的标准调音音高A4的频率为440Hz,往上高八度的A5的频率为880Hz,往下低八度的A3的频率为220Hz,如表2.1所示。
表2.1 不同音的频率对照表 单位:Hz
(续表)
“”是一种复拍子,表示以附点四分音符为一拍,每小节两拍。歌曲中把由3个八分音符组成的三连音当一拍,3个音符下画一条横线,就是3个音符共唱一拍。
“=60”表示该歌曲的速度为60拍/分钟,一拍时间为1s。歌曲中一小节两拍,因此一小节的演唱时间为2s,16小节的演唱时间为32s。
音符是乐谱中表示音高或音值的符号。五线谱中用空心或实心的小椭圆形和特定的附加符号表示音符,简谱中用7个阿拉伯数字(1、2、3、4、5、6、7)和特定的附加符号表示音符。
音调是听觉能分辨的声音的高低程度,是个主观量。纯音音调的高低主要由声音的频率来决定,频率越高,人感受到的音调也越高。音调也和声音的强度有关,一般2000Hz以下的低频纯音的音调随强度的增加而下降,3000Hz以上的高频纯音的音调随强度的增加而上升。音调还和声音持续的时间长短有关,非常短促(ms量级或更短)的纯音,只能听到像打击或弹指一样的响声,感觉不出音调。持续时间从10ms增加到50ms,能感觉到音调由低而高的连续变化;超过50ms,音调就稳定不变了。乐音的音调更复杂,主要由基音的频率决定。
音高是音的高度,是乐音在音阶上的绝对高度,如C音、D音,与声音的振动频率有关。音名是乐器各音级的标注名称,包括C、D、E、F、G、A、B,与简谱中的1、2、3、4、5、6、7相对应。
唱名是唱歌时发出的音,即do、re、mi、fa、so、la、si。在首调唱名法中,do的位置和高度可以移动和变化,但各个调式音级却有着固定不变的唱名和全半音关系。
音值又称音符值、音符时值,用于描述各音符的相对持续时间,常见的有全音符、二分音符、四分音符、八分音符、十六分音符等,如表2.2所示。
表2.2 常见音符的标记方法和音值
歌曲《我和我的祖国》的简谱中,中音5、中音6、中音5、中音4、中音3、中音2的音值为0.5拍,中音1和低音5的音值为1.5拍,中音1、中音3、高音1、中音7的音值为0.5拍,中音6的音值为0.75拍,中音3的音值为0.25拍,中音5的音值为1.5拍,中音5的音值为1.5拍。因此简谱前4小节,音符的音值依次为0.5、0.5、0.5、0.5、0.5、0.5、1.5、1.5、0.5、0.5、0.5、0.5、0.75、0.25、1.5、1.5。
2.3.3 编程要点
1.语句tone(13,1000);与noTone(13);
语句tone(13,1000);表示使数字端口13产生1000Hz的电信号。
语句tone(13,tune[x]);表示使数字端口13产生tune[x]音符的电信号。比如:x=0,tune[0]=Z5=587,数字端口13产生587Hz的电信号,即中音5的电信号。再比如:x=1,tune[1]=Z6=659,数字端口13产生659Hz的电信号,即中音6的电信号。
语句tone(13,X0);//如X0=-1,即tone(13,-1),表示数字端口13停止产生电信号。
语句noTone(13);表示使数字端口13停止产生电信号。
2.语句#define X0 -1与#define D1 196
语句#define X0 -1用来定义休止符频率。
语句#define D1 196表示变量D1=196,这是G调低音1的振动频率。
语法:
在Arduino中,定义的常量不占用芯片上的程序内存空间,在编译时编译器事先将常量名替换成常量值。注:define前必须有#,常量名与常量值之间不能用等号,只能用空格,常量值后不能有分号,否则编译时将出现错误。
3.语句int tune[]={}
该语句用来定义整型变量数组tune,排列各音符的音高。歌曲《我和我的祖国》的简谱的前6个音符是中音5、6、5、4、3、2,因此排列的音调是Z5、Z6、Z5、Z4、Z3、Z2。
int是有符号整数数据类型,占用2字节的内存,取值范围为-32768~32767,即-215~215-1,当变量数值过大而超过整数类型所能表示的范围时(-32768~32767),变量值会“回滚”,即32767之后为-32768,然后是-32767……
unsigned int是无符号整型数据类型,占用4字节的内存,取值范围为0~4294967295(232-1)。
4.语句float duration[]={}
该语句用来定义单精度浮点变量数组duration,排列各音符的音值。歌曲《我和我的祖国》的简谱的前6个音值均为0.5拍,因此排列的音值是0.5、0.5、0.5、0.5、0.5、0.5。
float是单精度浮点型数据类型,即有小数点的数字,占用4字节的内存,取值范围为-3.4028235E+38~3.4028235E+38,有6~7位有效数字。注:6.0/3.0的结果可能不为2.0,且执行浮点运算的速度远远慢于执行整数运算的速度。
5.语句length=sizeof(tune)/sizeof(tune[0]);
该语句表示运用sizeof函数查询数组中音符的个数,将数组所占的内存总空间大小(字节数)除以单个元素所占的内存空间大小(字节数),就得到了数组的大小。
6.语句for(int x=0;x<length;x++){语句1;}
该语句为循环执行语句,从x=0开始,每循环一次,x=x+1,x<length时一直循环。如果length=10,那么语句1将循环执行10次;如果length=20,那么语句1将循环执行20次。
7.语句delay(750*duration[x]);
该语句表示延时duration[x]*750ms,比如:x=0,duration[0]=0.5,delay(750*duration[0])即delay(375),延时375ms。
2.3.4 程序设计
1.代码一
(1)程序参考
(2)实验结果
首先在AU03电路板上安装并焊接1206型贴片电阻(10Ω)、耳机插座、喇叭、2根排针,然后将电路板的排针插入Arduino Uno开发板上的GND和13插槽内。代码一上传成功后接通电源,喇叭将发出频率为1000Hz的声音,持续200ms,停止发声1800ms。如此循环。
2.代码二
(1)程序参考
(2)实验结果
通电后,喇叭播放歌曲《我和我的祖国》。
2.3.5 拓展和挑战
从网上搜索一首你喜爱的歌曲简谱,编程播放。