Tag Parser  6.2.2
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/io/binaryreader.h>
9 #include <c++utilities/conversion/stringconversion.h>
10 
11 using namespace std;
12 using namespace ChronoUtilities;
13 
14 namespace Media {
15 
24 WaveFormatHeader::WaveFormatHeader() :
25  formatTag(0),
26  channelCount(0),
27  sampleRate(0),
28  bytesPerSecond(0),
29  chunkSize(0),
30  bitsPerSample(0)
31 {}
32 
37 void WaveFormatHeader::parse(IoUtilities::BinaryReader &reader)
38 {
39  formatTag = reader.readUInt16LE();
40  channelCount = reader.readUInt16LE();
41  sampleRate = reader.readUInt32LE();
42  bytesPerSecond = reader.readUInt32LE();
43  chunkSize = reader.readUInt16LE();
44  bitsPerSample = reader.readUInt16LE();
45 }
46 
51 {
52  switch(formatTag) {
53  case 0x0001u: return GeneralMediaFormat::Pcm;
56  default: return GeneralMediaFormat::Unknown;
57  }
58 }
59 
69 WaveAudioStream::WaveAudioStream(iostream &stream, uint64 startOffset) :
70  AbstractTrack(stream, startOffset),
71  m_dataOffset(0)
72 {
74 }
75 
80 {}
81 
83 {
85 }
86 
91 {
92  track.m_format = waveHeader.format();
93  track.m_formatId = ConversionUtilities::numberToString(waveHeader.formatTag);
94  track.m_channelCount = waveHeader.channelCount;
95  track.m_samplingFrequency = waveHeader.sampleRate;
96  track.m_bytesPerSecond = waveHeader.bytesPerSecond;
97  track.m_chunkSize = waveHeader.chunkSize;
98  track.m_bitsPerSample = waveHeader.bitsPerSample;
99  track.m_bitrate = waveHeader.bitrate();
100 }
101 
103 {
104  const string context("parsing RIFF/WAVE header");
105  if(!m_istream) {
106  throw NoDataFoundException();
107  }
108  if(m_reader.readUInt32BE() == 0x52494646u) {
109  m_istream->seekg(m_startOffset + 8);
110  if(m_reader.readUInt32BE() == 0x57415645u) {
111  while(!m_dataOffset) {
112  uint32 segmentId = m_reader.readUInt32BE();
113  uint32 restHeaderLen = m_reader.readUInt32LE();
114  switch(segmentId) {
115  case 0x666D7420u:
116  if(restHeaderLen >= 16u) {
117  WaveFormatHeader waveHeader;
118  waveHeader.parse(m_reader);
119  addInfo(waveHeader, *this);
120  restHeaderLen -= 16u;
121  } else {
122  addNotification(NotificationType::Warning, "\"fmt \" segment is truncated.", context);
123  }
124  break;
125  case 0x64617461u:
126  m_dataOffset = m_istream->tellg();
127  m_size = restHeaderLen;
129  m_duration = TimeSpan::fromSeconds(static_cast<double>(m_sampleCount) / static_cast<double>(m_samplingFrequency));
130  break;
131  default:
132  ;
133  }
134  m_istream->seekg(restHeaderLen, ios_base::cur);
135  }
136  } else {
137  throw NoDataFoundException();
138  }
139  } else {
140  throw NoDataFoundException();
141  }
142  if(m_format.general == GeneralMediaFormat::Mpeg1Audio && m_dataOffset) {
143  m_istream->seekg(m_dataOffset);
144  MpegAudioFrame frame;
145  frame.parseHeader(m_reader);
146  MpegAudioFrameStream::addInfo(frame, *this);
148  ? ((static_cast<double>(m_size) * 8.0) / (static_cast<double>(frame.xingFrameCount() * frame.sampleCount()) / static_cast<double>(frame.samplingFrequency())) / 1024.0)
149  : frame.bitrate();
150  m_bytesPerSecond = m_bitrate * 125;
151  m_duration = TimeSpan::fromSeconds(static_cast<double>(m_size) / (m_bitrate * 128.0));
152  }
153 }
154 
155 }
uint32 sampleCount() const
Returns the sample count if known; otherwise returns 0.
The WaveFormatHeader class parses the WAVEFORMATEX structure defined by MS.
uint32 samplingFrequency() const
Returns the sampeling frequency of the frame if known; otherwise returns 0.
uint32 bitrate() const
Returns the bitrate of the frame if known; otherwise returns 0.
std::string m_formatId
GeneralMediaFormat general
Definition: mediaformat.h:270
TrackType
Specifies the track type.
Definition: abstracttrack.h:28
The AbstractTrack class parses and stores technical information about video, audio and other kinds of...
Definition: abstracttrack.h:40
STL namespace.
virtual TrackType type() const
Returns the type of the track if known; otherwise returns TrackType::Unspecified. ...
IoUtilities::BinaryReader m_reader
void addNotification(const Notification &notification)
This protected method is meant to be called by the derived class to add a notification.
virtual void internalParseHeader()
This method is internally called to parse header information.
bool isXingFramefieldPresent() const
Returns an indication whether the Xing frame field is present.
void parseHeader(IoUtilities::BinaryReader &reader)
Parses the header read using the specified reader.
void parse(IoUtilities::BinaryReader &reader)
Parses the WAVE "fmt " header segment using the specified reader.
The MpegAudioFrame class is used to parse MPEG audio frames.
uint32 xingFrameCount() const
Returns an indication whether the Xing frame count is present.
uint32 bitrate() const
Calculates the bitrate from the header data.
WaveAudioStream(std::iostream &stream, uint64 startOffset)
Constructs a new track for the stream at the specified startOffset.
ChronoUtilities::TimeSpan m_duration
TAG_PARSER_EXPORT byte channelCount(byte config)
Returns the channel count for the specified MPEG-4 channel config.
Definition: mp4ids.cpp:342
MediaFormat format() const
Returns the media format denoted by the format tag.
static void addInfo(const WaveFormatHeader &waveHeader, AbstractTrack &track)
Adds the information from the specified waveHeader to the specified track.
The exception that is thrown when the data to be parsed holds no parsable information.
Definition: exceptions.h:19
virtual ~WaveAudioStream()
Destroys the track.
Contains all classes and functions of the TagInfo library.
Definition: exceptions.h:9
static void addInfo(const MpegAudioFrame &frame, AbstractTrack &track)
Adds the information from the specified frame to the specified track.
std::istream * m_istream
The MediaFormat class specifies the format of media data.
Definition: mediaformat.h:257