我正在做一个很重要的学校项目.我需要在C/C++中提取WAVE文件的信息,并使用该信息获取语音信号的LPC.但是,为了做到这一点,我需要对信号进行一些预处理,例如进行零交叉和能量分析等等.这意味着我需要标志和真正的价值.问题是我不知道如何获取有用的信息和正确的格式.我已经阅读了文件中的每一个字段,但我不知道我做的是正确的.建议吗?
这是我现在读取文件的方式:
readI = fread(&bps,1,2,audio);
printf(“bits per sample = %d \n”,bps);提前致谢.
解决方法
我的第一个建议是使用某种图书馆来帮助你.大多数声音解决方案看起来都是过度的,所以一个简单的图书馆(像您在问题的评论中推荐的一个图书馆,应该是
libsndfile).
如果您只想知道如何阅读WAV文件,以便您自己编写(因为您的学校可能会让您的任何其他常规人员使用图书馆,都可能会变得笨拙),快速的谷歌搜索会给您所有的信息需要plus some people who have already wrote many tutorials on reading the .wav format.
如果仍然没有得到它,这里有一些我自己的代码,我读取头文件和所有其他块的WAV / RIFF数据文件,直到我到达数据块.它是基于exclusively off the WAV Format Specification.提取实际的声音数据不是很难:你可以读它原始的,使用原始的,或转换为一种格式,你会更舒适的内部(32位PCM未压缩的数据或东西).
当看下面的代码时,将reader.Read …(…)替换为指定类型的整数值和字节大小的等效fread调用. WavChunks是一个枚举,它是WAV文件块中ID的Little Endian值,格式变量是可以包含在WAV文件格式中的Wav格式类型之一:
enum class WavChunks { RiffHeader = 0x46464952,WavRiff = 0x54651475,Format = 0x020746d66,LabeledText = 0x478747C6,Instrumentation = 0x478747C6,Sample = 0x6C706D73,Fact = 0x47361666,Data = 0x61746164,Junk = 0x4b4e554a,}; enum class WavFormat { PulseCodeModulation = 0x01,IEEEFloatingPoint = 0x03,ALaw = 0x06,MuLaw = 0x07,IMAADPCM = 0x11,YamahaITUG723ADPCM = 0x16,GSM610 = 0x31,ITUG721ADPCM = 0x40,MPEG = 0x50,Extensible = 0xFFFE }; int32 chunkid = 0; bool datachunk = false; while ( !datachunk ) { chunkid = reader.ReadInt32( ); switch ( (WavChunks)chunkid ) { case WavChunks::Format: formatsize = reader.ReadInt32( ); format = (WavFormat)reader.ReadInt16( ); channels = (Channels)reader.ReadInt16( ); channelcount = (int)channels; samplerate = reader.ReadInt32( ); bitspersecond = reader.ReadInt32( ); formatblockalign = reader.ReadInt16( ); bitdepth = reader.ReadInt16( ); if ( formatsize == 18 ) { int32 extradata = reader.ReadInt16( ); reader.Seek( extradata,SeekOrigin::Current ); } break; case WavChunks::RiffHeader: headerid = chunkid; memsize = reader.ReadInt32( ); riffstyle = reader.ReadInt32( ); break; case WavChunks::Data: datachunk = true; datasize = reader.ReadInt32( ); break; default: int32 skipsize = reader.ReadInt32( ); reader.Seek( skipsize,SeekOrigin::Current ); break; } }