📄 player.c
字号:
//------------------------------- 音乐简谱播放器-------------------------------------
/*奏乐程序使用说明
调用方式: sing fname [speed [times]]
文件名 速度(拍/分) 遍数
简谱文件格式:
第1行: 曲名 节拍 调号
第2行-- 乐谱 (空格,换行无意义,但不得插在一个"音描述"内部)
记号:
* 节拍,调号,小节分隔符,终止符,升音符,中音音高,休止符,附点,延长
符等 -- 按照常规.
* 音描述 --
[3连音符][升降还原符]音高[高低音后缀][音长][附点][延长符]
* 3连音符 -- ^ 只标在第1音前,音长只标在第3音后
(3连音的实际总音长为所标音长的两倍,例如:^323'的总音长为1拍)
* 降音符 -- @
* 还原符 -- $
* 高低音后缀 -- H(高音) U(高16度音) 连用音程相加
L(低音) W(低16度音)
* 音长 -- 无(1拍) '(1/2拍) "(1/4拍) 连用为相乘*/
//------------------------------------------------------------------------------------
#include"stdio.h"
#include"math.h"
#include"dos.h"
#define C 262
#define Max 100
//Var public
char Array[Max];
int ArrayLength=0;
int Rests=0;
int ThreeLegatoes=0;
double HalfAccent;
int TonalityVolue=0;
char Tonality[Max];
int UpAndDownArray[7];
int UpAndDownVolue=0;
int GetUpAndDown=0;
int Print=0;
//Get number of ch.
int IfNumber(char ch)
{
if(ch>='0'&&ch<='9')
{
return 1;
}
else
{
return 0;
}
}
//Get song messige.
int GetMessige(char Title[],int Metre[],char Tonality[],char ch)
{
int j;
if(ch!=' ')
{
if(ArrayLength!=-1)
{
Array[ArrayLength]=ch;
ArrayLength++;
}
else
{
if(ch=='\n')
{
printf("\nTitle:%s\nMetre:%d/%d\nTonality:%s\n",Title,Metre[0],Metre[1],Tonality);
return 1;
}
Tonality[TonalityVolue]=ch;
TonalityVolue++;
}
}
if(ArrayLength>1&&IfNumber(Array[ArrayLength-1])&&(Array[ArrayLength-2]=='/')&&IfNumber(Array[ArrayLength-3]))
{
for(j=0;j<ArrayLength-3;j++)
{
Title[j]=Array[j];
}
Title[j]='\0';
Metre[0]=Array[j]-48;
Metre[1]=Array[ArrayLength-1]-48;
ArrayLength=-1;
}
else if(ArrayLength>1&&IfNumber(Array[ArrayLength-1])&&(Array[ArrayLength-2]!='/')&&IfNumber(Array[ArrayLength-3]))
{
return ArrayLength;
}
return 0;
}
//Get up or down.
float UpAndDown(char ch)
{
if(ch=='#')
{
return HalfAccent;
}
else if(ch=='@')
{
return 1.0/HalfAccent;
}
return 1;
}
int Big(char ch)
{
if(ch>='A'&&ch<='Z')
{
return 1;
}
else if(ch>='a'&&ch<='z')
{
return -1;
}
return 0;
}
//To Metre Hz.
double ToHz(char ch)
{
int NoteNumber,NoteHz;
if(ch>='A'&&ch<='G')
{
NoteNumber=ch-'C';
}
else if(ch>='a'&&ch<='g')
{
NoteNumber=ch-'C'-32;
}
else
{
return C;
}
if(NoteNumber==4)
{
NoteHz=C*pow(HalfAccent,NoteNumber*2-1);
}
else if(NoteNumber<0)
{
NoteHz=C*pow(HalfAccent,NoteNumber*2+1);
}
else
{
NoteHz=C*pow(HalfAccent,NoteNumber*2);
}
if(Big(ch)==-1)
{
NoteHz*=2;
}
return NoteHz;
}
//Get the first Hz base on C.
double GetHz()
{
if(TonalityVolue==0)
{
printf("No tonality!");
getch();
exit(0);
}
if(TonalityVolue==1)
{
return ToHz(Tonality[0]);
}
else if(TonalityVolue==2)
{
if(IfNumber(Tonality[1]))
{
if(Big(Tonality[0])==1)
{
return ToHz(Tonality[0])/pow(2,Tonality[1]-48);
}
else if(Big(Tonality[0])==-1)
{
return ToHz(Tonality[0])*pow(2,Tonality[1]-48);
}
}
else
{
return UpAndDown(Tonality[0])*ToHz(Tonality[1]);
}
}
else if(TonalityVolue==3)
{
if(Big(Tonality[1])==1)
{
return UpAndDown(Tonality[0])*ToHz(Tonality[1])/pow(2,Tonality[2]-48);
}
else if(Big(Tonality[1])==-1)
{
return UpAndDown(Tonality[0])*ToHz(Tonality[1])*pow(2,Tonality[2]-48);
}
}
return C;
}
//Return note Hz.
double GetNoteHz(int Note)
{
if(Note>=4)
{
return GetHz()*pow(HalfAccent,((Note-1)*2-1));
}
else if(!Note)
{
return 0;
}
else
{
return GetHz()*pow(HalfAccent,((Note-1)*2));
}
}
//Get total Hz and return delay time.
double GetDelayTime(float *NoteHz,char Mark,float *ExtraDelayTime)
{
int i;
//Up and down:
if(Rests!=0)
{
UpAndDownArray[UpAndDownVolue]+=Rests;
Rests=0;
}
if(UpAndDownArray[UpAndDownVolue]&&(IfNumber(Mark)))
{
*NoteHz*=pow(HalfAccent,UpAndDownArray[UpAndDownVolue]);
}
//Hz part:
if(Mark=='#')
{
Rests=1;
}
else if(Mark=='@')
{
Rests=-1;
}
else if(Mark=='$'||Mark=='|')
{
for(i=0;i<7;i++)
{
UpAndDownArray[i]=0;
}
}
else if(Mark=='H')
{
*NoteHz*=2;
}
else if(Mark=='U')
{
*NoteHz*=4;
}
else if(Mark=='L')
{
*NoteHz/=2;
}
else if(Mark=='W')
{
*NoteHz/=4;
}
//Three legatoes:
if(ThreeLegatoes==1&&IfNumber(Mark))
{
ThreeLegatoes=2;
return 1/3.0;
}
//Delay part:
else if(Mark=='^')
{
ThreeLegatoes=1;
}
else if(ThreeLegatoes==2&&Mark=='\'')
{
ThreeLegatoes=0;
}
else if(ThreeLegatoes==0&&Mark=='\'')
{
return 1/2.0;
}
else if(Mark=='\"')
{
return 1/4.0;
}
else if(Mark=='-')
{
*ExtraDelayTime+=1;
}
else if(Mark=='.')
{
*ExtraDelayTime+=0.5;
}
return 1;
}
//Read file and 'sound'.
void Read(char FileName[],double speed)
{
int Note,NoteLength=0,GetMessigeTime=0,Metre[2],Zero=0;
float NoteHz=0,DelayTime=1,ExtraDelayTime=0,TotalDelayTime=0;
char ch,Title[Max];
FILE *fp;
if((fp=fopen(FileName,"r"))==NULL)
{
printf("Cannot open this file!\n");
getch();
exit(0);
}
while(!feof(fp))
{
ch=fgetc(fp);
//Messige part:
if(GetMessigeTime==1)
{
GetMessigeTime=-1;
}
else if((GetMessigeTime>1||feof(fp))&&GetMessigeTime!=-1)
{
printf("\nNo Metre.\n");
getch();
exit(0);
}
else if(GetMessigeTime==0)
{
GetMessigeTime=GetMessige(Title,Metre,Tonality,ch);
continue;
}
//Sound part:
if((ch>='0'&&ch<='7')||feof(fp))
{
Note=ch-48;
if(NoteLength)
{
if(Zero)
{
nosound();
Zero=0;
}
else
{
sound(NoteHz);
}
TotalDelayTime=DelayTime+ExtraDelayTime;
delay(TotalDelayTime*(60/speed)*1000*(4.0/Metre[1]));
//text NoteHz and TotalDelayTime:
if(Print)
{
printf("\n%.0f,%f\n",NoteHz,TotalDelayTime);
}
if(ThreeLegatoes!=2)
{
DelayTime=1;
}
ExtraDelayTime=0;
}
if(ch=='0')
{
Zero=1;
}
UpAndDownVolue=Note-1;
NoteHz=GetNoteHz(Note);
NoteLength++;
}
DelayTime*=GetDelayTime(&NoteHz,ch,&ExtraDelayTime);
}
nosound();
fclose(fp);
}
//String to Number.
double ToNumber(char *String)
{
int i,j;
double Number=0;
for(i=0;String[i]!='\0';i++)
{
String[i]-=48;
}
for(j=0;i>0;i--)
{
Number+=String[i-1]*pow(10,j);
j++;
}
return Number;
}
//by linfuqing N3070130124
void main(int Number,char *Admin[])
{
int i,j;
double time,speed;
char *FileName;
HalfAccent=exp(1.0/12*log(2));
//Initialization.
if(Number==1)
{
printf("Please write down your music file name!\n");
getch();
exit(0);
}
if(Number==2)
{
FileName=Admin[1];
speed=180;
time=1;
}
else if(Number==3)
{
FileName=Admin[1];
speed=ToNumber(Admin[2]);
time=1;
}
else if(Number==4)
{
FileName=Admin[1];
speed=ToNumber(Admin[2]);
time=ToNumber(Admin[3]);
}
else if(Number==5)
{
FileName=Admin[1];
speed=ToNumber(Admin[2]);
time=ToNumber(Admin[3]);
Print=1;
}
else
{
printf("Error!");
getch();
exit(0);
}
//now begin.
printf("\n-------------------------------[music player]------------------------------\n");
for(i=0;i<time;i++)
{
for(j=0;j<7;j++)
{
UpAndDownArray[j]=0;
}
TonalityVolue=0;
ArrayLength=0;
Rests=0;
ThreeLegatoes=0;
Read(FileName,speed);
}
printf("\n-----------------------------------[end]-----------------------------------\n");
getch();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -