【问题标题】:Reading and processing WAV file data in C/C++在 C/C++ 中读取和处理 WAV 文件数据
【发布时间】:2013-04-11 02:41:36
【问题描述】:

我目前正在做一个非常重要的学校项目。我需要在 C/C++ 中提取 WAVE 文件的信息,并使用该信息来获取语音信号的 LPC。但是,为了做到这一点,我需要对信号进行一些预处理,比如过零和能量分析等等。这意味着我需要符号和真实值。问题是我不知道如何获得有用的信息和正确的格式。我已经阅读了文件中的每个字段,但我不确定我做得对。请给点建议?

这是我目前读取文件的方式:

readI = fread(&bps, 1, 2, 音频); printf("每个样本的位数 = %d \n", bps);

提前致谢。

【问题讨论】:

标签: c++ c voice voice-recognition


【解决方案1】:

我的第一个建议是使用某种库来帮助您。大多数合理的解决方案似乎都是多余的,所以一个简单的库(就像你的问题评论中推荐的那样,libsndfile)应该可以解决问题。

如果您只是想知道如何阅读 WAV 文件以便编写自己的文件(因为您的学校可能会拒绝让您像其他普通人一样使用图书馆),那么快速的 google 搜索将为您提供所有信息您需要的信息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;
    }
}

【讨论】:

  • 为什么 RIFF 用十六进制倒写?我知道小端/大端,但我使用的所有十六进制编辑器都将其显示为 RIFF,而不是 FFIR,它们是在幕后进行了一些奇怪的转换,还是发生了其他事情?
  • 我相信@MarcusJ 是正确的应该阅读 RIFF,这里是对波形格式 soundfile.sapp.org/doc/WaveFormat 的描述,所以我认为它应该是 RiffHeader = 0x52494646,因为格式表明它是一个大端字段
  • @MarcusJ 因为它是小端序......它甚至直接在答案本身中说明。 旧评论
猜你喜欢
  • 1970-01-01
  • 2011-08-27
  • 2012-11-19
  • 2021-12-26
  • 1970-01-01
  • 2014-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多