一个演奏乐曲的趣味小程序

今年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");<
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值