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; }
测试通过,貌似听起来有几个音可能手误写错了,但是总体来说还是挺好玩的。