c++ - 读取 .wav 文件 - 不读取标题?

标签 c++ file text wav

我正在尝试从 .wav 文件中读取 header 信息,并且正在读取该文件的以下属性:

    type 
    size
    Format Tag
    Format Length
    Channels
    Sample Rate
    Average Bytes Second
    Block Align
    Bits Per Sample
    Data size

现在,一切都完美读取,直到读取采样率,然后,输出为“0”值或仅为 NULL。

代码如下:(我打开了文本文件,并将指针传递给了成员函数)

bool Wav::readHeader(FILE *dataIn)
{
   char type2[4];
   fread(this->type, sizeof(char), 4, dataIn);

   fread(&this->size, sizeof(int), 1, dataIn);

   fread(this->type, sizeof(char), 4, dataIn);

   fread(this->type, sizeof(char), 4, dataIn);

   fread(&this->format_length, sizeof(short), 1, dataIn);

   fread(&this->format_tag, sizeof(short), 1, dataIn);

   fread(&this->channels, sizeof(short), 1, dataIn);


   fread(&this->sample_rate, sizeof(unsigned int), 1, dataIn);

   fread(&this->avg_bytes_sec, sizeof(unsigned short), 1, dataIn);

   fread(&this->block_align, sizeof(short), 1, dataIn);

   fread(&this->bits_per_sample, sizeof(short), 1, dataIn);

   return true;
}

类成员定义为:

    char type[4]; 
    int size;
    unsigned short format_tag;
    unsigned short format_length;
    unsigned short channels;
    unsigned int sample_rate;
    unsigned short avg_bytes_sec;
    unsigned short block_align;
    unsigned short bits_per_sample;
    unsigned int data_size;

有没有人有任何解决方案或建议?

(附言,如果这个问题不对,我深表歉意。我已经尽力写好了!)

最佳答案

如果您有表示 (PCM) WAVE header 的紧凑结构,它看起来像这样:

struct Riff
{
  char chunkId[4]; // "RIFF" (assuming char is 8 bits)
  int chunkSize; // (assuming int is 32 bits)
  char format[4]; // "WAVE"
};

struct Format
{
  char chunkId[4]; // "fmt "
  int chunkSize;
  short format; // assuming short is 16 bits
  short numChannels;
  int sampleRate;
  int byteRate;
  short align;
  short bitsPerSample;
};

struct Data
{
  char chunkId[4]; // "data"
  int chunkSize; // length of data
  char* data;
};

struct Wave // Actual structure of a PCM WAVE file
{
  Riff riffHeader;
  Format formatHeader;
  Data dataHeader;
};

本质上,您的问题是 format_length(Format::chunkSize 在我的结构中)和 avg_bytes_sec(Format::byteRate 在我的结构中)在你的代码中每个都是 2 个字节,但它们每个应该是 4 个。你也没有读取数据子 block 的 header ,但我认为这是故意的?

要阅读,你可以这样做:

void readWave(std::ifstream& file, Wave& wave)
{
  // First read the RIFF header
  file.read(wave.riffHeader.chunkId,                                   4);
  file.read(reinterpret_cast<char*>(&wave.riffHeader.chunkSize),       4);
  file.read(wave.riffHeader.format,                                    4);

  // Now read the FORMAT header
  file.read(wave.formatHeader.chunkId,                                 4);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.chunkSize),     4);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.format),        2);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.numChannels),   2);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.sampleRate),    4);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.byteRate),      4);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.align),         2);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.bitsPerSample), 2);

  // Now read the DATA header
  file.read(wave.dataHeader.chunkId,                                   4);
  file.read(reinterpret_cast<char*>(&wave.dataHeader.chunkSize),       4);

  // The actual data goes in wave.dataHeader.data, so you can allocate it
  // and then read direclty into it now
}

Michael's link is the one I always use when I need to read/write a WAVE file (我不得不做几次)。我建议您仔细阅读。

如果您的 WAVE 文件中的“数据” block 之前有额外的 block ,此代码应该能够跳过它们:

void readWave(std::ifstream& file, Wave& wave)
{
  // First read the RIFF header
  file.read(wave.riffHeader.chunkId,                                   4);
  file.read(reinterpret_cast<char*>(&wave.riffHeader.chunkSize),       4);
  file.read(wave.riffHeader.format,                                    4);

  // Now read the FORMAT header
  file.read(wave.formatHeader.chunkId,                                 4);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.chunkSize),     4);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.format),        2);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.numChannels),   2);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.sampleRate),    4);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.byteRate),      4);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.align),         2);
  file.read(reinterpret_cast<char*>(&wave.formatHeader.bitsPerSample), 2);

  // WAVE files are just a special type of RIFF file, so it's possible
  // there are other chunks, like "fact" chunks. We'll skip over these
  // extra chunks until we find a "data" chunk
  char chunkId[4] = {0};
  int chunkSize = 0;
  while (file.read(chunkId, 4) &&
         (chunkId[0] != 'd' ||
          chunkId[1] != 'a' ||
          chunkId[2] != 't' ||
          chunkId[3] != 'a'))
    {
      file.read(reinterpret_cast<char*>(&chunkSize), 4); // Read the chunk's size
      file.seekg(chunkSize, std::ios_base::cur); // Skip the chunk
    }

  // We've found the DATA chunk and header
  wave.dataHeader.chunkId[0] = chunkId[0];
  wave.dataHeader.chunkId[1] = chunkId[1];
  wave.dataHeader.chunkId[2] = chunkId[2];
  wave.dataHeader.chunkId[3] = chunkId[3];
  file.read(reinterpret_cast<char*>(&wave.dataHeader.chunkSize),       4);

  // The actual data goes in wave.dataHeader.data, so you can allocate it
  // and then read direclty into it now
}

关于c++ - 读取 .wav 文件 - 不读取标题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11936702/

相关文章:

c++ - 即使 GLEW 已正确初始化,绘制调用也会发生读取访问冲突

c++ - 结构和 union

c++ - boost::boykov_kolmogorov_max_flow 的反向边缘图

Vista 上的 Java File.canWrite() 和 super 隐藏文件

java - 使用 java 或 xslt 根据 xml 的内容拆分 xml

mongodb - mongodb文本搜索错误没有文本索引

c++ - 四元数 - 旋转到

linux - 我如何在 Linux 中获得/dev/one 的等价物

javascript - React.js 中的奇怪错误——Fetch API 正在从 index.html 返回 HTML,尽管没有被调用

复制文本文件错误