简体   繁体   English

读.wav文件 - 不读标题?

[英]Reading .wav files - Not reading header?

I am trying to read the header information from a .wav file, and I'm reading the following properties of the file: 我试图从.wav文件中读取标头信息,我正在阅读该文件的以下属性:

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

Now, everything reads perfectly up until reading in Sample Rate, then, the output is either "0" value or just NULL. 现在,所有内容都读取完全直到读取采样率,然后输出为“0”值或仅为NULL。

Here is the code: (I have opened the text file, and passed the pointer to the member function) 这是代码:(我打开了文本文件,并将指针传递给成员函数)

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;
}

And the class members are defined as: 班级成员定义为:

    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;

Does anyone have any solutions or suggestions? 有没有人有任何解决方案或建议?

(PS Apologies if this question is not right. I have tried to write it the best I could!) (PS道歉,如果这个问题不对。我尽力写出来!)

If you had tightly packed structs representing the (PCM) WAVE's header, it would look like this: 如果你有紧密打包的结构代表(PCM)WAVE的标题,它将如下所示:

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;
};

Essentially, your problem is that format_length ( Format::chunkSize in my struct) and avg_bytes_sec ( Format::byteRate in my struct) are 2 bytes each in your code, but they should each be 4. You're also not reading the data subchunk's header, but I assume that's intentional? 基本上,你的问题是你的代码中的format_length (我的struct中的Format::chunkSize )和avg_bytes_sec (我的struct中的Format::byteRate )每个都是2个字节,但它们每个都应该是4.你也没有读取数据subchunk的标题,但我认为这是故意的?

To read, you can do something like this: 要阅读,您可以这样做:

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 (which I've had to do several times). 迈克尔的链接是我在需要读/写WAVE文件时总是使用的链接 (我必须做几次)。 I suggest you read it carefully. 我建议你仔细阅读。

If you've got extra chunks in your WAVE file before your "data" chunk, this code should be able to skip them: 如果在“数据”块之前在WAVE文件中有额外的块,则此代码应该能够跳过它们:

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM