首页 > 代码库 > C++生成简单WAV文件(三)——根据简谱生成菊花台

C++生成简单WAV文件(三)——根据简谱生成菊花台

上一次已经可以生成随机的音乐,要从单调的声音变成音乐,最简单的是模仿,那么先根据菊花台的简谱整一个吧。简谱是网上找的。为了简单,乐曲只生成中间一段。

 

写头文件没变,依然是:Head.h,Head.cpp,因为不需要随机产生音符,那么随机数那个就不用了。

 

Head.h:

#ifndef HEAD_H_#define HEAD_H_class Head{public:    Head();    void setsize(int);    long int getsa();    long int getsize();    ~Head();private:     char RIFF[4];     long int size0;     char WAVE[4];     char FMT[4];     long int size1;     short int fmttag;     short int channel;     long int samplespersec;     long int bytepersec;     short int blockalign;     short int bitpersamples;     char DATA[4];     long int size2;};#endif /* HEAD_H_ */

Head.cpp:

#include "Head.h"#include<iostream>using namespace std;Head::Head(){    strcpy(RIFF,"RIFF");    size0=0;    strcpy(WAVE,"WAVE");    strcpy(FMT,"fmt ");    size1=16;    fmttag=1;    channel=1;    samplespersec=11025;    bytepersec=11025;    blockalign=1;    bitpersamples=8;    strcpy(DATA,"data");    size2=0;    cout<<RIFF<<size0<<WAVE<<endl;}Head::~Head(){    cout<<123<<endl;}void Head::setsize(int size){    Head::size0=size+24;    Head::size2=size;}long int Head::getsa(){    return Head::samplespersec;}long int Head::getsize(){    return Head::size2;}

最后是MAIN:其中L[8],N[8],H[8],I[8]存的是不同音的频率。jiepai存的就是数据了。声音波形还是用的正弦波,其中每个节拍里声音轻重也是整了个正弦函数,这个比较简单,实际上不同乐器的差别在每个节拍里的函数肯定是差别很大的。还没细想过。

#include <iostream>#include<fstream>#include"Head.h"#include<math.h>#include"R.h"using namespace std;//L1   131     L2   147     L3   165     L4   175     L5   196     L6   220     L7   247//N1   262     N2   296     N3   330     N4   349     N5   392     N6   440     N7   494//H1   523     H2   587     H3   659     H4   698     H5   784     H6   880     H7   988//I1   1047     I2   1175     I3   1319     I4   1397     I5   1568     I6   1760     I7   1976int L[8]={0,131,147,165,175,196,220,247};int N[8]={0,262,296,330,349,392,440,494};int H[8]={0,523,587,659,698,784,880,988};int I[8]={0,1047,1175,1319,1397,1568,1760,1979};int pai=11025/4;int jiepai[80][2]={{N[3],4},{N[3],2},{N[2],2},{N[3],4},{N[0],4},{N[3],2},{N[5],2},                   {N[3],2},{N[2],2},{N[3],8},{N[1],4},{N[1],2},{N[2],2},{N[3],2},                   {N[5],2},{N[3],4},{N[2],4},{N[2],2},{N[1],2},{N[2],8},{N[3],6},                   {N[5],1},{N[3],1},{N[6],2},{N[5],6},{N[6],2},{N[5],2},{N[5],2},                   {N[3],2},{N[5],6},{L[5],5},{N[3],4},{N[2],2},{N[2],2},{N[5],4},                   {N[3],2},{N[2],2},{N[2],4},{N[1],4},{N[2],8},{N[3],4},{N[3],2},                   {N[2],2},{N[3],8},{N[3],2},{N[5],2},{N[3],2},{N[3],2},{N[3],8},                   {N[1],4},{N[1],2},{N[2],2},{N[3],2},{N[5],2},{N[3],4},{N[2],4},                   {N[2],2},{N[2],1},{N[2],8},{N[3],6},{N[5],1},{N[3],1},{N[6],1},                   {N[5],6},{N[6],2},{N[5],2},{N[5],2},{N[3],2},{N[5],8},{N[0],2},                   {N[3],2},{N[2],2},{N[3],2},{N[3],4},{N[5],4},{N[3],2},{N[2],2},                   {N[2],2},{N[1],7},{N[0],8}};void runrun(){        cout<<jiepai[3][1]<<endl;        Head head;        int i,i2,i3;         float a=0;        i3=0;        int size=0;        for(i=0;i<80;i++){            size+=jiepai[i][1];        }        head.setsize(size*pai);//将数据文件大小放进WAV头里面        cout<<head.getsize()<<endl;        char body[head.getsize()];//同时将WAV的数据大小确认        for(i2=0;i2<80;i2++)        {            if(jiepai[i2][0]!=0){            a=(11025/(jiepai[i2][0]));};            for(i=0;i<jiepai[i2][1]*pai;i++){                    if(jiepai[i2][0]!=0){                    body[i+i3]=(int)(64*sin(6.28/a*i)*(sin(3.14*i/pai/jiepai[i2][1]))+128);}                    else{                        body[i+i3]=128;                    };            }            i3+=jiepai[i2][1]*pai;            cout<<a<<" "<<i3<<endl;        }        ofstream ocout;        ocout.open("1213.wav",ios::out|ios::binary);        ocout.write((char*)&head,sizeof head);        ocout.write((char*)&body,sizeof body);        ocout.close();//        cout <<head.getsize() <<" "<<dou[0]<<endl;}int main() {    runrun();    return 0;}

测试通过,貌似听起来有几个音可能手误写错了,但是总体来说还是挺好玩的。