WaveInfo Class Reference

This class reads and hold wave file header information. More...

#include <wave-reader.h>

Collaboration diagram for WaveInfo:

Public Member Functions

 WaveInfo ()
 
bool IsStreamed () const
 Is stream size unknown? Duration and SampleCount not valid if true. More...
 
BaseFloat SampFreq () const
 Sample frequency, Hz. More...
 
uint32 SampleCount () const
 Number of samples in stream. Invalid if IsStreamed() is true. More...
 
BaseFloat Duration () const
 Approximate duration, seconds. Invalid if IsStreamed() is true. More...
 
int32 NumChannels () const
 Number of channels, 1 to 16. More...
 
size_t BlockAlign () const
 Bytes per sample. More...
 
size_t DataBytes () const
 Wave data bytes. Invalid if IsStreamed() is true. More...
 
bool ReverseBytes () const
 Is data file byte order different from machine byte order? More...
 
void Read (std::istream &is)
 'is' should be opened in binary mode. More...
 

Private Attributes

BaseFloat samp_freq_
 
int32 samp_count_
 
uint8 num_channels_
 
bool reverse_bytes_
 

Detailed Description

This class reads and hold wave file header information.

Definition at line 65 of file wave-reader.h.

Constructor & Destructor Documentation

◆ WaveInfo()

WaveInfo ( )
inline

Definition at line 67 of file wave-reader.h.

Referenced by WaveInfoHolder::Clear().

67  : samp_freq_(0), samp_count_(0),
BaseFloat samp_freq_
Definition: wave-reader.h:99

Member Function Documentation

◆ BlockAlign()

size_t BlockAlign ( ) const
inline

Bytes per sample.

Definition at line 86 of file wave-reader.h.

References WaveInfo::num_channels_.

Referenced by WaveInfo::DataBytes(), and WaveData::Read().

86 { return 2 * num_channels_; }

◆ DataBytes()

size_t DataBytes ( ) const
inline

Wave data bytes. Invalid if IsStreamed() is true.

Definition at line 89 of file wave-reader.h.

References WaveInfo::BlockAlign(), and WaveInfo::samp_count_.

Referenced by WaveData::Read().

89 { return samp_count_ * BlockAlign(); }
size_t BlockAlign() const
Bytes per sample.
Definition: wave-reader.h:86

◆ Duration()

BaseFloat Duration ( ) const
inline

Approximate duration, seconds. Invalid if IsStreamed() is true.

Definition at line 80 of file wave-reader.h.

References WaveInfo::samp_count_, and WaveInfo::samp_freq_.

Referenced by main().

80 { return samp_count_ / samp_freq_; }
BaseFloat samp_freq_
Definition: wave-reader.h:99

◆ IsStreamed()

bool IsStreamed ( ) const
inline

Is stream size unknown? Duration and SampleCount not valid if true.

Definition at line 71 of file wave-reader.h.

References WaveInfo::samp_count_.

Referenced by main(), and WaveData::Read().

71 { return samp_count_ < 0; }

◆ NumChannels()

int32 NumChannels ( ) const
inline

Number of channels, 1 to 16.

Definition at line 83 of file wave-reader.h.

References WaveInfo::num_channels_.

Referenced by WaveData::Read().

83 { return num_channels_; }

◆ Read()

void Read ( std::istream &  is)

'is' should be opened in binary mode.

Read() will throw on error. On success 'is' will be positioned at the beginning of wave data.

Definition at line 114 of file wave-reader.cc.

References WaveHeaderReadGofer::Expect4ByteTag(), rnnlm::i, KALDI_ASSERT, KALDI_ERR, KALDI_VLOG, KALDI_WARN, WaveHeaderReadGofer::Read4ByteTag(), WaveHeaderReadGofer::ReadUint16(), WaveHeaderReadGofer::ReadUint32(), WaveHeaderReadGofer::swap, and WaveHeaderReadGofer::tag.

Referenced by WaveData::Read(), WaveInfo::ReverseBytes(), and WaveData::WaveData().

