今年4月24日,是我国发射第一颗人造地球卫星——“东方红1号”,50周年的纪念日。读了许多纪念文章,耳边仿佛就响起“东方红”的乐曲。忽然想起多年前写过一个演奏乐曲的小程序,它读取经过简单翻译的简谱,然后利用PC机的扬声器演奏出乐曲来。演奏的第一个乐曲就是“东方红”。特地将程序放上来,纪念这个伟大的日子。
当时的想法有点奇怪,并不是直接读谱演奏,而是读谱以后生成另一个源程序,这个派生的源程序将音符和节拍,计算成音频和延时后直接写入代码中,然后才演奏。想不起当时为什么这样做,也许是为了分发最后生成的奏乐执行程序方便吧。现在原文照录。
读谱生成代码的程序:genmusic.cpp.
#include<stdio.h>
#include<string>
#include<windows.h>
using namespace std;
class Piccolo {
private:
int T; // basic duration
DWORD Hz[8];
FILE *sp; // file to read
FILE *tp; // file to write
void gennote(int hz,int i,int t)
/* 读简谱生成奏乐文件。 hz代表音符,i代表音调:0为低音,1为正常,2为高音。t代表节拍:1=0.25拍,2=0.5拍,3=0.75拍,4=1拍,以此类推。即t=节拍数x4 */
{
DWORD dhz,dur;
dhz=Hz[hz];
dur=60000/T/4*t; // 调整节拍的时长。
if (i==0) dhz=dhz/2; //低音
if (i==2) dhz=dhz*2; //高音
fprintf(tp," song.push_back(%d);\n",dhz);
fprintf(tp," song.push_back(%d);\n",dur);
printf(" Beep(%d,%d);\n",dhz,dur); // print to screen
}
public:
Piccolo(void)
{
/* 基本音符的频率 */
Hz[0]=0;
Hz[1]=1300;
Hz[2]=1463;
Hz[3]=1625;
Hz[4]=1733;
Hz[5]=1950;
Hz[6]=2167;
Hz[7]=2438;
}
void genmusic(string sn)
{
DWORD hz,t,x;
string sfn,tfn;
sfn=sn+".txt"; // 读入的简谱文件,每个音为一行:第一个为音符,第二为音调,第三为节拍。-1代表结束。
tfn=sn+".cpp"; // 产生的奏乐程序。根据简谱计算出频率和延时,产生Beep(hz,duration)函数
if (sp=fopen(sfn.c_str(),"r")) {
if (tp=fopen(tfn.c_str(),"w")) {
fscanf(sp,"%d",&T); // 首先读入的是节拍的时长。一般100毫秒为一个四分之一拍比较合适
cout<<T<<endl; //printf("%d\n",T);
fprintf(tp,"#include<stdio.h>\n"); // 写入奏乐程序的包含文件
fprintf(tp,"#include<vector>\n");<