ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2020-04-29 19:03:17  阅读:346  来源: 互联网

标签:乐曲 1300 600 song 300 back 演奏 push 趣味


今年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[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");
               fprintf(tp,"#include<windows.h>\n");
               fprintf(tp,"using namespace std;\n");
               fprintf(tp,"int main(void)\n{\n");
               fprintf(tp,"    vector<DWORD> song;\n");

               while(!feof(sp))
               {
                   fscanf(sp,"%d %d %d",&hz,&x,&t);
                   if(hz!=-1) {
                      cout<<hz<<' '<<x<<' '<<t<<endl; //printf("%d%c%d%c%d\n",hz,' ',x,' ',t);
                      gennote(hz,x,t); // 将每个音的音符、音调、节拍写入奏乐程序
                   }
                   else break;
               }
               fprintf(tp,"    for(size_t sz=song.size(), i=0; i!=sz; i+=2) {\n      for(int j=0;j<song[i+1];j+=100) printf(\"+\");\n      Beep(song[i],song[i+1]);\n      printf(\"\\n\");\n    }\n");
               fprintf(tp,"    return 0;\n}");
               fclose(sp);
               sp=NULL;
               fclose(tp);
               tp=NULL;
           }
           else cout<<"Error:file "+tfn+" cannot be created."<<endl; // 在当前目录没有建立文件的权限
       }
       else cout<<"Error: file "+sfn+" is not found."<<endl;  // 简谱文件不存在
    }
};

int main(void)
{
    Piccolo pic;
    pic.genmusic("dongfanghong");
    return 0;
}

简谱文件:dongfanghong.txt。第一行是节拍的时长。一般100毫秒为一个四分之一拍比较合适。跟着的就是简谱。每个音为一行:第一个为音符(1、2、3、4、5、6、7),第二为音调(0为低音,1为中音,2为高音),第三为节拍(1=0.25拍,2=0.5拍,3=0.75拍,4=1拍,以此类推)。-1代表结束。

100
5 1 4
2 1 4
1 1 4
7 0 2
6 0 2
5 0 4
5 1 4
2 1 4
3 1 2
2 1 2
1 1 4
1 1 2
6 0 2
2 1 2
3 1 2
2 1 2
1 1 2
2 1 2
1 1 2
7 0 2
6 0 2 
5 0 12
0 1 4
5 1 4
5 1 2
6 1 2
2 1 8
1 1 4
1 1 2
6 0 2
2 1 8
5 1 4
5 1 4
6 1 2
1 1 2
6 1 2
5 1 2
1 1 4
1 1 2
6 1 2
2 1 8
5 1 4
2 1 4
1 1 4
7 0 2
6 0 2
5 0 4
5 1 4
2 1 4
3 1 2
2 1 2
1 1 4
1 1 2
6 0 2
2 1 2
3 1 2
2 1 2
1 1 2
2 1 2
1 1 2
7 0 2
6 0 2
5 0 12
0 1 4
-1 -1 -1 

编译并运行这个genmusic.cpp,生成奏乐程序源文件:dongfanghong.cpp。

#include<stdio.h>
#include<vector>
#include<windows.h>
using namespace std;
int main(void)
{
    vector<DWORD> song;
    song.push_back(1950);
    song.push_back(600);
    song.push_back(1463);
    song.push_back(600);
    song.push_back(1300);
    song.push_back(600);
    song.push_back(1219);
    song.push_back(300);
    song.push_back(1083);
    song.push_back(300);
    song.push_back(975);
    song.push_back(600);
    song.push_back(1950);
    song.push_back(600);
    song.push_back(1463);
    song.push_back(600);
    song.push_back(1625);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(300);
    song.push_back(1300);
    song.push_back(600);
    song.push_back(1300);
    song.push_back(300);
    song.push_back(1083);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(300);
    song.push_back(1625);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(300);
    song.push_back(1300);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(300);
    song.push_back(1300);
    song.push_back(300);
    song.push_back(1219);
    song.push_back(300);
    song.push_back(1083);
    song.push_back(300);
    song.push_back(975);
    song.push_back(1800);
    song.push_back(4200400);
    song.push_back(600);
    song.push_back(1950);
    song.push_back(600);
    song.push_back(1950);
    song.push_back(300);
    song.push_back(2167);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(1200);
    song.push_back(1300);
    song.push_back(600);
    song.push_back(1300);
    song.push_back(300);
    song.push_back(1083);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(1200);
    song.push_back(1950);
    song.push_back(600);
    song.push_back(1950);
    song.push_back(600);
    song.push_back(2167);
    song.push_back(300);
    song.push_back(1300);
    song.push_back(300);
    song.push_back(2167);
    song.push_back(300);
    song.push_back(1950);
    song.push_back(300);
    song.push_back(1300);
    song.push_back(600);
    song.push_back(1300);
    song.push_back(300);
    song.push_back(2167);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(1200);
    song.push_back(1950);
    song.push_back(600);
    song.push_back(1463);
    song.push_back(600);
    song.push_back(1300);
    song.push_back(600);
    song.push_back(1219);
    song.push_back(300);
    song.push_back(1083);
    song.push_back(300);
    song.push_back(975);
    song.push_back(600);
    song.push_back(1950);
    song.push_back(600);
    song.push_back(1463);
    song.push_back(600);
    song.push_back(1625);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(300);
    song.push_back(1300);
    song.push_back(600);
    song.push_back(1300);
    song.push_back(300);
    song.push_back(1083);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(300);
    song.push_back(1625);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(300);
    song.push_back(1300);
    song.push_back(300);
    song.push_back(1463);
    song.push_back(300);
    song.push_back(1300);
    song.push_back(300);
    song.push_back(1219);
    song.push_back(300);
    song.push_back(1083);
    song.push_back(300);
    song.push_back(975);
    song.push_back(1800);
    song.push_back(4200400);
    song.push_back(600);
    for(size_t sz=song.size(), i=0; i!=sz; i+=2) {
      for(int j=0;j<song[i+1];j+=100) printf("+");
      Beep(song[i],song[i+1]);
      printf("\n");
    }
    return 0;
}

编译,运行这个dongfanghong.cpp程序,“东方红”的乐曲就奏响了!

标签:乐曲,1300,600,song,300,back,演奏,push,趣味
来源: https://blog.csdn.net/yang_deyuan/article/details/105813047

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有