有了WAV頭文件的格式,要生成一個WAV格式的聲音文件就比較簡單了,只要將頭文件輸出,在簡單生成一點內容就可以了。為了簡單,就生成一個單聲道,11025HZ的,長度一秒的聲音文件。
那么開做,要生成一個文件,那么文件的輸出流<fstream>肯定要用到,參考了一下資料,簡單整了如下的一個程序:
#include <iostream> #include<fstream> //文件輸出 #include<math.h> //主要生產波形使用SIN函數,所以弄了這個頭 using namespace std; float dou=256; //聲音dou的頻率264,這里為了湊整數用的256 HZ struct WavHead{ char RIFF[4]; //頭部分那個RIFF long int size0;//存的是后面所有文件大小 char WAVE[4]; char FMT[4]; long int size1;//存的是fmt保存的大小,包含這之后,data前面幾個,共16個 short int fmttag; short int channel; long int samplespersec;//每秒采樣數,用的是11025 long int bytepersec; short int blockalign; short int bitpersamples; char DATA[4]; long int size2;//剩下文件大小,也就是聲音采樣是大小,因為是一秒鍾的內容,那么就是11025了。 }; int main() { WavHead head={{'R','I','F','F'},0,{'W','A','V','E'},{'f','m','t',' '},16, 1,1,11025,11025,1,8,{'d','a','t','a'}, 0};//初始化,沒將聲音采樣文件大小賦值,后面修改 head.size0=11025+16+8; head.size2=11025; char body[head.size2];//打算將采樣數據放在這個里面 int i,i2;//為了聲音不是很單調,用了兩個循環,里面一層i是生成聲音函數,外面那層i2,是生成不同頻率的。 float a=(head.samplespersec/dou);//是dou持續時間(1/dou)除以采樣數(1/head.samplespersec),也就是一個dou的波形里有a個采樣點,這里是43。 for (i2=1;i2<=2;i2++){//這里弄了兩個聲音,一個是256HZ,一個是512HZ for(i=0+head.size2/2*(i2-1);i<head.size2/2*i2;i++){ body[i]=(int)(64*sin(6.28/a*i*i2)+128);//這個波用的是sina函數,以128(ox80)為中心的正弦波,實際上當采樣點是0x80的時候是靜音,大於則是正的,小於0X80則是負的,前面64則是聲音大小,等於128的時候,生成的聲音最大 } } ofstream ocout; ocout.open("123.wav",ios::out|ios::binary);//打開(不存在時生成)123.wav ocout.write((char*)&head,sizeof head);//將文件頭部分寫進文件 ocout.write((char*)&body,sizeof body);//將數據文件寫入程序 ocout.close();//關閉文件 cout <<head.samplespersec <<" "<<dou<< endl; // 調試的時候查看一下文件大小是否出錯 return 0; }
調試運行成功