114  {
115  WaveHeaderReadGofer reader(is);
116  reader.Read4ByteTag();
117  if (strcmp(reader.tag, "RIFF") == 0)
118  reverse_bytes_ = false;
119  else if (strcmp(reader.tag, "RIFX") == 0)
120  reverse_bytes_ = true;
121  else
122  KALDI_ERR << "WaveData: expected RIFF or RIFX, got " << reader.tag;
123 
124 #ifdef __BIG_ENDIAN__
126 #endif
127  reader.swap = reverse_bytes_;
128 
129  uint32 riff_chunk_size = reader.ReadUint32();
130  reader.Expect4ByteTag("WAVE");
131 
132  uint32 riff_chunk_read = 0;
133  riff_chunk_read += 4; // WAVE included in riff_chunk_size.
134 
135  // Possibly skip any RIFF tags between 'WAVE' and 'fmt '.
136  // Apple devices produce a filler tag 'JUNK' for memory alignment.
137  reader.Read4ByteTag();
138  riff_chunk_read += 4;
139  while (strcmp(reader.tag,"fmt ") != 0) {
140  uint32 filler_size = reader.ReadUint32();
141  riff_chunk_read += 4;
142  for (uint32 i = 0; i < filler_size; i++) {
143  is.get(); // read 1 byte,
144  }
145  riff_chunk_read += filler_size;
146  // get next RIFF tag,
147  reader.Read4ByteTag();
148  riff_chunk_read += 4;
149  }
150 
151  KALDI_ASSERT(strcmp(reader.tag,"fmt ") == 0);
152  uint32 subchunk1_size = reader.ReadUint32();
153  uint16 audio_format = reader.ReadUint16();
154  num_channels_ = reader.ReadUint16();
155  uint32 sample_rate = reader.ReadUint32(),
156  byte_rate = reader.ReadUint32(),
157  block_align = reader.ReadUint16(),
158  bits_per_sample = reader.ReadUint16();
159  samp_freq_ = static_cast<BaseFloat>(sample_rate);
160 
161  uint32 fmt_chunk_read = 16;
162  if (audio_format == 1) {
163  if (subchunk1_size < 16) {
164  KALDI_ERR << "WaveData: expect PCM format data to have fmt chunk "
165  << "of at least size 16.";
166  }
167  } else if (audio_format == 0xFFFE) { // WAVE_FORMAT_EXTENSIBLE
168  uint16 extra_size = reader.ReadUint16();
169  if (subchunk1_size < 40 || extra_size < 22) {
170  KALDI_ERR << "WaveData: malformed WAVE_FORMAT_EXTENSIBLE format data.";
171  }
172  reader.ReadUint16(); // Unused for PCM.
173  reader.ReadUint32(); // Channel map: we do not care.
174  uint32 guid1 = reader.ReadUint32(),
175  guid2 = reader.ReadUint32(),
176  guid3 = reader.ReadUint32(),
177  guid4 = reader.ReadUint32();
178  fmt_chunk_read = 40;
179 
180  // Support only KSDATAFORMAT_SUBTYPE_PCM for now. Interesting formats:
181  // ("00000001-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_PCM)
182  // ("00000003-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
183  // ("00000006-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_ALAW)
184  // ("00000007-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_MULAW)
185  if (guid1 != 0x00000001 || guid2 != 0x00100000 ||
186  guid3 != 0xAA000080 || guid4 != 0x719B3800) {
187  KALDI_ERR << "WaveData: unsupported WAVE_FORMAT_EXTENSIBLE format.";
188  }
189  } else {
190  KALDI_ERR << "WaveData: can read only PCM data, format id in file is: "
191  << audio_format;
192  }
193 
194  for (uint32 i = fmt_chunk_read; i < subchunk1_size; ++i)
195  is.get(); // use up extra data.
196 
197  if (num_channels_ == 0)
198  KALDI_ERR << "WaveData: no channels present";
199  if (bits_per_sample != 16)
200  KALDI_ERR << "WaveData: unsupported bits_per_sample = " << bits_per_sample;
201  if (byte_rate != sample_rate * bits_per_sample/8 * num_channels_)
202  KALDI_ERR << "Unexpected byte rate " << byte_rate << " vs. "
203  << sample_rate << " * " << (bits_per_sample/8)
204  << " * " << num_channels_;
205  if (block_align != num_channels_ * bits_per_sample/8)
206  KALDI_ERR << "Unexpected block_align: " << block_align << " vs. "
207  << num_channels_ << " * " << (bits_per_sample/8);
208 
209  riff_chunk_read += 4 + subchunk1_size;
210  // size of what we just read, 4 for subchunk1_size + subchunk1_size itself.
211 
212  // We support an optional "fact" chunk (which is useless but which
213  // we encountered), and then a single "data" chunk.
214 
215  reader.Read4ByteTag();
216  riff_chunk_read += 4;
217 
218  // Skip any subchunks between "fmt" and "data". Usually there will
219  // be a single "fact" subchunk, but on Windows there can also be a
220  // "list" subchunk.
221  while (strcmp(reader.tag, "data") != 0) {
222  // We will just ignore the data in these chunks.
223  uint32 chunk_sz = reader.ReadUint32();
224  if (chunk_sz != 4 && strcmp(reader.tag, "fact") == 0)
225  KALDI_WARN << "Expected fact chunk to be 4 bytes long.";
226  for (uint32 i = 0; i < chunk_sz; i++)
227  is.get();
228  riff_chunk_read += 4 + chunk_sz; // for chunk_sz (4) + chunk contents (chunk-sz)
229 
230  // Now read the next chunk name.
231  reader.Read4ByteTag();
232  riff_chunk_read += 4;
233  }
234 
235  KALDI_ASSERT(strcmp(reader.tag, "data") == 0);
236  uint32 data_chunk_size = reader.ReadUint32();
237  riff_chunk_read += 4;
238 
239  // Figure out if the file is going to be read to the end. Values as
240  // observed in the wild:
241  bool is_stream_mode =
242  riff_chunk_size == 0
243  || riff_chunk_size == 0xFFFFFFFF
244  || data_chunk_size == 0
245  || data_chunk_size == 0xFFFFFFFF
246  || data_chunk_size == 0x7FFFF000; // This value is used by SoX.
247 
248  if (is_stream_mode)
249  KALDI_VLOG(1) << "Read in RIFF chunk size: " << riff_chunk_size
250  << ", data chunk size: " << data_chunk_size
251  << ". Assume 'stream mode' (reading data to EOF).";
252 
253  if (!is_stream_mode
254  && std::abs(static_cast<int64>(riff_chunk_read) +
255  static_cast<int64>(data_chunk_size) -
256  static_cast<int64>(riff_chunk_size)) > 1) {
257  // We allow the size to be off by one without warning, because there is a
258  // weirdness in the format of RIFF files that means that the input may
259  // sometimes be padded with 1 unused byte to make the total size even.
260  KALDI_WARN << "Expected " << riff_chunk_size << " bytes in RIFF chunk, but "
261  << "after first data block there will be " << riff_chunk_read
262  << " + " << data_chunk_size << " bytes "
263  << "(we do not support reading multiple data chunks).";
264  }
265 
266  if (is_stream_mode)
267  samp_count_ = -1;
268  else
269  samp_count_ = data_chunk_size / block_align;
270 }
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
BaseFloat samp_freq_
Definition: wave-reader.h:99

