212 [[nodiscard]]
auto get(uint32_t n = 0)
const {
214 BufferStreamReadOnly stream{chunkData};
216 std::optional<ChunkFMT> chunk = std::nullopt;
217 if (chunkData.size() >=
sizeof(uint32_t) * 2 +
sizeof(uint16_t) * 4) {
219 const auto fmtExtraCompressionInfoLength = stream.size() - 16;
220 stream >> chunk->
format >> chunk->channels >> chunk->samplesPerSecond >> chunk->averageBytesPerSecond >> chunk->blockAlign >> chunk->bitsPerSample;
221 if (fmtExtraCompressionInfoLength) {
222 chunk->extraCompressionInfo = stream.read_bytes(fmtExtraCompressionInfoLength);
226 }
else if constexpr (Type ==
CHUNK_CUE) {
227 std::optional<ChunkCUE> chunk = std::nullopt;
228 if (stream.size() >=
sizeof(uint32_t) && stream.size() -
sizeof(uint32_t) %
sizeof(
ChunkCUE::CuePoint) == 0) {
230 const auto cueNumPoints = stream.read<uint32_t>();
231 for (uint32_t i = 0; i < cueNumPoints; i++) {
234 chunk->cuePoints.push_back(point);
239 std::optional<ChunkPLST> chunk = std::nullopt;
240 if (stream.size() >=
sizeof(uint32_t) && (stream.size() -
sizeof(uint32_t)) %
sizeof(
ChunkPLST::Segment) == 0) {
242 const auto plstNumSegments = stream.read<uint32_t>();
243 for (uint32_t i = 0; i < plstNumSegments; i++) {
246 chunk->segments.push_back(segment);
251 std::optional<ChunkFACT> chunk = std::nullopt;
252 if (stream.size() >=
sizeof(uint32_t)) {
254 const auto factExtraCompressionInfoLength = stream.size() -
sizeof(uint32_t);
256 if (factExtraCompressionInfoLength) {
257 chunk->extraCompressionInfo = stream.read_bytes(factExtraCompressionInfoLength);
262 std::optional<ChunkSMPL> chunk = std::nullopt;
263 if (stream.size() >=
sizeof(uint32_t) * 10) {
265 stream >> chunk->
manufacturer >> chunk->product >> chunk->samplePeriod >> chunk->midiUnityNote >> chunk->midiPitchFraction >> chunk->smpteFormat >> chunk->smpteOffset >> chunk->sampleLoops >> chunk->samplerData;
266 const auto smplNumLoops = stream.read<uint32_t>();
267 for (uint32_t i = 0; i < smplNumLoops; i++) {
269 auto& sampleLoop = chunk->loops.emplace_back();
270 stream >> sampleLoop.id >> sampleLoop.type >> sampleLoop.start >> sampleLoop.end >> sampleLoop.fraction >> sampleLoop.playCount;
275 std::optional<ChunkINST> chunk = std::nullopt;
276 if (stream.size() ==
sizeof(uint8_t) * 7) {
278 stream >> chunk->
unshiftedNote >> chunk->fineTune >> chunk->gain >> chunk->lowNote >> chunk->highNote >> chunk->lowVelocity >> chunk->highVelocity;
282 std::optional<ChunkCSET> chunk = std::nullopt;
283 if (stream.size() ==
sizeof(uint16_t) * 4) {
285 stream >> chunk->
codePage >> chunk->countryCode >> chunk->language >> chunk->dialect;
288 }
else if constexpr (Type ==
CHUNK_MD5) {
289 std::optional<ChunkMD5> chunk = std::nullopt;
290 if (stream.size() ==
sizeof(uint8_t) * 16) {
292 stream >> chunk->
md5;
296 std::optional<ChunkVDAT> chunk = std::nullopt;
297 if (stream.size() > 0) {
300 std::string backingString;
305 .
parse({
reinterpret_cast<const char*
>(chunkData.data()), chunkData.size()}, backingString);
307 while (tokens.tell() < tokens.size()) {
309 auto token = tokens.next();
313 }
else if (token ==
"PLAINTEXT") {
314 if (tokens.next() !=
"{") {
317 for (token = tokens.next(); token !=
"}"; token = tokens.next()) {
324 }
else if (token ==
"WORDS") {
325 if (tokens.next() !=
"{") {
328 while ((token = tokens.next()) ==
"WORD") {
329 auto& word = vdat.
words.emplace_back();
330 word.word = tokens.next();
331 tokens.next(word.startTime);
332 tokens.next(word.endTime);
333 if ((token = tokens.next()) !=
"{") {
336 while (tokens.peek() !=
"}") {
337 auto& phoneme = word.phonemes.emplace_back();
338 tokens.next(phoneme.code);
339 phoneme.name = tokens.next();
340 tokens.next(phoneme.startTime);
341 tokens.next(phoneme.endTime);
342 tokens.next(phoneme.volume);
346 }
else if (token ==
"EMPHASIS") {
347 if ((token = tokens.next()) !=
"{") {
350 while (tokens.peek() !=
"}") {
351 auto& emphasis = vdat.
emphasis.emplace_back();
352 tokens.next(emphasis.time);
353 tokens.next(emphasis.value);
356 }
else if (token ==
"OPTIONS") {
357 if ((token = tokens.next()) !=
"{") {
360 for (token = tokens.next(); token !=
"}"; token = tokens.next()) {
361 vdat.
options[std::string{token}] = tokens.next();
371 return this->
hasNthChunk(Type, n) ? std::optional{std::move(chunkData)} : std::nullopt;