Tag Parser: mpegaudio/mpegaudioframe.cpp Source File

Tag Parser 12.5.3 C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags

Loading...
Searching...
No Matches
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
9using namespace std;
10using namespace CppUtilities;
11
12namespace TagParser {
13
17std::string_view 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 std::string_view();
30 }
31}
32
37
38const 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, 16u) % " at 0x"
56 % numberToString<std::int64_t>(reader.stream()->tellg() - static_cast<std::streamoff>(4), 16)
57 + " is invalid.",
58 "parsing MPEG audio frame header");
59 throw InvalidDataException();
60 }
61
62 // read XING header (see https://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header#XINGHeader)
63 if (size() < s_xingHeaderOffset - 4 + 8) {
64 return;
65 }
66 reader.stream()->seekg(s_xingHeaderOffset - 4, ios_base::cur);
67 m_xingHeader = reader.readUInt64BE();
68 if (isXingHeaderAvailable()) {
69 m_xingHeaderFlags = static_cast<XingHeaderFlags>(m_xingHeader & 0xffffffffuL);
70 if (isXingFramefieldPresent()) {
71 m_xingFramefield = reader.readUInt32BE();
72 }
73 if (isXingBytesfieldPresent()) {
74 m_xingBytesfield = reader.readUInt32BE();
75 }
76 if (isXingTocFieldPresent()) {
77 reader.stream()->seekg(0x64, ios_base::cur);
78 }
79 if (isXingQualityIndicatorFieldPresent()) {
80 m_xingQualityIndicator = reader.readUInt32BE();
81 }
82 }
83}
84
88 double MpegAudioFrame::mpegVersion() const
89{
90 switch (m_header & 0x180000u) {
91 case 0x180000u:
92 return 1.0;
93 case 0x100000u:
94 return 2.0;
95 case 0x0u:
96 return 2.5;
97 default:
98 return 0.0;
99 }
100}
101
105 int MpegAudioFrame::layer() const
106{
107 switch (m_header & 0x60000u) {
108 case 0x60000u:
109 return 1;
110 case 0x40000u:
111 return 2;
112 case 0x20000u:
113 return 3;
114 default:
115 return 0;
116 }
117}
118
122std::uint32_t MpegAudioFrame::samplingFrequency() const
123{
124 switch (m_header & 0xc00u) {
125 case 0xc00u:
126 return 0;
127 case 0x800u:
128 switch (m_header & 0x180000u) {
129 case 0x180000u:
130 return 32000;
131 case 0x100000u:
132 return 16000;
133 case 0x0u:
134 return 8000u;
135 }
136 break;
137 case 0x400u:
138 switch (m_header & 0x180000u) {
139 case 0x180000u:
140 return 48000;
141 case 0x100000u:
142 return 24000;
143 case 0x0u:
144 return 12000;
145 }
146 break;
147 case 0x0u:
148 switch (m_header & 0x180000u) {
149 case 0x180000u:
150 return 44100;
151 case 0x100000:
152 return 22050;
153 case 0x0u:
154 return 11025;
155 }
156 break;
157 }
158 return 0;
159}
160
164 MpegChannelMode MpegAudioFrame::channelMode() const
165{
166 if (isValid()) {
167 switch (m_header & 0xc0u) {
168 case 0xc0u:
169 return MpegChannelMode::SingleChannel;
170 case 0x80u:
171 return MpegChannelMode::DualChannel;
172 case 0x40u:
173 return MpegChannelMode::JointStereo;
174 case 0x00:
175 return MpegChannelMode::Stereo;
176 default:;
177 }
178 }
179 return MpegChannelMode::Unspecifed;
180}
181
185std::uint32_t MpegAudioFrame::sampleCount() const
186{
187 switch (m_header & 0x60000u) {
188 case 0x60000u:
189 return 384u;
190 case 0x40000u:
191 return 1152u;
192 case 0x20000u:
193 switch (m_header & 0x180000u) {
194 case 0x180000u:
195 return 1152u;
196 case 0x100000u:
197 case 0x0u:
198 return 576u;
199 }
200 default:;
201 }
202 return 0;
203}
204
208std::uint32_t MpegAudioFrame::size() const
209{
210 switch (m_header & 0x60000u) {
211 case 0x60000u: // layer 1
212 return static_cast<std::uint32_t>(
213 ((static_cast<double>(bitrate()) * 1024.0 / 8.0) / static_cast<double>(samplingFrequency())) * static_cast<double>(sampleCount())
214 + static_cast<double>(paddingSize()))
215 * 4;
216 case 0x40000u: // layer 2
217 case 0x20000u: // layer 3
218 return static_cast<std::uint32_t>(
219 ((static_cast<double>(bitrate()) * 1024.0 / 8.0) / static_cast<double>(samplingFrequency())) * static_cast<double>(sampleCount())
220 + static_cast<double>(paddingSize()));
221 default:
222 return 0;
223 }
224}
225
226} // namespace TagParser
TagParser::Diagnostics
The Diagnostics class is a container for DiagMessage.
Definition diagnostics.h:156
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::MpegAudioFrame::size
std::uint32_t size() const
Returns the size if known; otherwise returns 0.
Definition mpegaudioframe.cpp:208
TagParser::MpegAudioFrame::isXingQualityIndicatorFieldPresent
constexpr bool isXingQualityIndicatorFieldPresent() const
Returns an indication whether the Xing quality indicator field is present.
Definition mpegaudioframe.h:199
TagParser::MpegAudioFrame::samplingFrequency
std::uint32_t samplingFrequency() const
Returns the sampeling frequency of the frame if known; otherwise returns 0.
Definition mpegaudioframe.cpp:122
TagParser::MpegAudioFrame::channelMode
MpegChannelMode channelMode() const
Returns the channel mode if known; otherwise returns MpegChannelMode::Unspecifed.
Definition mpegaudioframe.cpp:164
TagParser::MpegAudioFrame::paddingSize
constexpr std::uint32_t paddingSize() const
Returns the padding size if known; otherwise returns 0.
Definition mpegaudioframe.h:121
TagParser::MpegAudioFrame::sampleCount
std::uint32_t sampleCount() const
Returns the sample count if known; otherwise returns 0.
Definition mpegaudioframe.cpp:185
TagParser::MpegAudioFrame::isXingTocFieldPresent
constexpr bool isXingTocFieldPresent() const
Returns an indication whether the Xing TOC is present.
Definition mpegaudioframe.h:191
TagParser::MpegAudioFrame::isValid
constexpr bool isValid() const
Returns an indication whether the frame is valid.
Definition mpegaudioframe.h:93
TagParser::MpegAudioFrame::layer
int layer() const
Returns the MPEG layer if known (1, 2, or 3); otherwise returns 0.
Definition mpegaudioframe.cpp:105
TagParser::MpegAudioFrame::bitrate
std::uint16_t bitrate() const
Returns the bitrate of the frame if known; otherwise returns 0.
Definition mpegaudioframe.h:109
TagParser::MpegAudioFrame::isXingBytesfieldPresent
constexpr bool isXingBytesfieldPresent() const
Returns an indication whether the Xing bytes field is present.
Definition mpegaudioframe.h:183
TagParser::MpegAudioFrame::parseHeader
void parseHeader(CppUtilities::BinaryReader &reader, Diagnostics &diag)
Parses the header read using the specified reader.
Definition mpegaudioframe.cpp:49
TagParser::MpegAudioFrame::isXingHeaderAvailable
constexpr bool isXingHeaderAvailable() const
Returns an indication whether a Xing header is present.
Definition mpegaudioframe.h:159
TagParser::MpegAudioFrame::mpegVersion
double mpegVersion() const
Returns the MPEG version if known (1.0, 2.0 or 2.5); otherwise returns 0.
Definition mpegaudioframe.cpp:88
TagParser::MpegAudioFrame::isXingFramefieldPresent
constexpr bool isXingFramefieldPresent() const
Returns an indication whether the Xing frame field is present.
Definition mpegaudioframe.h:175
exceptions.h
mpegaudioframe.h
CppUtilities
Definition abstractcontainer.h:16
TagParser
Contains all classes and functions of the TagInfo library.
Definition aaccodebook.h:10
TagParser::mpegChannelModeString
TAG_PARSER_EXPORT std::string_view mpegChannelModeString(MpegChannelMode channelMode)
Returns the string representation for the specified channelMode.
Definition mpegaudioframe.cpp:17
TagParser::DiagLevel::Critical
@ Critical
Definition diagnostics.h:21
TagParser::XingHeaderFlags
XingHeaderFlags
Definition mpegaudioframe.h:29
TagParser::MpegChannelMode
MpegChannelMode
Specifies the channel mode.
Definition mpegaudioframe.h:19
TagParser::MpegChannelMode::DualChannel
@ DualChannel
Definition mpegaudioframe.h:22
TagParser::MpegChannelMode::JointStereo
@ JointStereo
Definition mpegaudioframe.h:21
TagParser::MpegChannelMode::Unspecifed
@ Unspecifed
Definition mpegaudioframe.h:24
TagParser::MpegChannelMode::SingleChannel
@ SingleChannel
Definition mpegaudioframe.h:23
TagParser::MpegChannelMode::Stereo
@ Stereo
Definition mpegaudioframe.h:20