二、实验目的及要求
培养上机动手能力,巩固分支结构、循环结构、函数调用以及文件操作。练习利用学过的知识设计出具有个性化的程序来。
要求:利用C语言中的Beep()函数,或驱动声卡发声的各种API函数,来编写简单的音乐播放软件,增加C语言编程的趣味性。本次实验要求每个学生各选择自已喜欢的一首歌曲作为程序的曲谱文件,并对该曲谱文件进行数字化,然后编写出播放该歌曲的音乐程序。
三、涉及的内容或知识点
编码、数组、函数、文件等知识;
例如:在TC环境下可以用sound()、nosound()、delay()等函数驱动PC喇叭发声,在VC环境下,PC喇叭音频可以用Beep()函数来实现,其中Beep()的用法为:void Beep(unsigned frequency, unsigned milliseconds);功能是以打开PC扬声器发出指定频率的声响,并延时一定时间。参数frequency是一个无符号整数,代表的是发声的频率。milliseconds参数也是一个无符号类型的参数,代表是延时的时间长度,其单位是毫秒。
也可以参考有关驱动声卡的API函数,通过声卡设计出更加优美的音乐。
四、设计思路
1.曲调的编码
音乐演奏的关键是曲调(发声的频率)的定义与识别及发音时间(节拍)的控制。为了实现计算机自动识谱,可定义一套曲调的编码规则。
例:
基本延时:单位是毫秒(例100),其他音符的延时是该基本延时的倍数。
音符码:字符 1,2 ,3 ,4,5,6,7分别表示音符do re mi fa so la xi(c d e f g a b);
高音码:H代表高音,M代表中音,L代表底音。
节拍码:
1表示1/16拍,是基本延时的1倍;
2表示1/8拍,是基本延时的2倍;
4表示1/4拍,是基本延时的4倍;
8表示1/2拍,是基本延时的8倍;
16表示1拍,是基本延时的16倍;
32表示2拍,是基本延时的32倍,以此类推。
例在一组编码5M16中:
5代表音符的so;
M代表中音;
16代表1拍,是基本延时的16倍。
2.乐谱文件
按编码规则用记事本编辑乐曲,然后保存到程序的目录下,乐谱文件供程序调用。乐谱文件的第一个数字是基本延时(毫秒),末尾以-1#-1来代表文件结束。
例如:mymusic.txt
100 1M8 2M8 3M8 4M8 5M16 6M8 7M8 1H8 6M8 5M16 -1#-1
3.自动识谱程序
(1) 读乐谱文件
输入乐谱文件(FileName),读入基本延时(rate)、音符码frequency[i]、高音码note[i]和节拍码time[i]:
/*-------------------------------------*/
if((f1=fopen(FileName,"r"))==NULL)
{
printf("不能打开文件!\n");
exit(1);
}
fscanf(f1,"%d",&rate);
flag=0; i=0;
while(!feof(f1)&&flag!=1)
{
fscanf(f1," %d %c%d",&sound,&hight,&t);
if(t!=-1)
{
frequency[i]=sound;
note[i]= hight;
time[i]=t;
i++;
}
else
flag=1;
}
/*-------------------------------------*/
(2) 合成频率和节拍
对照音符与频率关系表(中音符的频率近似是低符的频率的2倍,高音符的频率近似是低符的频率的4倍)和曲调的编码规则,用swich语句把音符码和高音码合成频率frequency ,节拍和基本延时合成延时milliseconds。
(3)用Beep()函数来实现PC喇叭音频。
其中Beep()的用法为:
void Beep(unsigned frequency, unsigned milliseconds);
功能是以打开PC扬声器发出指定频率的声响,并延时一定时间。参数frequency是一个无符号整数,代表的是发声的频率。milliseconds参数也是一个无符号类型的参数,代表是延时的时间长度,其单位是毫秒。