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   1976
int 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;
}

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

原文地址:https://www.cnblogs.com/shibuliao/p/3819803.html