我是靠谱客的博主 腼腆枕头,最近开发中收集的这篇文章主要介绍webrtc中的wav文件格式解析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

发现wav文件的格式解析有点小问题,原因就是不同的软件录制的wav文件里面有一些多余的头,这样就无法保证头的大小为44字节了,所以解析的代码需要注意这一点。我发现早前版本的webrtc里的源码就没有考虑到这一点,在解析ffmpeg转换后的wav文件和苹果录制的wav文件时,就出了问题。请看源码:webrtc/src/common_audio/wav_header.cc文件里的函数ReadWavHeader实现。

本人改写如下:

bool ReadWavHeader(ReadableWav* readable,
                   int* num_channels,
                   int* sample_rate,
                   WavFormat* format,
                   size_t* bytes_per_sample,
                   size_t* num_samples) {

    WavHeader header;
#if 0
    if (readable->Read(&header, kWavHeaderSize - sizeof(header.data)) !=
        kWavHeaderSize - sizeof(header.data))
        return false;

    const uint32_t fmt_size = ReadLE32(header.fmt.header.Size);
    if (fmt_size != kFmtSubchunkSize) {
        // There is an optional two-byte extension field permitted to be present
        // with PCM, but which must be zero.
        int16_t ext_size;
        if (kFmtSubchunkSize + sizeof(ext_size) != fmt_size)
            return false;
        if (readable->Read(&ext_size, sizeof(ext_size)) != sizeof(ext_size))
            return false;
        if (ext_size != 0)
            return false;
    }

    if (readable->Read(&header.data, sizeof(header.data)) != sizeof(header.data))
        return false;
#else
    while (true) {
        ChunkHeader unknown_header;
        if (readable->Read(&unknown_header, sizeof(unknown_header)) != sizeof(unknown_header))
            return false;

        std::string fourccID = ReadFourCC(unknown_header.ID);
        if (fourccID == "RIFF")
        {
            header.riff.header = unknown_header;
            if (readable->Read(&header.riff.Format, sizeof(header.riff.Format)) != sizeof(header.riff.Format))
                return false;
        }
        else if (fourccID == "fmt ")
        {
            header.fmt.header = unknown_header;
            if (readable->Read(&header.fmt.info, sizeof(header.fmt.info)) != sizeof(header.fmt.info))
                return false;

            const uint32_t fmt_size = ReadLE32(header.fmt.header.Size);
            if (fmt_size != kFmtSubchunkSize) {
                // There is an optional two-byte extension field permitted to be present
                // with PCM, but which must be zero.
                int16_t ext_size;
                if (kFmtSubchunkSize + sizeof(ext_size) != fmt_size)
                    return false;
                if (readable->Read(&ext_size, sizeof(ext_size)) != sizeof(ext_size))
                    return false;
                if (ext_size != 0)
                    return false;
            }
        }
        else if (fourccID == "data")
        {
            header.data.header = unknown_header;
            break;//until find data
        }
        else// if (fourccID == "LIST")//skip junk/list/fllr if exists
        {
            const size_t bytes_in_payload = ReadLE32(unknown_header.Size);
            if (readable->Seek(bytes_in_payload, SEEK_CUR) != 0)
                return false;
        }
    }
#endif
  // Parse needed fields.
  *format = static_cast<WavFormat>(ReadLE16(header.fmt.AudioFormat));
  *num_channels = ReadLE16(header.fmt.NumChannels);
  *sample_rate = ReadLE32(header.fmt.SampleRate);
  *bytes_per_sample = ReadLE16(header.fmt.BitsPerSample) / 8;
  const size_t bytes_in_payload = ReadLE32(header.data.header.Size);
  if (*bytes_per_sample == 0)
    return false;
  *num_samples = bytes_in_payload / *bytes_per_sample;

  // Sanity check remaining fields.
  if (ReadFourCC(header.riff.header.ID) != "RIFF")
    return false;
  if (ReadFourCC(header.riff.Format) != "WAVE")
    return false;
  if (ReadFourCC(header.fmt.header.ID) != "fmt ")
    return false;
  if (ReadFourCC(header.data.header.ID) != "data")
    return false;

  if (ReadLE32(header.riff.header.Size) < RiffChunkSize(bytes_in_payload))
    return false;
  if (ReadLE32(header.fmt.ByteRate) !=
      ByteRate(*num_channels, *sample_rate, *bytes_per_sample))
    return false;
  if (ReadLE16(header.fmt.BlockAlign) !=
      BlockAlign(*num_channels, *bytes_per_sample))
    return false;

  return CheckWavParameters(*num_channels, *sample_rate, *format,
                            *bytes_per_sample, *num_samples);
}

 

 

最后

以上就是腼腆枕头为你收集整理的webrtc中的wav文件格式解析的全部内容,希望文章能够帮你解决webrtc中的wav文件格式解析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部