SourcePP
Several modern C++20 libraries for sanely parsing Valve's formats.
Loading...
Searching...
No Matches
WAV.h
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <optional>
5
6#include <BufferStream.h>
7
8#include "RIFF.h"
9
10namespace sndpp {
11
13
14class WAV : public RIFF {
15public:
16 enum ChunkType : uint32_t {
19 CHUNK_CUE = sourcepp::parser::binary::makeFourCC("cue "), // Cue points / markers
20 CHUNK_PLST = sourcepp::parser::binary::makeFourCC("plst"), // Playlist for cue points
21 CHUNK_FACT = sourcepp::parser::binary::makeFourCC("fact"), // More track details
29
30 //CHUNK_LIST = sourcepp::parser::binary::makeFourCC("LIST"), // Metadata
31 //CHUNK_LIST_WAVL = sourcepp::parser::binary::makeFourCC("WAVL"), // Wave list
32
33 //CHUNK_LIST_INFO = sourcepp::parser::binary::makeFourCC("INFO"), // Overall metadata
34 //CHUNK_LIST_INFO_IARL = sourcepp::parser::binary::makeFourCC("IARL"), // Archive location
35 //CHUNK_LIST_INFO_IGNR = sourcepp::parser::binary::makeFourCC("IGNR"), // Genre
36 //CHUNK_LIST_INFO_IKEY = sourcepp::parser::binary::makeFourCC("IKEY"), // Keywords
37 //CHUNK_LIST_INFO_ILGT = sourcepp::parser::binary::makeFourCC("ILGT"), // Lightness
38 //CHUNK_LIST_INFO_IMED = sourcepp::parser::binary::makeFourCC("IMED"), // Medium
39 //CHUNK_LIST_INFO_INAM = sourcepp::parser::binary::makeFourCC("INAM"), // Title
40 //CHUNK_LIST_INFO_IPLT = sourcepp::parser::binary::makeFourCC("IPLT"), // Palette setting
41 //CHUNK_LIST_INFO_IPRD = sourcepp::parser::binary::makeFourCC("IPRD"), // Product
42 //CHUNK_LIST_INFO_ISBJ = sourcepp::parser::binary::makeFourCC("ISBJ"), // Subject
43 //CHUNK_LIST_INFO_ISFT = sourcepp::parser::binary::makeFourCC("ISFT"), // Software used
44 //CHUNK_LIST_INFO_ISHP = sourcepp::parser::binary::makeFourCC("ISHP"), // Sharpness
45 //CHUNK_LIST_INFO_IART = sourcepp::parser::binary::makeFourCC("IART"), // Artist
46 //CHUNK_LIST_INFO_ISRC = sourcepp::parser::binary::makeFourCC("ISRC"), // Source (file supplier)
47 //CHUNK_LIST_INFO_ISRF = sourcepp::parser::binary::makeFourCC("ISRF"), // Source form
48 //CHUNK_LIST_INFO_ITCH = sourcepp::parser::binary::makeFourCC("ITCH"), // Technician
49 //CHUNK_LIST_INFO_ICMS = sourcepp::parser::binary::makeFourCC("ICMS"), // Commissioner
50 //CHUNK_LIST_INFO_ICMT = sourcepp::parser::binary::makeFourCC("ICMT"), // Comments
51 //CHUNK_LIST_INFO_ICOP = sourcepp::parser::binary::makeFourCC("ICOP"), // Copyright
52 //CHUNK_LIST_INFO_ICRP = sourcepp::parser::binary::makeFourCC("ICRP"), // Crop
53 //CHUNK_LIST_INFO_IDPI = sourcepp::parser::binary::makeFourCC("IDPI"), // Dots per inch
54 //CHUNK_LIST_INFO_IENG = sourcepp::parser::binary::makeFourCC("IENG"), // Engineer
55 //CHUNK_LIST_INFO_ISMP = sourcepp::parser::binary::makeFourCC("ISMP"), // Digitization start time (SMPTE time code)
56 //CHUNK_LIST_INFO_IDIT = sourcepp::parser::binary::makeFourCC("IDIT"), // Digitization start time (26 characters, formatted like "Wed Jan 02 02:03:55 1990\n\0")
57 //CHUNK_LIST_INFO_ICRD = sourcepp::parser::binary::makeFourCC("ICRD"), // Creation date (YYYY, YYYY-MM, YYYY-MM-DD)
58 //CHUNK_LIST_INFO_ITRK = sourcepp::parser::binary::makeFourCC("ITRK"), // Track number
59
60 //CHUNK_LIST_ADTL = sourcepp::parser::binary::makeFourCC("adtl"), // Cue points metadata
61 //CHUNK_LIST_ADTL_LABL = sourcepp::parser::binary::makeFourCC("labl"), // Cue point label
62 //CHUNK_LIST_ADTL_NOTE = sourcepp::parser::binary::makeFourCC("note"), // Cue point note
63 //CHUNK_LIST_ADTL_LTXT = sourcepp::parser::binary::makeFourCC("ltxt"), // Section label
64 };
65
66 struct ChunkFMT {
67 uint16_t format;
68 uint16_t channels;
71 uint16_t blockAlign;
72 uint16_t bitsPerSample;
73 std::vector<std::byte> extraCompressionInfo;
74 };
75
76 struct ChunkCUE {
77 struct CuePoint {
78 uint32_t id;
79 int32_t position;
81 uint32_t chunkStart;
82 uint32_t blockStart;
83 uint32_t sampleOffset;
84 };
85
86 std::vector<CuePoint> cuePoints;
87 };
88
89 struct ChunkPLST {
90 struct Segment {
91 uint32_t id;
92 uint32_t length;
93 uint32_t repeats;
94 };
95
96 std::vector<Segment> segments;
97 };
98
99 struct ChunkFACT {
100 uint32_t samples;
101 std::vector<std::byte> extraCompressionInfo;
102 };
103
104 struct ChunkSMPL {
105 struct SampleLoop {
106 uint32_t id;
107 uint32_t type;
108 uint32_t start;
109 uint32_t end;
110 uint32_t fraction;
111 uint32_t playCount;
112 };
113
114 uint32_t manufacturer;
115 uint32_t product;
116 uint32_t samplePeriod;
119 uint32_t smpteFormat;
120 uint32_t smpteOffset;
121 uint32_t sampleLoops;
122 uint32_t samplerData;
123 std::vector<SampleLoop> loops;
124 };
125
126 struct ChunkINST {
128 int8_t fineTune;
129 int8_t gain;
130 uint8_t lowNote;
131 uint8_t highNote;
132 uint8_t lowVelocity;
134 };
135
136 struct ChunkCSET {
137 uint16_t codePage;
138 uint16_t countryCode;
139 uint16_t language;
140 uint16_t dialect;
141 };
142
143 struct ChunkMD5 {
144 std::array<uint8_t, 16> md5;
145 };
146
147 //struct ChunkLISTINFO {
148 // struct META {
149 // ChunkType infoType;
150 // std::string metadata;
151 // };
152 // std::vector<META> metadata;
153 //};
154
155 //struct ChunkLISTADTL {
156 // struct LTXT {
157 // uint32_t sampleLength;
158 // uint32_t purpose;
159 // uint16_t country;
160 // uint16_t language;
161 // uint16_t dialect;
162 // uint16_t codePage;
163 // std::string label;
164 // };
165 // std::vector<std::string> labels;
166 // std::vector<std::string> notes;
167 // std::vector<LTXT> labelTexts;
168 //};
169
170 explicit WAV(uint32_t signature = RIFF_SIGNATURE);
171
172 explicit WAV(std::vector<std::byte>&& wavData);
173
174 explicit WAV(std::span<const std::byte> wavData);
175
176 explicit WAV(const std::filesystem::path& wavPath);
177
178 template<ChunkType Type>
179 [[nodiscard]] auto getFirstWAVChunk() const {
180 return this->getNthWAVChunk<Type>(0);
181 }
182
183 template<ChunkType Type>
184 [[nodiscard]] auto getNthWAVChunk(uint32_t n) const {
185 auto chunkData = this->getNthChunk(Type, n);
186 BufferStreamReadOnly stream{chunkData};
187 if constexpr (Type == CHUNK_FMT) {
188 std::optional<ChunkFMT> chunk = std::nullopt;
189 if (chunkData.size() >= sizeof(uint32_t) * 2 + sizeof(uint16_t) * 4) {
190 chunk = ChunkFMT{};
191 const auto fmtExtraCompressionInfoLength = stream.size() - 16; // size of the standard FMT header
192 stream >> chunk->format >> chunk->channels >> chunk->samplesPerSecond >> chunk->averageBytesPerSecond >> chunk->blockAlign >> chunk->bitsPerSample;
193 if (fmtExtraCompressionInfoLength) {
194 chunk->extraCompressionInfo = stream.read_bytes(fmtExtraCompressionInfoLength);
195 }
196 }
197 return chunk;
198 } else if constexpr (Type == CHUNK_CUE) {
199 std::optional<ChunkCUE> chunk = std::nullopt;
200 if (stream.size() >= sizeof(uint32_t) && stream.size() - sizeof(uint32_t) % sizeof(ChunkCUE::CuePoint) == 0) {
201 chunk = ChunkCUE{};
202 const auto cueNumPoints = stream.read<uint32_t>();
203 for (uint32_t i = 0; i < cueNumPoints; i++) {
204 ChunkCUE::CuePoint point{};
205 stream >> point.id >> point.position >> point.chunk >> point.chunkStart >> point.blockStart >> point.sampleOffset;
206 chunk->cuePoints.push_back(point);
207 }
208 }
209 return chunk;
210 } else if constexpr (Type == CHUNK_PLST) {
211 std::optional<ChunkPLST> chunk = std::nullopt;
212 if (stream.size() >= sizeof(uint32_t) && (stream.size() - sizeof(uint32_t)) % sizeof(ChunkPLST::Segment) == 0) {
213 chunk = ChunkPLST{};
214 const auto plstNumSegments = stream.read<uint32_t>();
215 for (uint32_t i = 0; i < plstNumSegments; i++) {
216 ChunkPLST::Segment segment{};
217 stream >> segment.id >> segment.length >> segment.repeats;
218 chunk->segments.push_back(segment);
219 }
220 }
221 return chunk;
222 } else if constexpr (Type == CHUNK_FACT) {
223 std::optional<ChunkFACT> chunk = std::nullopt;
224 if (stream.size() >= sizeof(uint32_t)) {
225 chunk = ChunkFACT{};
226 const auto factExtraCompressionInfoLength = stream.size() - sizeof(uint32_t);
227 stream >> chunk->samples;
228 if (factExtraCompressionInfoLength) {
229 chunk->extraCompressionInfo = stream.read_bytes(factExtraCompressionInfoLength);
230 }
231 }
232 return chunk;
233 } else if constexpr (Type == CHUNK_SMPL) {
234 std::optional<ChunkSMPL> chunk = std::nullopt;
235 if (stream.size() >= sizeof(uint32_t) * 10) {
236 chunk = ChunkSMPL{};
237 stream >> chunk->manufacturer >> chunk->product >> chunk->samplePeriod >> chunk->midiUnityNote >> chunk->midiPitchFraction >> chunk->smpteFormat >> chunk->smpteOffset >> chunk->sampleLoops >> chunk->samplerData;
238 const auto smplNumLoops = stream.read<uint32_t>();
239 for (uint32_t i = 0; i < smplNumLoops; i++) {
240 // ReSharper disable once CppUseStructuredBinding
241 auto& sampleLoop = chunk->loops.emplace_back();
242 stream >> sampleLoop.id >> sampleLoop.type >> sampleLoop.start >> sampleLoop.end >> sampleLoop.fraction >> sampleLoop.playCount;
243 }
244 }
245 return chunk;
246 } else if constexpr (Type == CHUNK_INST) {
247 std::optional<ChunkINST> chunk = std::nullopt;
248 if (stream.size() == sizeof(uint8_t) * 7) {
249 chunk = ChunkINST{};
250 stream >> chunk->unshiftedNote >> chunk->fineTune >> chunk->gain >> chunk->lowNote >> chunk->highNote >> chunk->lowVelocity >> chunk->highVelocity;
251 }
252 return chunk;
253 } else if constexpr (Type == CHUNK_CSET) {
254 std::optional<ChunkCSET> chunk = std::nullopt;
255 if (stream.size() == sizeof(uint16_t) * 4) {
256 chunk = ChunkCSET{};
257 stream >> chunk->codePage >> chunk->countryCode >> chunk->language >> chunk->dialect;
258 }
259 return chunk;
260 } else if constexpr (Type == CHUNK_MD5) {
261 std::optional<ChunkMD5> chunk = std::nullopt;
262 if (stream.size() == sizeof(uint8_t) * 16) {
263 chunk = ChunkMD5{};
264 stream >> chunk->md5;
265 }
266 return chunk;
267 } else {
268 return this->hasNthChunk(Type, n) ? std::optional{std::move(chunkData)} : std::nullopt;
269 }
270 }
271};
272
273} // namespace sndpp
std::vector< std::byte > getNthChunk(uint32_t chunkType, uint32_t n) const
Definition RIFF.cpp:91
uint32_t signature
Definition RIFF.h:43
RIFF(uint32_t type, uint32_t signature=RIFF_SIGNATURE)
Definition RIFF.cpp:11
bool hasNthChunk(uint32_t chunkType, uint32_t n) const
Definition RIFF.cpp:84
WAV(uint32_t signature=RIFF_SIGNATURE)
Definition WAV.cpp:5
ChunkType
Definition WAV.h:16
@ CHUNK_FACT
Definition WAV.h:21
@ CHUNK_JUNK
Definition WAV.h:27
@ CHUNK_PLST
Definition WAV.h:20
@ CHUNK_FMT
Definition WAV.h:17
@ CHUNK_MD5
Definition WAV.h:25
@ CHUNK_SMPL
Definition WAV.h:22
@ CHUNK_CSET
Definition WAV.h:24
@ CHUNK_DATA
Definition WAV.h:18
@ CHUNK_PAD
Definition WAV.h:26
@ CHUNK_FLLR
Definition WAV.h:28
@ CHUNK_INST
Definition WAV.h:23
@ CHUNK_CUE
Definition WAV.h:19
auto getFirstWAVChunk() const
Definition WAV.h:179
auto getNthWAVChunk(uint32_t n) const
Definition WAV.h:184
Definition RIFF.h:10
constexpr auto RIFF_SIGNATURE
Definition RIFF.h:12
constexpr auto WAV_TYPE
Definition WAV.h:12
consteval uint32_t makeFourCC(const char fourCC[4])
Creates a FourCC identifier from a string of 4 characters.
Definition Binary.h:20
uint16_t codePage
Definition WAV.h:137
uint16_t dialect
Definition WAV.h:140
uint16_t language
Definition WAV.h:139
uint16_t countryCode
Definition WAV.h:138
std::vector< CuePoint > cuePoints
Definition WAV.h:86
std::vector< std::byte > extraCompressionInfo
Definition WAV.h:101
uint32_t samples
Definition WAV.h:100
uint16_t channels
Definition WAV.h:68
uint16_t format
Definition WAV.h:67
uint32_t samplesPerSecond
Definition WAV.h:69
uint16_t bitsPerSample
Definition WAV.h:72
uint16_t blockAlign
Definition WAV.h:71
std::vector< std::byte > extraCompressionInfo
Definition WAV.h:73
uint32_t averageBytesPerSecond
Definition WAV.h:70
uint8_t highVelocity
Definition WAV.h:133
uint8_t unshiftedNote
Definition WAV.h:127
uint8_t highNote
Definition WAV.h:131
uint8_t lowNote
Definition WAV.h:130
uint8_t lowVelocity
Definition WAV.h:132
std::array< uint8_t, 16 > md5
Definition WAV.h:144
std::vector< Segment > segments
Definition WAV.h:96
uint32_t product
Definition WAV.h:115
uint32_t midiUnityNote
Definition WAV.h:117
uint32_t samplerData
Definition WAV.h:122
std::vector< SampleLoop > loops
Definition WAV.h:123
uint32_t smpteFormat
Definition WAV.h:119
uint32_t midiPitchFraction
Definition WAV.h:118
uint32_t sampleLoops
Definition WAV.h:121
uint32_t samplePeriod
Definition WAV.h:116
uint32_t manufacturer
Definition WAV.h:114
uint32_t smpteOffset
Definition WAV.h:120