◆ ReverseBytes()

bool ReverseBytes ( ) const
inline

Is data file byte order different from machine byte order?

Definition at line 92 of file wave-reader.h.

References WaveInfo::Read(), and WaveInfo::reverse_bytes_.

Referenced by WaveData::Read().

92 { return reverse_bytes_; }

◆ SampFreq()

BaseFloat SampFreq ( ) const
inline

Sample frequency, Hz.

Definition at line 74 of file wave-reader.h.

References WaveInfo::samp_freq_.

Referenced by WaveData::Read().

74 { return samp_freq_; }
BaseFloat samp_freq_
Definition: wave-reader.h:99

◆ SampleCount()

uint32 SampleCount ( ) const
inline

Number of samples in stream. Invalid if IsStreamed() is true.

Definition at line 77 of file wave-reader.h.

References WaveInfo::samp_count_.

77 { return samp_count_; }

Member Data Documentation

◆ num_channels_

uint8 num_channels_
private

Definition at line 101 of file wave-reader.h.

Referenced by WaveInfo::BlockAlign(), and WaveInfo::NumChannels().

◆ reverse_bytes_

bool reverse_bytes_
private

Definition at line 102 of file wave-reader.h.

Referenced by WaveInfo::ReverseBytes().

◆ samp_count_

int32 samp_count_
private

◆ samp_freq_


The documentation for this class was generated from the following files: