Переглянути джерело

Fix reading wav with metadata (#17)

Fangjun Kuang 2 роки тому
батько
коміт
f649b3cab9
1 змінених файлів з 22 додано та 5 видалено
  1. 22 5
      sherpa-ncnn/csrc/wave-reader.cc

+ 22 - 5
sherpa-ncnn/csrc/wave-reader.cc

@@ -32,10 +32,10 @@ namespace {
 // TODO(fangjun): Support big endian
 struct WaveHeader {
   void Validate() const {
-    //                       F F I R
+    //                    F F I R
     assert(chunk_id == 0x46464952);
     assert(chunk_size == 36 + subchunk2_size);
-    //                     E V A W
+    //                  E V A W
     assert(format == 0x45564157);
     assert(subchunk1_id == 0x20746d66);
     assert(subchunk1_size == 16);  // 16 for PCM
@@ -46,6 +46,22 @@ struct WaveHeader {
     assert(bits_per_sample == 16);  // we support only 16 bits per sample
   }
 
+  // See
+  // https://en.wikipedia.org/wiki/WAV#Metadata
+  // and
+  // https://www.robotplanet.dk/audio/wav_meta_data/riff_mci.pdf
+  void SeekToDataChunk(std::istream &is) {
+    //                        a t a d
+    while (subchunk2_id != 0x61746164) {
+      // const char *p = reinterpret_cast<const char *>(&subchunk2_id);
+      // printf("Skip chunk (%x): %c%c%c%c of size: %d\n", subchunk2_id, p[0],
+      //        p[1], p[2], p[3], subchunk2_size);
+      is.seekg(subchunk2_size, std::istream::cur);
+      is.read(reinterpret_cast<char *>(&subchunk2_id), sizeof(int32_t));
+      is.read(reinterpret_cast<char *>(&subchunk2_size), sizeof(int32_t));
+    }
+  }
+
   int32_t chunk_id;
   int32_t chunk_size;
   int32_t format;
@@ -57,8 +73,8 @@ struct WaveHeader {
   int32_t byte_rate;
   int16_t block_align;
   int16_t bits_per_sample;
-  int32_t subchunk2_id;
-  int32_t subchunk2_size;
+  int32_t subchunk2_id;    // a tag of this chunk
+  int32_t subchunk2_size;  // size of subchunk2
 };
 static_assert(sizeof(WaveHeader) == 44, "");
 
@@ -68,9 +84,10 @@ std::vector<float> ReadWaveImpl(std::istream &is, float *sample_rate) {
   WaveHeader header;
   is.read(reinterpret_cast<char *>(&header), sizeof(header));
   assert(static_cast<bool>(is));
-
   header.Validate();
 
+  header.SeekToDataChunk(is);
+
   *sample_rate = header.sample_rate;
 
   // header.subchunk2_size contains the number of bytes in the data.