我目前正在做一个非常重要的学校项目。我需要在C / C ++中提取WAVE文件的信息,并使用该信息来获取语音信号的LPC。但是,为了做到这一点,我需要对信号进行一些预处理,比如进行零交叉和能量分析等。这意味着我需要标志和真正的价值。问题是我不知道如何获得有用的信息和正确的格式。我已经读过文件中的每个字段,但我不确定我做得对。建议,拜托?
这是我此刻阅读文件的方式:
readI = fread(& bps,1,2,audio); printf(“每个样本的位数=%d \ n”,bps);
提前致谢。
答案 0 :(得分:15)
我的第一个建议是使用某种图书馆来帮助你。大多数声音解决方案看起来都有些过分,所以一个简单的库(就像你的问题评论中推荐的那个,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值,format
变量是可以包含在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;
}
}