9.3 音響技巧
9.3.1 音樂(lè)程序設(shè)計(jì)
我們知道,音樂(lè)是音高和音長(zhǎng)的有序組合,設(shè)計(jì)微機(jī)音樂(lè)最重要的就是如何定義音高和音長(zhǎng),以及如何讓揚(yáng)聲器發(fā)出指定的音符。下面給出音符與頻率的關(guān)系表。C語(yǔ)言提供的三個(gè)函數(shù)sound( )、nosound( )和clock( )可以很方便地解決上述的問(wèn)題。sound( )函數(shù)可以用指定頻率打開(kāi)PC機(jī)揚(yáng)聲器直到用nosound( )函數(shù)來(lái)關(guān)閉它; clock( )函數(shù)正好用來(lái)控制發(fā)聲時(shí)間,而且它不受PC機(jī)主頻高低的影響。下面這段程序可使微機(jī)發(fā)出c調(diào)1的聲音。
表9-2 音符與頻率關(guān)系表
音符 c d e f g a b
1 2 3 4 5 6 7
頻率 262 294 330 349 392 440 494
音符 c d e f g a b
1 2 3 4 5 6 7
頻率 523 587 659 698 784 880 988
音符 c d e f g a b
1 2 3 4 5 6 7
頻率 1047 1175 1319 1397 2568 1760 1976
[例9-12] 音樂(lè)程序music1.c
#include
#include
void pause(int);
void sound1(int,int);
void main(void)
{
int i,freq,speed=5;
int time=4*speed;
char *qm="iddgwwwqqgfff dddfghhhggg ddgwwwqqgfff\
ddffhjqqqqq wpggjhgddgqq hhqwwqjjjggg\
ddgwwwqqqgfff ddffhjqqqqqq";/*定義歌曲*/
while (*qm++ !='\0'){
i=1;
switch(*qm){
case 'k':
time=1*speed; i=0;
break;
case 'i':
time=6*speed; i=0;
break;
case 'o':
time=10*speed; i=0;
break;
case 'p':
pause(time); i=0;
break;
case 'a':
freq=523;
break;
case 's':
freq=587;
break;
case 'd':
freq=659;
break;
case 'f':
freq=698;
break;
case 'g':
freq=784;
break;
case 'h':
freq=880;
break;
case 'j':
freq=988;
break;
case 'z':
freq=262;
break;
case 'X':
freq=294;
break;
case 'c':
freq=330;
break;
case 'v':
freq=349;
break;
case 'b':
freq=392;
break;
case 'n':
freq=440;
break;
case 'm':
freq=494;
break;
case 'q':
freq=1047;
break;
case 'w':
freq=1175;
break;
case 'e':
freq=1319;
break;
case 'r':
freq=1397;
break;
case 't':
freq=2568;
break;
case 'y':
freq=1760;
break;
case 'u':
freq=1976;
break;
default:
i=0;
break;
}
if(i)
sound1(freq,time);
}
}
void sound1(int freq,int time) /*freq為頻率,time為持續(xù)時(shí)間*/
{
union{
long divisor;
unsigned char c[2];
}count;
unsigned char ch;
count.divisor=1193280/freq; /* 1193280 是系統(tǒng)時(shí)鐘速率*/
outp(67,182);
outp(66,count.c[0]);
outp(66,count.c[1]);
ch=inp(97);
outp(97,ch|3);
pause(time);
outp(97,ch);
}
void pause(int time)
{
int t1,t2;
union REGS in,out;
in.h.ah=0X2c;
int86(0X21,&in,&out); /* 取當(dāng)前時(shí)間*/
t1=t2=100*out.h.dh+out.h.dl; /*out.h.dh 為秒值,out.h.dl 為1/100 秒值*/
while(t2-t1
9.3.1 音樂(lè)程序設(shè)計(jì)
我們知道,音樂(lè)是音高和音長(zhǎng)的有序組合,設(shè)計(jì)微機(jī)音樂(lè)最重要的就是如何定義音高和音長(zhǎng),以及如何讓揚(yáng)聲器發(fā)出指定的音符。下面給出音符與頻率的關(guān)系表。C語(yǔ)言提供的三個(gè)函數(shù)sound( )、nosound( )和clock( )可以很方便地解決上述的問(wèn)題。sound( )函數(shù)可以用指定頻率打開(kāi)PC機(jī)揚(yáng)聲器直到用nosound( )函數(shù)來(lái)關(guān)閉它; clock( )函數(shù)正好用來(lái)控制發(fā)聲時(shí)間,而且它不受PC機(jī)主頻高低的影響。下面這段程序可使微機(jī)發(fā)出c調(diào)1的聲音。
表9-2 音符與頻率關(guān)系表
音符 c d e f g a b
1 2 3 4 5 6 7
頻率 262 294 330 349 392 440 494
音符 c d e f g a b
1 2 3 4 5 6 7
頻率 523 587 659 698 784 880 988
音符 c d e f g a b
1 2 3 4 5 6 7
頻率 1047 1175 1319 1397 2568 1760 1976
[例9-12] 音樂(lè)程序music1.c
#include
#include
void pause(int);
void sound1(int,int);
void main(void)
{
int i,freq,speed=5;
int time=4*speed;
char *qm="iddgwwwqqgfff dddfghhhggg ddgwwwqqgfff\
ddffhjqqqqq wpggjhgddgqq hhqwwqjjjggg\
ddgwwwqqqgfff ddffhjqqqqqq";/*定義歌曲*/
while (*qm++ !='\0'){
i=1;
switch(*qm){
case 'k':
time=1*speed; i=0;
break;
case 'i':
time=6*speed; i=0;
break;
case 'o':
time=10*speed; i=0;
break;
case 'p':
pause(time); i=0;
break;
case 'a':
freq=523;
break;
case 's':
freq=587;
break;
case 'd':
freq=659;
break;
case 'f':
freq=698;
break;
case 'g':
freq=784;
break;
case 'h':
freq=880;
break;
case 'j':
freq=988;
break;
case 'z':
freq=262;
break;
case 'X':
freq=294;
break;
case 'c':
freq=330;
break;
case 'v':
freq=349;
break;
case 'b':
freq=392;
break;
case 'n':
freq=440;
break;
case 'm':
freq=494;
break;
case 'q':
freq=1047;
break;
case 'w':
freq=1175;
break;
case 'e':
freq=1319;
break;
case 'r':
freq=1397;
break;
case 't':
freq=2568;
break;
case 'y':
freq=1760;
break;
case 'u':
freq=1976;
break;
default:
i=0;
break;
}
if(i)
sound1(freq,time);
}
}
void sound1(int freq,int time) /*freq為頻率,time為持續(xù)時(shí)間*/
{
union{
long divisor;
unsigned char c[2];
}count;
unsigned char ch;
count.divisor=1193280/freq; /* 1193280 是系統(tǒng)時(shí)鐘速率*/
outp(67,182);
outp(66,count.c[0]);
outp(66,count.c[1]);
ch=inp(97);
outp(97,ch|3);
pause(time);
outp(97,ch);
}
void pause(int time)
{
int t1,t2;
union REGS in,out;
in.h.ah=0X2c;
int86(0X21,&in,&out); /* 取當(dāng)前時(shí)間*/
t1=t2=100*out.h.dh+out.h.dl; /*out.h.dh 為秒值,out.h.dl 為1/100 秒值*/
while(t2-t1