Tag Parser  7.0.3
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
waveaudiostream.cpp
Go to the documentation of this file.
1 #include "./waveaudiostream.h"
2 
3 #include "../mpegaudio/mpegaudioframestream.h"
4 
5 #include "../exceptions.h"
6 #include "../mediaformat.h"
7 
8 #include <c++utilities/conversion/stringconversion.h>
9 #include <c++utilities/io/binaryreader.h>
10 
11 using namespace std;
12 using namespace ChronoUtilities;
13 
14 namespace TagParser {
15 
24 WaveFormatHeader::WaveFormatHeader()
25  : formatTag(0)
26  , channelCount(0)
27  , sampleRate(0)
28  , bytesPerSecond(0)
29  , chunkSize(0)
30  , bitsPerSample(0)
31 {
32 }
33 
38 void WaveFormatHeader::parse(IoUtilities::BinaryReader &reader)
39 {
40  formatTag = reader.readUInt16LE();
41  channelCount = reader.readUInt16LE();
42  sampleRate = reader.readUInt32LE();
43  bytesPerSecond = reader.readUInt32LE();
44  chunkSize = reader.readUInt16LE();
45  bitsPerSample = reader.readUInt16LE();
46 }
47 
52 {
53  switch (formatTag) {
54  case 0x0001u:
56  case 0x0050u:
58  case 0x0055u:
60  default:
62  }
63 }
64 
74 WaveAudioStream::WaveAudioStream(iostream &stream, uint64 startOffset)
75  : AbstractTrack(stream, startOffset)
76  , m_dataOffset(0)
77 {
79 }
80 
85 {
86 }
87 
89 {
91 }
92 
97 {
98  track.m_format = waveHeader.format();
99  track.m_formatId = ConversionUtilities::numberToString(waveHeader.formatTag);
100  track.m_channelCount = waveHeader.channelCount;
101  track.m_samplingFrequency = waveHeader.sampleRate;
102  track.m_bytesPerSecond = waveHeader.bytesPerSecond;
103  track.m_chunkSize = waveHeader.chunkSize;
104  track.m_bitsPerSample = waveHeader.bitsPerSample;
105  track.m_bitrate = waveHeader.bitrate();
106 }
107 
109 {
110  const string context("parsing RIFF/WAVE header");
111  if (!m_istream) {
112  throw NoDataFoundException();
113  }
114  if (m_reader.readUInt32BE() != 0x52494646u) {
115  throw NoDataFoundException();
116  }
117  m_istream->seekg(m_startOffset + 8);
118  if (m_reader.readUInt32BE() != 0x57415645u) {
119  throw NoDataFoundException();
120  }
121  while (!m_dataOffset) {
122  uint32 segmentId = m_reader.readUInt32BE();
123  uint32 restHeaderLen = m_reader.readUInt32LE();
124  switch (segmentId) {
125  case 0x666D7420u:
126  if (restHeaderLen >= 16u) {
127  WaveFormatHeader waveHeader;
128  waveHeader.parse(m_reader);
129  addInfo(waveHeader, *this);
130  restHeaderLen -= 16u;
131  } else {
132  diag.emplace_back(DiagLevel::Warning, "\"fmt \" segment is truncated.", context);
133  }
134  break;
135  case 0x64617461u:
136  m_dataOffset = m_istream->tellg();
137  m_size = restHeaderLen;
139  m_duration = TimeSpan::fromSeconds(static_cast<double>(m_sampleCount) / static_cast<double>(m_samplingFrequency));
140  break;
141  default:;
142  }
143  m_istream->seekg(restHeaderLen, ios_base::cur);
144  }
145  if (m_format.general != GeneralMediaFormat::Mpeg1Audio || !m_dataOffset) {
146  return;
147  }
148  m_istream->seekg(m_dataOffset);
149  MpegAudioFrame frame;
150  frame.parseHeader(m_reader);
151  MpegAudioFrameStream::addInfo(frame, *this);
153  ? ((static_cast<double>(m_size) * 8.0)
154  / (static_cast<double>(frame.xingFrameCount() * frame.sampleCount()) / static_cast<double>(frame.samplingFrequency())) / 1024.0)
155  : frame.bitrate();
156  m_bytesPerSecond = m_bitrate * 125;
157  m_duration = TimeSpan::fromSeconds(static_cast<double>(m_size) / (m_bitrate * 128.0));
158 }
159 
160 } // namespace TagParser
TAG_PARSER_EXPORT byte channelCount(byte config)
Returns the channel count for the specified MPEG-4 channel config.
Definition: mp4ids.cpp:445
uint32 sampleCount() const
Returns the sample count if known; otherwise returns 0.
IoUtilities::BinaryReader m_reader
~WaveAudioStream() override
Destroys the track.
void parseHeader(IoUtilities::BinaryReader &reader)
Parses the header read using the specified reader.
WaveAudioStream(std::iostream &stream, uint64 startOffset)
Constructs a new track for the stream at the specified startOffset.
static void addInfo(const WaveFormatHeader &waveHeader, AbstractTrack &track)
Adds the information from the specified waveHeader to the specified track.
STL namespace.
MediaFormat format() const
Returns the media format denoted by the format tag.
GeneralMediaFormat general
Definition: mediaformat.h:256
void parse(IoUtilities::BinaryReader &reader)
Parses the WAVE "fmt " header segment using the specified reader.
bool isXingFramefieldPresent() const
Returns an indication whether the Xing frame field is present.
ChronoUtilities::TimeSpan m_duration
uint32 bitrate() const
Calculates the bitrate from the header data.
TrackType type() const override
Returns the type of the track if known; otherwise returns TrackType::Unspecified. ...
std::istream * m_istream
static void addInfo(const MpegAudioFrame &frame, AbstractTrack &track)
Adds the information from the specified frame to the specified track.
uint32 xingFrameCount() const
Returns an indication whether the Xing frame count is present.
TrackType
Specifies the track type.
Definition: abstracttrack.h:28
uint32 bitrate() const
Returns the bitrate of the frame if known; otherwise returns 0.
uint32 samplingFrequency() const
Returns the sampeling frequency of the frame if known; otherwise returns 0.
void internalParseHeader(Diagnostics &diag) override
This method is internally called to parse header information.