Tag Parser  9.4.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
mpegaudioframe.cpp
Go to the documentation of this file.
1 #include "./mpegaudioframe.h"
2 
3 #include "../exceptions.h"
4 
5 #include <c++utilities/conversion/stringbuilder.h>
6 #include <c++utilities/conversion/stringconversion.h>
7 #include <c++utilities/io/binaryreader.h>
8 
9 using namespace std;
10 using namespace CppUtilities;
11 
12 namespace TagParser {
13 
17 const char *mpegChannelModeString(MpegChannelMode channelMode)
18 {
19  switch (channelMode) {
20  case MpegChannelMode::Stereo:
21  return "2 channels: stereo";
22  case MpegChannelMode::JointStereo:
23  return "2 channels: joint stereo";
24  case MpegChannelMode::DualChannel:
25  return "2 channels: dual channel";
26  case MpegChannelMode::SingleChannel:
27  return "1 channel: single channel";
28  default:
29  return nullptr;
30  }
31 }
32 
38 const std::uint16_t MpegAudioFrame::s_bitrateTable[0x2][0x3][0xF] = { { { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 },
39  { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 },
40  { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } },
41  { { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 },
42  { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 } } };
43 
49 void MpegAudioFrame::parseHeader(BinaryReader &reader, Diagnostics &diag)
50 {
51  // read MPEG audio frame header
52  m_header = reader.readUInt32BE();
53  if (!isValid()) {
54  diag.emplace_back(DiagLevel::Critical,
55  "Frame 0x" % numberToString(m_header, 16) % " at 0x" % numberToString<std::int64_t>(reader.stream()->tellg() - 4l, 16) + " is invalid.",
56  "parsing MPEG audio frame header");
57  throw InvalidDataException();
58  }
59 
60  // read XING header (see https://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header#XINGHeader)
61  if (size() < s_xingHeaderOffset - 4 + 8) {
62  return;
63  }
64  reader.stream()->seekg(s_xingHeaderOffset - 4, ios_base::cur);
65  m_xingHeader = reader.readUInt64BE();
66  if (isXingHeaderAvailable()) {
67  m_xingHeaderFlags = static_cast<XingHeaderFlags>(m_xingHeader & 0xffffffffuL);
68  if (isXingFramefieldPresent()) {
69  m_xingFramefield = reader.readUInt32BE();
70  }
71  if (isXingBytesfieldPresent()) {
72  m_xingBytesfield = reader.readUInt32BE();
73  }
74  if (isXingTocFieldPresent()) {
75  reader.stream()->seekg(64, ios_base::cur);
76  }
77  if (isXingQualityIndicatorFieldPresent()) {
78  m_xingQualityIndicator = reader.readUInt32BE();
79  }
80  }
81 }
82 
86 double MpegAudioFrame::mpegVersion() const
87 {
88  switch (m_header & 0x180000u) {
89  case 0x180000u:
90  return 1.0;
91  case 0x100000u:
92  return 2.0;
93  case 0x0u:
94  return 2.5;
95  default:
96  return 0.0;
97  }
98 }
99 
103 int MpegAudioFrame::layer() const
104 {
105  switch (m_header & 0x60000u) {
106  case 0x60000u:
107  return 1;
108  case 0x40000u:
109  return 2;
110  case 0x20000u:
111  return 3;
112  default:
113  return 0;
114  }
115 }
116 
120 std::uint32_t MpegAudioFrame::samplingFrequency() const
121 {
122  switch (m_header & 0xc00u) {
123  case 0xc00u:
124  return 0;
125  case 0x800u:
126  switch (m_header & 0x180000u) {
127  case 0x180000u:
128  return 32000;
129  case 0x100000u:
130  return 16000;
131  case 0x0u:
132  return 8000u;
133  }
134  break;
135  case 0x400u:
136  switch (m_header & 0x180000u) {
137  case 0x180000u:
138  return 48000;
139  case 0x100000u:
140  return 24000;
141  case 0x0u:
142  return 12000;
143  }
144  break;
145  case 0x0u:
146  switch (m_header & 0x180000u) {
147  case 0x180000u:
148  return 44100;
149  case 0x100000:
150  return 22050;
151  case 0x0u:
152  return 11025;
153  }
154  break;
155  }
156  return 0;
157 }
158 
162 MpegChannelMode MpegAudioFrame::channelMode() const
163 {
164  if (isValid()) {
165  switch (m_header & 0xc0u) {
166  case 0xc0u:
167  return MpegChannelMode::SingleChannel;
168  case 0x80u:
169  return MpegChannelMode::DualChannel;
170  case 0x40u:
171  return MpegChannelMode::JointStereo;
172  case 0x00:
173  return MpegChannelMode::Stereo;
174  default:;
175  }
176  }
177  return MpegChannelMode::Unspecifed;
178 }
179 
183 std::uint32_t MpegAudioFrame::sampleCount() const
184 {
185  switch (m_header & 0x60000u) {
186  case 0x60000u:
187  return 384u;
188  case 0x40000u:
189  return 1152u;
190  case 0x20000u:
191  switch (m_header & 0x180000u) {
192  case 0x180000u:
193  return 1152u;
194  case 0x100000u:
195  case 0x0u:
196  return 576u;
197  }
198  default:;
199  }
200  return 0;
201 }
202 
206 std::uint32_t MpegAudioFrame::size() const
207 {
208  switch (m_header & 0x60000u) {
209  case 0x60000u: // layer 1
210  return static_cast<std::uint32_t>(
211  ((static_cast<double>(bitrate()) * 1024.0 / 8.0) / static_cast<double>(samplingFrequency())) * static_cast<double>(sampleCount())
212  + static_cast<double>(paddingSize()))
213  * 4;
214  case 0x40000u: // layer 2
215  case 0x20000u: // layer 3
216  return static_cast<std::uint32_t>(
217  ((static_cast<double>(bitrate()) * 1024.0 / 8.0) / static_cast<double>(samplingFrequency())) * static_cast<double>(sampleCount())
218  + static_cast<double>(paddingSize()));
219  default:
220  return 0;
221  }
222 }
223 
224 } // namespace TagParser
TagParser::MatroskaTagIds::TrackSpecific::bitrate
constexpr TAG_PARSER_EXPORT const char * bitrate()
The track's bit rate in bits per second.
Definition: matroskatagid.h:456
TagParser::MpegChannelMode
MpegChannelMode
Specifies the channel mode.
Definition: mpegaudioframe.h:18
mpegaudioframe.h
TagParser::Diagnostics
The Diagnostics class is a container for DiagMessage.
Definition: diagnostics.h:156
TagParser
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:10
TagParser::mpegChannelModeString
TAG_PARSER_EXPORT const char * mpegChannelModeString(MpegChannelMode channelMode)
Returns the string representation for the specified channelMode.
Definition: mpegaudioframe.cpp:17
CppUtilities
Definition: abstractcontainer.h:15
TagParser::InvalidDataException
The exception that is thrown when the data to be parsed or to be made seems invalid and therefore can...
Definition: exceptions.h:25
TagParser::XingHeaderFlags
XingHeaderFlags
Definition: mpegaudioframe.h:28