首页 > 代码库 > 调用CImg库显示WAV格式音频波形
调用CImg库显示WAV格式音频波形
在做傅里叶变换和小波变换时经常要通过显示波形来检验算法,但通过visual studio之类显示波形又显得麻烦,而且不能跨平台。
CImg是一个跨平台的C++的图像处理库,提供的图像处理等功能十分强大,而且加入项目中十分轻便,只需将头文件包含在项目中即可,十分轻便。
可自行到http://www.cimg.eu/下载
利用它来在linux、Mac OS X中显示波形,再合适不过了,下面是音频波形显示的代码。
主函数
main.cpp
#include <iostream>#include "wavfile.h"#include "CImg.h"using namespace std;using namespace cimg_library;using namespace AudioUtils;int main(void){ WaveFile *wf=new WaveFile(); /* 读取本目录里的audio.wav文件,并生成波形 */ wf->readwav("audio.wav"); int datalength=wf->size()/wf->bit(); wf->output_WAVfile_info(); int *data=http://www.mamicode.com/(int*)malloc(sizeof(int)*datalength); for(int i=0;i<datalength;i++) { data[i]=(float)(wf->data[i]/100); } /* 调用CImg显示波形 */ const unsigned char red[] = { 255, 0, 0 }, yellow[] = { 255, 255, 0 }, green[] = { 0, 255, 0 }; /* 一维信号 */ int num=wf->size()/(8*(wf->bit())); CImg<float> signal_wav(num,1, 1, 1, 0); for(int i=0;i<num;i++) { signal_wav[i]=(data[i*8])*100; } CImg<unsigned char> signal_visu( 1200, 400, 1, 3, 0 ); /* 画格子 */ signal_visu.draw_grid( 50, 50, 0, 0, 0, 0, yellow, 0.5 ); signal_visu.draw_graph(signal_wav,red,1,3,0,35000,-35000,0); /* 画波形 */ CImgDisplay main_disp_wav (signal_visu, "signal" ); getchar(); return 0;}
wavfile.h
1 #ifndef WAVFILE_H 2 #define WAVFILE_H 3 #include <iostream> 4 #include <fstream> 5 using namespace std; 6 7 /* 8 BYTE=unsigned char(完全等同) WORD=unsigned short(完全等同) DWORD=unsigned long(完全等同) 9 10 unsigned char是无符号字节型 11 */ 12 namespace AudioUtils 13 { 14 /* 15 RIFF WAVE Chunk 16 ================================== 17 | |所占字节数| 具体内容 | 18 ================================== 19 | ID | 4 Bytes | ‘RIFF‘ | 20 ---------------------------------- 21 | Size | 4 Bytes | | 22 ---------------------------------- 23 | Type | 4 Bytes | ‘WAVE‘ | 24 ---------------------------------- 25 26 27 */ 28 class RiffBlock 29 { 30 public: 31 void ReadRiff(ifstream &infile) 32 { 33 int i=0; 34 for(i=0;i<4;i++) 35 { 36 infile.read((char*)&m_RiffID[i],1); 37 } 38 infile.read((char*)&m_RiffSize,4); 39 for(i=0;i<4;i++) 40 { 41 infile.read((char*)&Format[i],1); 42 } 43 } 44 45 /* 46 此处应当声明为pravte 用函数return, 不安全代码,暂简略处理 47 */ 48 unsigned char m_RiffID[4]; 49 unsigned long m_RiffSize; 50 unsigned char Format[4]; 51 }; 52 /* 53 ==================================================================== 54 | | 字节数 | 具体内容 | 55 ==================================================================== 56 | ID | 4 Bytes | ‘fmt ‘ | 57 -------------------------------------------------------------------- 58 | Size | 4 Bytes | 数值为16或18,18则最后又附加信息 | 59 -------------------------------------------------------------------- ---- 60 | FormatTag | 2 Bytes | 编码方式,一般为0x0001 | | 61 -------------------------------------------------------------------- | 62 | Channels | 2 Bytes | 声道数目,1--单声道;2--双声道 | | 63 -------------------------------------------------------------------- | 64 | SamplesPerSec | 4 Bytes | 采样频率 | | 65 -------------------------------------------------------------------- | 66 | AvgBytesPerSec| 4 Bytes | 每秒所需字节数 | |===> WAVE_FORMAT 67 -------------------------------------------------------------------- | 68 | BlockAlign | 2 Bytes | 数据块对齐单位(每个采样需要的字节数) | | 69 -------------------------------------------------------------------- | 70 | BitsPerSample | 2 Bytes | 每个采样需要的bit数 | | 71 -------------------------------------------------------------------- | 72 | | 2 Bytes | 附加信息(可选,通过Size来判断有无) | | 73 -------------------------------------------------------------------- ---- 74 75 */ 76 class FmtBlock 77 { 78 public: 79 //seekg()移动文件指针 80 void ReadFmt(ifstream &infile) 81 { 82 int i=0; 83 for(i=0;i<4;i++) 84 { 85 infile.read((char*)&m_FmtID[i],1); 86 } 87 infile.read((char*)&m_FmtSize,4); 88 int size=m_FmtSize; 89 infile.read((char*)&m_FmtTag,2); 90 infile.read((char*)&m_Channels,2); 91 infile.read((char*)&m_SamplesPerSec,4); 92 infile.read((char*)&m_AverageBytesPerSec,4); 93 infile.read((char*)&m_BlockAlign,2); 94 infile.read((char*)&m_BitsPerSample,2); 95 if(size==18) 96 { 97 infile.read((char*)&m_OtherMeg,2); 98 } 99 }100 101 int BitsPerSample()102 {103 return (m_BitsPerSample/8);104 }105 106 unsigned char m_FmtID[4];107 unsigned long m_FmtSize;108 unsigned short m_FmtTag;109 unsigned short m_Channels;110 unsigned long m_SamplesPerSec;111 unsigned long m_AverageBytesPerSec;112 unsigned short m_BlockAlign;113 unsigned short m_BitsPerSample;114 unsigned short m_OtherMeg;115 };116 117 /*118 Data Chunk119 ==================================120 | |所占字节数| 具体内容 |121 ==================================122 | ID | 4 Bytes | ‘data‘ |123 ----------------------------------124 | Size | 4 Bytes | |125 ----------------------------------126 | data | | |127 ----------------------------------128 129 1Bytes130 ---------------------------------------------------------------------131 | 单声道 | 取样1 | 取样2 | 取样3 | 取样4 |132 | | --------------------------------------------------------133 | 8bit量化 | 声道0 | 声道0 | 声道0 | 声道0 |134 ---------------------------------------------------------------------135 | 双声道 | 取样1 | 取样2 |136 | |--------------------------------------------------------137 | 8bit量化 | 声道0(左) | 声道1(右) | 声道0(左) | 声道1(右) |138 1WORD139 ---------------------------------------------------------------------140 | | 取样1 | 取样2 |141 | 单声道 |--------------------------------------------------------142 | 16bit量化 | 声道0 | 声道0 | 声道0 | 声道0 |143 | | (低位字节) | (高位字节) | (低位字节) | (高位字节) |144 ---------------------------------------------------------------------145 | | 取样1 |146 | 双声道 |--------------------------------------------------------147 | 16bit量化 | 声道0(左) | 声道0(左) | 声道1(右) | 声道1(右) |148 | | (低位字节) | (高位字节) | (低位字节) | (高位字节) |149 ---------------------------------------------------------------------150 151 */152 class DataBlock153 {154 public:155 void ReadData(ifstream &infile,int BitsPerSample)//BitsPerSample:1 8bit;2 16bit156 {157 int i=0;158 159 bool un_find_data=http://www.mamicode.com/true;160 while(un_find_data)161 {162 infile.read((char*)&temp,1);163 if(temp==‘d‘)164 {165 infile.read((char*)&temp,1);166 if(temp==‘a‘)167 {168 infile.read((char*)&temp,1);169 if(temp==‘t‘)170 {171 infile.read((char*)&temp,1);172 if(temp==‘a‘)173 {174 un_find_data=http://www.mamicode.com/false;175 }176 }177 }178 179 }180 }181 182 infile.read((char*)&m_DataSize,4);183 m_NumSamples=m_DataSize/BitsPerSample;184 if(BitsPerSample==1)185 {186 m_Data8=new char[m_NumSamples];187 for(i=0;i<m_NumSamples;i++)188 {189 infile.read((char*)&m_Data8[i],BitsPerSample);190 }191 }192 else if(BitsPerSample==2)193 {194 m_Data16=new short[m_NumSamples];195 for(i=0;i<m_NumSamples;i++)196 {197 infile.read((char*)&m_Data16[i],BitsPerSample);198 }199 }200 201 202 }203 204 short *m_Data16;205 char *m_Data8;206 207 unsigned char temp;208 unsigned char m_DataID[4];209 unsigned long m_DataSize;210 211 212 int m_NumSamples;//样本数量213 };214 class WaveFile215 {216 public:217 void readwav(char *path)218 {219 ifstream infile(path,ios::binary);220 m_Riff = new RiffBlock();221 m_Fmt = new FmtBlock();222 m_Data = http://www.mamicode.com/new DataBlock();223 224 m_Riff->ReadRiff(infile);225 m_Fmt->ReadFmt(infile);226 m_Data->ReadData(infile,m_Fmt->BitsPerSample());227 int i=0;228 data=http://www.mamicode.com/new int[m_Data->m_DataSize/m_Fmt->BitsPerSample()];229 for(i=0;i<(m_Data->m_DataSize)/(m_Fmt->BitsPerSample());i++)230 {231 232 if(m_Fmt->BitsPerSample()==1)233 {234 data[i]=(int)m_Data->m_Data8[i];235 }236 else if(m_Fmt->BitsPerSample()==2)237 {238 data[i]=(int)m_Data->m_Data16[i];239 }240 }241 242 }243 244 245 void output_WAVfile_info(void)//test246 {247 cout<<"Audio Msg:"<<endl;248 /*249 RIFF WAVE Chunk Message250 */251 cout<<m_Riff->m_RiffID<<endl;252 cout<<m_Riff->m_RiffSize<<endl;253 cout<<m_Riff->Format<<endl;254 255 /*256 Fmt Message257 */258 cout<<m_Fmt->m_FmtID<<endl;259 cout<<m_Fmt->m_FmtSize<<endl;260 cout<<m_Fmt->m_FmtTag<<endl;261 cout<<m_Fmt->m_Channels<<endl;262 cout<<m_Fmt->m_SamplesPerSec<<endl;263 cout<<m_Fmt->m_AverageBytesPerSec<<endl;264 cout<<m_Fmt->m_BlockAlign<<endl;265 cout<<m_Fmt->m_BitsPerSample<<endl;266 cout<<m_Fmt->m_OtherMeg<<endl;267 /*268 Data Chunk Message269 */270 cout<<m_Data->temp<<endl;271 cout<<m_Data->m_DataID<<endl;272 cout<<m_Data->m_DataSize<<endl;273 274 }275 int size(void)//音频长度276 {277 return m_Data->m_DataSize;278 }279 int channels(void)280 {281 return m_Fmt->m_Channels;282 }283 int bit(void)284 {285 return m_Fmt->BitsPerSample();286 }287 int *data;288 private: 289 RiffBlock *m_Riff;290 FmtBlock *m_Fmt;291 DataBlock *m_Data;292 };293 }294 295 #endif
编译时运行如下命令:
1 g++ -o out main.cpp -O2 -lm -lpthread -L/usr/X11R6/lib -lm -lpthread -lX11
结果:
调用CImg库显示WAV格式音频波形
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。