Tag Parser: wav/waveaudiostream.cpp Source File

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

Loading...
Searching...
No Matches
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
11using namespace std;
12using namespace CppUtilities;
13
14namespace TagParser {
15
20
25std::uint64_t WaveFormatHeader::parse(CppUtilities::BinaryReader &reader, std::uint64_t maxSize, Diagnostics &diag)
26{
27 uint64_t bytesRead = 0;
28 if (maxSize < 16) {
29 diag.emplace_back(DiagLevel::Warning, "\"fmt \" segment is truncated.", "parsing WAVE format header");
30 return bytesRead;
31 }
32
33 formatTag = reader.readUInt16LE();
34 channelCount = reader.readUInt16LE();
35 sampleRate = reader.readUInt32LE();
36 bytesPerSecond = reader.readUInt32LE();
37 chunkSize = reader.readUInt16LE();
38 bitsPerSample = reader.readUInt16LE();
39 bytesRead = 16;
40
41 // read extended header unless format is PCM
42 if (formatTag == 0x0001u || formatTag == 0x0003u) {
43 return bytesRead;
44 }
45 if ((maxSize -= 16) < 2) {
46 diag.emplace_back(DiagLevel::Warning, "\"fmt \" segment is truncated (extended header missing).", "parsing WAVE format header");
47 return bytesRead;
48 }
49 const auto extensionSize = reader.readUInt16LE();
50 bytesRead += 2;
51 if ((maxSize -= 2) < 2) {
52 diag.emplace_back(DiagLevel::Warning, "\"fmt \" segment is truncated (extended header truncated).", "parsing WAVE format header");
53 return bytesRead;
54 }
55
56 // skip extended header unless format is "WAVE_FORMAT_EXTENSIBLE"
57 if (formatTag != 65534) {
58 reader.stream()->seekg(extensionSize, ios_base::cur);
59 bytesRead += extensionSize;
60 return bytesRead;
61 }
62
63 // read extended header for "WAVE_FORMAT_EXTENSIBLE"
64 if (extensionSize != 22) {
65 diag.emplace_back(DiagLevel::Warning, "\"fmt \" extended header has unexptected size.", "parsing WAVE format header");
66 return bytesRead;
67 }
68 bitsPerSample = reader.readUInt16LE();
69 channelMask = reader.readUInt32LE();
70 guid1 = reader.readUInt64BE();
71 guid2 = reader.readUInt64BE();
72 return bytesRead += 22;
73}
74
78 MediaFormat WaveFormatHeader::format() const
79{
80 switch (formatTag) {
81 case 0x0001u:
82 return MediaFormat(GeneralMediaFormat::Pcm, SubFormats::PcmIntLe);
83 case 0x0003u:
84 return MediaFormat(GeneralMediaFormat::Pcm, SubFormats::PcmFloatIeee);
85 case 0x0050u:
86 return MediaFormat(GeneralMediaFormat::Mpeg1Audio, SubFormats::Mpeg1Layer2);
87 case 0x0055u:
88 return MediaFormat(GeneralMediaFormat::Mpeg1Audio, SubFormats::Mpeg1Layer3);
89 default:
90 switch (guid2) {
91 case 0x000800000aa00389b71:
92 switch (guid1) {
93 case 0x0100000000001000ul:
94 return MediaFormat(GeneralMediaFormat::Pcm, SubFormats::PcmIntLe);
95 case 0x0300000000001000ul:
96 return MediaFormat(GeneralMediaFormat::Pcm, SubFormats::PcmFloatIeee);
97 }
98 break;
99 }
100 return GeneralMediaFormat::Unknown;
101 }
102}
103
109
113 WaveAudioStream::WaveAudioStream(iostream &stream, std::uint64_t startOffset)
114 : AbstractTrack(stream, startOffset)
115 , m_dataOffset(0)
116{
117 m_mediaType = MediaType::Audio;
118}
119
123WaveAudioStream::~WaveAudioStream()
124{
125}
126
127 TrackType WaveAudioStream::type() const
128{
129 return TrackType::WaveAudioStream;
130}
131
135 void WaveAudioStream::addInfo(const WaveFormatHeader &waveHeader, AbstractTrack &track)
136{
137 track.m_format += waveHeader.format();
138 track.m_formatId = numberToString(waveHeader.formatTag);
139 track.m_channelCount = waveHeader.channelCount;
140 track.m_samplingFrequency = waveHeader.sampleRate;
141 track.m_bytesPerSecond = waveHeader.bytesPerSecond;
142 track.m_chunkSize = waveHeader.chunkSize;
143 track.m_bitsPerSample = waveHeader.bitsPerSample;
144 track.m_bitrate = waveHeader.bitrate();
145}
146
147 void WaveAudioStream::internalParseHeader(Diagnostics &diag, AbortableProgressFeedback &progress)
148{
149 CPP_UTILITIES_UNUSED(progress)
150
151 const string context("parsing RIFF/WAVE header");
152 if (!m_istream) {
153 throw NoDataFoundException();
154 }
155 if (m_reader.readUInt32BE() != 0x52494646u) {
156 throw NoDataFoundException();
157 }
158 m_istream->seekg(static_cast<streamoff>(m_startOffset + 8));
159 if (m_reader.readUInt32BE() != 0x57415645u) {
160 throw NoDataFoundException();
161 }
162 while (!m_dataOffset) {
163 const auto segmentId = m_reader.readUInt32BE();
164 auto restHeaderLen = static_cast<std::uint64_t>(m_reader.readUInt32LE());
165 switch (segmentId) {
166 case 0x666D7420u: { // format segment
167 WaveFormatHeader waveHeader;
168 const auto bytesRead = waveHeader.parse(m_reader, restHeaderLen, diag);
169 addInfo(waveHeader, *this);
170 restHeaderLen -= bytesRead;
171 } break;
172 case 0x64617461u: // data segment
173 m_dataOffset = static_cast<std::uint64_t>(m_istream->tellg());
174 m_size = restHeaderLen;
175 m_sampleCount = m_size / m_chunkSize;
176 m_duration = TimeSpan::fromSeconds(static_cast<double>(m_sampleCount) / static_cast<double>(m_samplingFrequency));
177 break;
178 default:;
179 }
180 m_istream->seekg(static_cast<std::streamoff>(restHeaderLen), ios_base::cur);
181 }
182 if (m_format.general != GeneralMediaFormat::Mpeg1Audio || !m_dataOffset) {
183 return;
184 }
185 m_istream->seekg(static_cast<streamoff>(m_dataOffset));
186 MpegAudioFrame frame;
187 frame.parseHeader(m_reader, diag);
188 MpegAudioFrameStream::addInfo(frame, *this);
189 m_bitrate = frame.isXingFramefieldPresent()
190 ? ((static_cast<double>(m_size) * 8.0)
191 / (static_cast<double>(frame.xingFrameCount() * frame.sampleCount()) / static_cast<double>(frame.samplingFrequency())) / 1024.0)
192 : frame.bitrate();
193 m_bytesPerSecond = static_cast<std::uint32_t>(m_bitrate * 125);
194 m_duration = TimeSpan::fromSeconds(static_cast<double>(m_size) / (m_bitrate * 128.0));
195}
196
197} // namespace TagParser
TagParser::AbortableProgressFeedback
The AbortableProgressFeedback class provides feedback about an ongoing operation via callbacks.
Definition progressfeedback.h:186
TagParser::AbstractTrack::m_sampleCount
std::uint64_t m_sampleCount
Definition abstracttrack.h:221
TagParser::AbstractTrack::startOffset
std::uint64_t startOffset() const
Returns the start offset of the track in the associated stream.
Definition abstracttrack.h:316
TagParser::AbstractTrack::m_bytesPerSecond
std::uint32_t m_bytesPerSecond
Definition abstracttrack.h:216
TagParser::AbstractTrack::m_size
std::uint64_t m_size
Definition abstracttrack.h:203
TagParser::AbstractTrack::m_bitsPerSample
std::uint16_t m_bitsPerSample
Definition abstracttrack.h:215
TagParser::AbstractTrack::m_formatId
std::string m_formatId
Definition abstracttrack.h:199
TagParser::AbstractTrack::AbstractTrack
AbstractTrack(std::istream &inputStream, std::ostream &outputStream, std::uint64_t startOffset)
Constructs a new track.
Definition abstracttrack.cpp:33
TagParser::AbstractTrack::m_channelCount
std::uint16_t m_channelCount
Definition abstracttrack.h:217
TagParser::AbstractTrack::m_duration
CppUtilities::TimeSpan m_duration
Definition abstracttrack.h:207
TagParser::AbstractTrack::m_reader
CppUtilities::BinaryReader m_reader
Definition abstracttrack.h:194
TagParser::AbstractTrack::m_chunkSize
std::uint16_t m_chunkSize
Definition abstracttrack.h:220
TagParser::AbstractTrack::m_startOffset
std::uint64_t m_startOffset
Definition abstracttrack.h:196
TagParser::AbstractTrack::WaveAudioStream
friend class WaveAudioStream
Definition abstracttrack.h:112
TagParser::AbstractTrack::m_format
MediaFormat m_format
Definition abstracttrack.h:198
TagParser::AbstractTrack::m_bitrate
double m_bitrate
Definition abstracttrack.h:208
TagParser::AbstractTrack::m_istream
std::istream * m_istream
Definition abstracttrack.h:192
TagParser::AbstractTrack::m_samplingFrequency
std::uint32_t m_samplingFrequency
Definition abstracttrack.h:213
TagParser::AbstractTrack::m_mediaType
MediaType m_mediaType
Definition abstracttrack.h:201
TagParser::Diagnostics
The Diagnostics class is a container for DiagMessage.
Definition diagnostics.h:156
TagParser::MediaFormat
The MediaFormat class specifies the format of media data.
Definition mediaformat.h:247
TagParser::MpegAudioFrameStream::addInfo
static void addInfo(const MpegAudioFrame &frame, AbstractTrack &track)
Adds the information from the specified frame to the specified track.
Definition mpegaudioframestream.cpp:23
TagParser::MpegAudioFrame
The MpegAudioFrame class is used to parse MPEG audio frames.
Definition mpegaudioframe.h:37
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::sampleCount
std::uint32_t sampleCount() const
Returns the sample count if known; otherwise returns 0.
Definition mpegaudioframe.cpp:185
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::xingFrameCount
constexpr std::uint32_t xingFrameCount() const
Returns an indication whether the Xing frame count is present.
Definition mpegaudioframe.h:207
TagParser::MpegAudioFrame::parseHeader
void parseHeader(CppUtilities::BinaryReader &reader, Diagnostics &diag)
Parses the header read using the specified reader.
Definition mpegaudioframe.cpp:49
TagParser::MpegAudioFrame::isXingFramefieldPresent
constexpr bool isXingFramefieldPresent() const
Returns an indication whether the Xing frame field is present.
Definition mpegaudioframe.h:175
TagParser::NoDataFoundException
The exception that is thrown when the data to be parsed holds no parsable information (e....
Definition exceptions.h:18
TagParser::WaveAudioStream::type
TrackType type() const override
Returns the type of the track if known; otherwise returns TrackType::Unspecified.
Definition waveaudiostream.cpp:127
TagParser::WaveAudioStream::addInfo
static void addInfo(const WaveFormatHeader &waveHeader, AbstractTrack &track)
Adds the information from the specified waveHeader to the specified track.
Definition waveaudiostream.cpp:135
TagParser::WaveAudioStream::~WaveAudioStream
~WaveAudioStream() override
Destroys the track.
Definition waveaudiostream.cpp:123
TagParser::WaveAudioStream::internalParseHeader
void internalParseHeader(Diagnostics &diag, AbortableProgressFeedback &progress) override
This method is internally called to parse header information.
Definition waveaudiostream.cpp:147
TagParser::WaveFormatHeader
The WaveFormatHeader class parses the WAVEFORMATEX structure defined by MS.
Definition waveaudiostream.h:8
TagParser::WaveFormatHeader::bitsPerSample
std::uint16_t bitsPerSample
Definition waveaudiostream.h:23
TagParser::WaveFormatHeader::chunkSize
std::uint16_t chunkSize
Definition waveaudiostream.h:22
TagParser::WaveFormatHeader::guid1
std::uint64_t guid1
Definition waveaudiostream.h:16
TagParser::WaveFormatHeader::bytesPerSecond
std::uint32_t bytesPerSecond
Definition waveaudiostream.h:21
TagParser::WaveFormatHeader::guid2
std::uint64_t guid2
Definition waveaudiostream.h:17
TagParser::WaveFormatHeader::formatTag
std::uint16_t formatTag
Definition waveaudiostream.h:18
TagParser::WaveFormatHeader::format
MediaFormat format() const
Returns the media format denoted by the format tag.
Definition waveaudiostream.cpp:78
TagParser::WaveFormatHeader::channelCount
std::uint16_t channelCount
Definition waveaudiostream.h:19
TagParser::WaveFormatHeader::bitrate
constexpr std::uint32_t bitrate() const
Calculates the bitrate from the header data.
Definition waveaudiostream.h:46
TagParser::WaveFormatHeader::parse
std::uint64_t parse(CppUtilities::BinaryReader &reader, std::uint64_t maxSize, Diagnostics &diag)
Parses the WAVE "fmt " header segment using the specified reader.
Definition waveaudiostream.cpp:25
TagParser::WaveFormatHeader::sampleRate
std::uint32_t sampleRate
Definition waveaudiostream.h:20
TagParser::WaveFormatHeader::channelMask
std::uint32_t channelMask
Definition waveaudiostream.h:24
exceptions.h
mediaformat.h
mpegaudioframestream.h
CppUtilities
Definition abstractcontainer.h:16
TagParser::SubFormats::Mpeg1Layer2
@ Mpeg1Layer2
Definition mediaformat.h:114
TagParser::SubFormats::Mpeg1Layer3
@ Mpeg1Layer3
Definition mediaformat.h:114
TagParser::SubFormats::PcmIntLe
@ PcmIntLe
Definition mediaformat.h:226
TagParser::SubFormats::PcmFloatIeee
@ PcmFloatIeee
Definition mediaformat.h:226
TagParser
Contains all classes and functions of the TagInfo library.
Definition aaccodebook.h:10
TagParser::DiagLevel::Warning
@ Warning
Definition diagnostics.h:20
TagParser::MediaType::Audio
@ Audio
Definition mediaformat.h:16
TagParser::GeneralMediaFormat::Pcm
@ Pcm
Definition mediaformat.h:73
TagParser::GeneralMediaFormat::Unknown
@ Unknown
Definition mediaformat.h:31
TagParser::GeneralMediaFormat::Mpeg1Audio
@ Mpeg1Audio
Definition mediaformat.h:65
TagParser::TrackType
TrackType
The TrackType enum specifies the underlying file type of a track and the concrete class of the track ...
Definition abstracttrack.h:32
TagParser::TrackType::WaveAudioStream
@ WaveAudioStream
Definition abstracttrack.h:37
waveaudiostream.h