简体   繁体   中英

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:

    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.

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!)

If you had tightly packed structs representing the (PCM) WAVE's header, it would look like this:

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?

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). 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:

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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