C++解析wav文件方法介绍_第1页
C++解析wav文件方法介绍_第2页
C++解析wav文件方法介绍_第3页
C++解析wav文件方法介绍_第4页
C++解析wav文件方法介绍_第5页
已阅读5页,还剩4页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第C++解析wav文件方法介绍目录一、前言二、接口三、具体步骤四、完整源码

一、前言

一开始本来在网上找代码,不过改了好几个都不是很好用。因为很多wav文件的fmt块后面并不是data块,经常还带有其他块,正确的方法应该是按MSDN的方法,找到data块再读取。

二、接口

最后接口如下:

classAudioReader

public:

structPCM

int_numChannel;//通道数1,2AL_FORMAT_MONO8,AL_FORMAT_STEREO8

int_bitPerSample;//采样数8,16

byte*_data;

size_t_size;

size_t_freq;//采样率

voidDelete(){delete[]_data;}

staticboolReadWAV(string_viewpath_name,PCMpcm);

};

三、具体步骤

打开文件,这里就是普通的文件流,按二进制、只读打开文件即可:

ifstreamifs;

if(!g_file-GetFile(path_name,ifs))

debug_err(format("打开文件失败:{}",path_name));

returnfalse;

}

查找riff块:

uint32_tdwChunkSize;

uint32_tdwChunkPosition;

//查找riff块

FindChunk(ifs,fourccRIFF,dwChunkSize,dwChunkPosition);

uint32_tfiletype;

ReadChunkData(ifs,filetype,sizeof(uint32_t),dwChunkPosition);

if(filetype!=fourccWAVE)

debug_err(format("匹配标记失败(fourccWAVE):{}",path_name));

returnfalse;

}

其中fourccRIFF和fourccWAVE是我们定义的标记,也就是处理了下大小端,如下:

#ifdefDND_ENDIAN_BIG

#definefourccRIFF'RIFF'

#definefourccDATA'data'

#definefourccFMT'fmt'

#definefourccWAVE'WAVE'

#definefourccXWMA'XWMA'

#definefourccDPDS'dpds'

#endif

#ifdefDND_ENDIAN_LITTLE

#definefourccRIFF'FFIR'

#definefourccDATA'atad'

#definefourccFMT'tmf'

#definefourccWAVE'EVAW'

#definefourccXWMA'AMWX'

#definefourccDPDS'sdpd'

#endif

而FindChunk和ReadChunkData两个函数,分别是查找一个块,和读取一个块。代码实现有点长,可以参考后面我给出的完整源码。

接着,查找并读取fmt块,这个块描述了wav文件的音频属性,结构如下(部分字段会用到):

//16字节

structWAVEFormat

int16_taudioFormat;

int16_tnumChannels;

int32_tsampleRate;

int32_tbyteRate;

int16_tblockAlign;

int16_tbitsPerSample;

};

//查找fmt块

if(!FindChunk(ifs,fourccFMT,dwChunkSize,dwChunkPosition))

debug_err(format("查找块失败(fourccFMT):{}",path_name));

returnfalse;

//读wave信息

WAVEFormatwave_format;

if(!ReadChunkData(ifs,wave_format,dwChunkSize,dwChunkPosition))

debug_err(format("读取块失败(wave_format):{}",path_name));

returnfalse;

};

接下来查找data块,根据返回的大小分配内存:

//查找音频数据

if(!FindChunk(ifs,fourccDATA,dwChunkSize,dwChunkPosition))

debug_err(format("查找块失败(fourccDATA):{}",path_name));

returnfalse;

pcm._data=newbyte[dwChunkSize];

然后读取data块,将数据读取到我们分配的内存pcm._data。然后记录下一些重要的字段。由于OpenaAL不能直接播放32位(只8、16)的数据,这里简单返回失败。

if(!ReadChunkData(ifs,pcm._data,dwChunkSize,dwChunkPosition))

debug_err(format("读取块失败(pcm数据):{}",path_name));

pcm.Delete();

returnfalse;

pcm._size=dwChunkSize;

pcm._numChannel=wave_format.numChannels;

pcm._bitPerSample=wave_format.bitsPerSample;

pcm._freq=wave_format.sampleRate;

if(pcm._bitPerSample==32)

debug_err(format("不支持32位:{}",path_name));

pcm.Delete();

returnfalse;

returntrue;

四、完整源码

可以此处获取最新的源码(我将来会添加ogg格式的解析),也可以用下面的:传送门

//.h

classAudioReader

public:

structPCM

int_numChannel;//通道数1,2AL_FORMAT_MONO8,AL_FORMAT_STEREO8

int_bitPerSample;//采样数8,16

byte*_data;

size_t_size;

size_t_freq;//采样率

voidDelete(){delete[]_data;}

staticboolReadWAV(string_viewpath_name,PCMpcm);

//16字节

structWAVEFormat

int16_taudioFormat;

int16_tnumChannels;

int32_tsampleRate;

int32_tbyteRate;

int16_tblockAlign;

int16_tbitsPerSample;

//.cpp

#ifdefDND_ENDIAN_BIG

#definefourccRIFF'RIFF'

#definefourccDATA'data'

#definefourccFMT'fmt'

#definefourccWAVE'WAVE'

#definefourccXWMA'XWMA'

#definefourccDPDS'dpds'

#endif

#ifdefDND_ENDIAN_LITTLE

#definefourccRIFF'FFIR'

#definefourccDATA'atad'

#definefourccFMT'tmf'

#definefourccWAVE'EVAW'

#definefourccXWMA'AMWX'

#definefourccDPDS'sdpd'

#endif

boolFindChunk(ifstreamifs,uint32_tfourcc,uint32_tsize,uint32_tpos)

boolret=true;

ifs.seekg(0);

if(ifs.fail())

returnfalse;

uint32_tdwChunkType;

uint32_tdwChunkDataSize;

uint32_tdwRIFFDataSize=0;

uint32_tdwFileType;

uint32_tbytesRead=0;

uint32_tdwOffset=0;

while(ret)

ifs.read((char*)dwChunkType,sizeof(uint32_t));

ifs.read((char*)dwChunkDataSize,sizeof(uint32_t));

switch(dwChunkType)

casefourccRIFF:

dwRIFFDataSize=dwChunkDataSize;

dwChunkDataSize=4;

ifs.read((char*)dwFileType,sizeof(uint32_t));

break;

default:

ifs.seekg(dwChunkDataSize,std::ios::cur);

if(ifs.fail())

returnfalse;

break;

dwOffset+=sizeof(uint32_t)*2;

if(dwChunkType==fourcc)

size=dwChunkDataSize;

pos=dwOffset;

returntrue;

dwOffset+=dwChunkDataSize;

if(bytesRead=dwRIFFDataSize)

returnfalse;

returntrue;

boolReadChunkData(ifstreamifs,void*buffer,uint32_tsize,uint32_tpos)

ifs.seekg(pos);

if(ifs.fail())

returnfalse;

ifs.read((char*)buffer,size);

returntrue;

boolAudioReader::ReadWAV(string_viewpath_name,PCMpcm)

ifstreamifs;

if(!g_file-GetFile(path_name,ifs))

debug_err(format("打开文件失败:{}",path_name));

returnfalse;

uint32_tdwChunkSize;

uint32_tdwChunkPosition;

//查找riff块

FindChunk(ifs,fourccRIFF,dwChunkSize,dwChunkPosition);

uint32_tfiletype;

ReadChunkData(ifs,filetype,sizeof(uint32_t),dwChunkPosition);

if(filetype!=fourccWAVE)

debug_err(format("匹配标记失败(fourccWAVE):{}",path_name));

returnfalse;

//查找fmt块

if(!FindChunk(ifs,fourccFMT,dwChunkSize,dwChunkPosition))

debug_err(format("查找块失败(fourccFMT):{}",path_name));

returnfalse;

//读wave信息

WAVEFormatwave_format;

if(!ReadChunkData(ifs,wave_format,dwChunkSize,dwChunkPosition))

debug_err(format("读取块失败(wave_format):{}",path_name));

returnfalse;

//查找音频数据

if(!Fin

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论