第三讲让你的程序声图并茂Word文件下载.docx
《第三讲让你的程序声图并茂Word文件下载.docx》由会员分享,可在线阅读,更多相关《第三讲让你的程序声图并茂Word文件下载.docx(24页珍藏版)》请在冰豆网上搜索。
![第三讲让你的程序声图并茂Word文件下载.docx](https://file1.bdocx.com/fileroot1/2023-2/4/41bf0509-9fe9-4e1d-8eed-ebcbc446c4c7/41bf0509-9fe9-4e1d-8eed-ebcbc446c4c71.gif)
,&
snd);
/*iftheanswerittoexit,doso.*/
if(snd==0)
break;
/*Askhowmanytimestorepastthesound.*/
Nungeroftimes:
"
/*gettheanswer*/
scanf("
cnt);
/*repeatthesoundthenumberoftimespecifed*/
while(cnt--){
/*swichontypeofsoundtoproduce*/
switch(snd)
{case1:
/*doasiren:
sweepup*/
for(note=1000;
note>
150;
note-=10)
sound(note);
delay(20);
}
/*Sweepdown*/
for(;
note<
1000;
note+=10)
delay(20);
break;
case2:
/*doanoverload.sweepup*/
for(note=4000;
10;
delay(70);
case3:
/*doawhoop:
Sweepup*/
for(note=1000;
{
sound(note);
delay(200);
case4:
/*doaphaser:
sweepdown*/
for(note=60;
note<
2000;
note+=10)
sound(note);
delay(100);
default:
/*unknown,askagain*/
printf("
Invalidentry;
tryagain\n"
break;
请大家打开TC运行该代码,程序重复的询问用户要产生哪一种声音。
C语言调用两个库函数使PC发出声音:
sound()打开声音;
nosound()关闭声音。
他们包含在dos.h中,格式如下:
voidsound(unsignedintfrequency);
voidnosound(void);
其中frequency为频率,单位Hz。
为了使声音持续一段时间,我们还常用delay()函数,格式如下:
voiddelay(unsignedintmilliseconde);
其中milliseconde表示所需延时的时间。
下面这个例子将不断发出各种频率的声音:
stdio.h>
stdlib.h>
time.h>
inti,j;
randomize();
while(!
bioskey
(1))
i=rand()*5000;
sound(i);
delay(10);
nosound();
前台音乐设计
首先我们来看下面这个例子,演奏的是《好人一生平安》
#defineN164
#defineN232
#defineN416
#defineN88
#defineN164
#defineEND0
enumNOTES
C10=131,D10=147,E10=165,F10=175,G10=196,A10=220,B10=247,
C0=262,D0=296,E0=330,F0=349,G0=392,A0=440,B0=494,
C1=525,D1=587,E1=659,F1=698,G1=784,A1=880,B1=988,
C2=1047,D2=1175,E2=1319,F2=1397,G2=1568,A2=1760,B2=1796
}song[]={
D0,N4,E0,N8,D0,N8,C0,N4,A10,N4,G10,N8,E10,N8,G10,N8,A10,
N8,C0,N2,A10,N4,A10,N8,C0,N8,G10,N8,A0,N8,E0,N8,G0,N8,
D0,N2,E0,N4,D0,N8,E0,N8,G0,N4,E0,N4,G10,N8,E10,N8,G10,
N8,A10,N8,C0,N2,A10,N4,A10,N8,C0,N8,A10,N8,A10,N8,D10,
N8,E10,N8,G10,N2,D0,N4,D0,N4,G0,N4,A0,N8,G0,N8,F0,N2,G0,
N2,A0,N4,G0,N8,E0,N8,D0,N8,E0,N8,C0,N8,A10,N8,D0,N2,E0,
N4,G0,N8,E0,N8,G0,N4,E0,N4,G10,N8,E10,N8,G10,N8,A10,N8,
C0,N4,A10,N4,A10,N8,C0,N8,D0,N8,A10,N8,C0,N8,E0,N8,D0,
N1,END,END};
main()
intnote=0,fre,dur,control;
clock_tgoal;
while(song[note]!
=0)
{
fre=song[note];
dur=song[note+1];
if(kbhit())break;
if(fre)
outportb(0x43,0xb6);
fre=(unsigned)(1193180L/fre);
outportb(0x42,(char)fre);
outportb(0x42,(char)(fre>
>
8));
control=inportb(0x61);
outportb(0x61,(control)|0x3);
}
goal=(clock_t)dur+clock();
while(goal>
clock());
outportb(0x61,control);
goal=(clock_t)0;
note=note+2;
}
音乐是时间的艺术,即把各种音符按不同的时值演奏出来,就可以构成曲调。
因此,音乐程序设计中的两个重要因素是:
如何用“曲调定义语言”来表示音符(即音高);
如何控制音符的持续时间(即音长)。
解决了这两个问题之后,剩下的就是如何用c语言控制计算机的扬声器发声。
下面我们详细的讲解一下。
(1)音符及音长的定义
音调由音符构成,音调的高低由音符频率决定,频率越高,音调也越高。
音乐中使用的频率一般为131~1976HZ,它包括了中央C调及其前后的4个8度的音程。
用c语言中的枚举类型常量可定义上述表中的各音符的频率。
如果音乐中有比表中的音符更高的音调,则可根据表上的有关值推出,如高8度的C,D和E的频率分别为2091,2350和2638,还需作适当的调整。
EnumNOTES
C10=131,DlO=147,ElO=165,FlO=175,GlO=196,A10=220,B10=247.
CO=262,DO=294,EO=330,FO=349,GO=392,AO=440,BO=494,
C1=523,Dl=587,EI=659,Fl=698,G1=784,A1=880,B1=988,
C2=1047,D2=1175,E2=1319,F2=1397,G2=1568,A2=1760,B2=1976
音长即一个音符的持续题意。
在乐曲中,音长用全音符、半音符、4分音符……来表示,通常以4分音符一拍,等等。
音长可用下面定义:
#defineN132
#defineN216
#defineN48
#defineN84
#defineN162
#defineEND0
如果感觉计算机所演奏的乐曲速度过快,可以适当调整上面的值。
(2)用C语言定义音乐
NOTES类型中各音调对应的简谱如下:
上面的乐谱共有10个音符,其音高和音长如下:
(3)如何控制扬声器
如何控制扬声器发生,则可用TurboC中的库函数中outportb(intport,charbyte),函数的原型在”dos.h”文件中,port为端口地址,byte为传送给端口的字节。
扬声器的端也址为0x42,下面的程序中主要是发声的频率。
另外,还需要使发声延迟,就要用到”clock_t”,类型变量goal和clock()库函数,变量和程序的原型在”time.h”文件中,使扬声器发声的步骤为:
①初始化端口0x42;
②向端口0x42传送声频率fre;
延迟:
当goal>
clock()时,做循环。
后台音乐设计
后台音乐设计主要是程序的背景声音,看下面的例子:
graphics.h>
fcntl.h>
voidinterrupt(*handler)();
voidinterruptmusic();
inthandle,control;
C10=131,D10=147,E10=165,F10=175,G10=196,A10=220,B10=247,
C0=262,D0=296,E0=330,F0=349,G0=392,A0=440,B0=494,
C1=523,D1=587,E1=659,F1=698,G1=784,A1=880,B1=988,
C2=1047,D2=1175,E2=1319,F2=1397,G2=1568,A2=1760,B2=1796
E1,N4,E1,N8,E1,N8,F1,N4,G1,N4,F1,N4,F1,N4,E1,N4,D1,
N4,C1,N4,C1,N4,D1,N4,E1,N4,E1,N4,D1,N4,D1,N4,E1,N4,
E1,N8,E1,N8,F1,N4,G1,N4,G1,N4,F1,N4,E1,N4,D1,N4,C1,
N4,C1,N4,D1,N4,E1,N4,D1,N4,D1,N4,C1,N4,D1,N4,D1,N8,
D1,N8,E1,N4,C1,N4,D1,N4,E1,N8,F1,N8,E1,N4,C1,N4,D1,
N4,E1,N8,F1,N8,E1,N4,C1,N4,C1,N4,D1,N4,G0,N4,E1,N4,
E1,N4,E1,N8,F1,N4,G1,N4,G1,N4,F1,N4,E1,N4,D1,N4,C1,
N4,C1,N4,D1,N4,E1,N4,E1,N4,D1,N4,C1,N4,D1,N4,
END,END
};
intgdriver=VGA,gmode=1,i;
initgraph(&
gdriver,&
gmode,"
"
handler=getvect(0x1c);
setvect(0x1c,music);
cleardevice();
setbkcolor(BLUE);
setcolor(YELLOW);
setfillstyle(SOLID_FILL,RED);
sector(200,150,50,120,70,50);
bar3d(400,150,500,200,10,5);
setactivepage
(1);
sector(200,150,50,170,70,50);
bar3d(400,200,500,250,10,5);
for(i=0;
i<
100;
i++)
while(kbhit())gotoend;
setvisualpage
(1);
delay((100-i)*10);
setvisualpage(0);
delay((100-i)*10);
end:
;
outportb(0x61,control&
0xfe);
setvect(0x1c,handler);
cleardevice();
closegraph();
voidinterruptmusic()
staticintflag=0,note=0,fre,dur=8;
flag++;
if(/*flag>
(int)dur*2/5*/fre)
flag=0;
note=note+2;
if(note>
=134)note=0;
handler();
乐谱文件的制作
我们在这里使用的乐谱文件格式如下:
最高音的前面加”*”;
高音,在每个音的前面加”h”;
中音,在每个音的前面加”m”;
低音,在每个音的前面加”L”。
“*”、“h”、“m”、“L”与其控制的音符构成音高,决定发声频率。
音高的后面是音长,可用整数或小数输入,以控制延时,但中间必须用空格分开。
乐谱文件的最前端是一个整数,表示音长基数,一般为300、600、900、1200。
乐谱文件的最末端是乐谱文件结束符”##”,以表示乐谱文件结束。
下面是电影《<
城南旧事》插曲《送别》的一段。
乐谱文件为:
600m51m30.5m50.5hl2m61hl0.5m60.5m52m5Iml0.5m20.5m31m20.5ml0.5m23##
每个音的音长=音长基数*节拍数,其中,音长基数是乐谱文件的第一个字符,如上面乐谱文件为600,每个音的音频可用一摸拟频率值输入。
下面是程序源代码、编译、连接成可执行文件music.exe,用法为:
music乐谱文件。
conio.h>
voidmain(intargc,char*argv[])
FILE*fp;
intrate;
charsound_high[3];
floatsound_long;
registerinti=0,j;
intsign=0;
floatstr[100][2];
if(argc!
=2)/*命令行参数个数不正确*/{
printf("
PararnetersErrors!
\n"
);
exit
(1);
if((fp=fopen(argv[1],"
r"
))==NULL)/* 文件打开失败*/
openfilemusic,docErrors!
);
exit
(1);
fscanf(fp,"
&
rate);
/*读取音长基数的值 */
feof(fp)&
&
!
sign)/*文件没有结束并且数据还是乐谱*/
fscanf(fp,"
%s%f"
sound_high,&
sound_long);
/*得到音频、音长的数值*/
str[i][1]=rate*sound_long;
/* 音乐=音长基数*节拍数*/
switch(sound_high[0]){
case'
*'
:
/*最高音*/
switch(sound_high[1]){/*确定发音的频率*/
1'
str[i++][0]=1046.5;
2'
str[i++][0]=1174.7;
3'
str[i++][0]=1318.5;
4'
str[i++][0]=1396.9;
brcak:
5'
str[i++][0]=1568;
6'
str[i++][0]=1760;
7'
str[i++][0]=1975.5;
default:
printf("
\nErrorsinmusic.doc\n"
exit
(1);
case'
h'
/*高音*/
switch(sound_high[1]){
str[i++][0]=523.3;
str[i++][0]=587.3;
str[i++][0]=659.3;
str[i++][0]=698.5;
str[i++][0]=784.0;
str[i++][0]=880;
str[i++][0]=987.8;
\nErrorsinmusic.doc\n"
m'
/*中音*/
switch(sound_high[1]){
str[i++][0]=262;
str[i++][0]=296;
str[i++][0]=329.6;
str[i++][0]=349.2;
str[i++][0]=392;
str[i++][0]=440;
str[i++][0]=493.9;
printf("
l'
/*低音*/
str[i++][0]=131;
str[i++][0]=147;
str[i++][0]=165;
str[i++][0]=176;
str[i++][0]=196;
str[i++][0]=220;
str[i++][0]=247;
printf("
#'
if(sound_high[1]=='
)sign=1;
exit
(1);
for(j=0;
j<
i;
j++)
sound(str[j][0]);
/*按频率值发出歌曲的音调*/
delay(str[j][1]);
/*关闭扬声器*/
声图并茂
我们来看下面这个程序的源代码,实现的是一个表盘的走动,并且发出响声,整点还有报时功能。
math.h>
#defineCENTERX320/*表盘中心位置*/
#defineCENTERY175
#defineCLICK100/*喀嗒声频率*/
#defineCLICKDELAY30/*喀嗒声延时*/
#defineHEBEEP10000/*高声频率*/
#defineLOWBEEP500/*低声频率*/
#defineBEEPDELAY200/*报时声延时*/
/*表盘刻度形状*/
intMrk_1[8]={-5,-160,5,-160,5,-130,-5,-130,};
intMrk_2[8]={-5,-160,5,-160,2,-130,-2-130,};
/*时针形状*/
intHourHand[