Tag Parser  7.1.0
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(static_cast<streamoff>(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 = static_cast<uint64>(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(static_cast<streamoff>(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 = static_cast<uint32>(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.
The MpegAudioFrame class is used to parse MPEG audio frames.
WaveAudioStream(std::iostream &stream, uint64 startOffset)
Constructs a new track for the stream at the specified startOffset.
The MediaFormat class specifies the format of media data.
Definition: mediaformat.h:243
static void addInfo(const WaveFormatHeader &waveHeader, AbstractTrack &track)
Adds the information from the specified waveHeader to the specified track.
The WaveFormatHeader class parses the WAVEFORMATEX structure defined by MS.
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. ...
The exception that is thrown when the data to be parsed holds no parsable information.
Definition: exceptions.h:18
std::istream * m_istream
static void addInfo(const MpegAudioFrame &frame, AbstractTrack &track)
Adds the information from the specified frame to the specified track.
The AbstractTrack class parses and stores technical information about video, audio and other kinds of...
Definition: abstracttrack.h:39
uint32 xingFrameCount() const
Returns an indication whether the Xing frame count is present.
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:9
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.
The Diagnostics class is a container for DiagMessage.
Definition: diagnostics.h:154