首页 > 代码库 > 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;}
测试通过,貌似听起来有几个音可能手误写错了,但是总体来说还是挺好玩的。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。