216 BufferStreamReadOnly stream{chunkData};
218 std::optional<ChunkFMT> chunk = std::nullopt;
219 if (chunkData.size() >=
sizeof(uint32_t) * 2 +
sizeof(uint16_t) * 4) {
221 const auto fmtExtraCompressionInfoLength = stream.size() - 16;
222 stream >> chunk->
format >> chunk->channels >> chunk->samplesPerSecond >> chunk->averageBytesPerSecond >> chunk->blockAlign >> chunk->bitsPerSample;
223 if (fmtExtraCompressionInfoLength) {
224 chunk->extraCompressionInfo = stream.read_bytes(fmtExtraCompressionInfoLength);
228 }
else if constexpr (Type ==
CHUNK_CUE) {
229 std::optional<ChunkCUE> chunk = std::nullopt;
230 if (stream.size() >=
sizeof(uint32_t) && stream.size() -
sizeof(uint32_t) %
sizeof(
ChunkCUE::CuePoint) == 0) {
232 const auto cueNumPoints = stream.read<uint32_t>();
233 for (uint32_t i = 0; i < cueNumPoints; i++) {
236 chunk->cuePoints.push_back(point);
241 std::optional<ChunkPLST> chunk = std::nullopt;
242 if (stream.size() >=
sizeof(uint32_t) && (stream.size() -
sizeof(uint32_t)) %
sizeof(
ChunkPLST::Segment) == 0) {
244 const auto plstNumSegments = stream.read<uint32_t>();
245 for (uint32_t i = 0; i < plstNumSegments; i++) {
248 chunk->segments.push_back(segment);
253 std::optional<ChunkFACT> chunk = std::nullopt;
254 if (stream.size() >=
sizeof(uint32_t)) {
256 const auto factExtraCompressionInfoLength = stream.size() -
sizeof(uint32_t);
258 if (factExtraCompressionInfoLength) {
259 chunk->extraCompressionInfo = stream.read_bytes(factExtraCompressionInfoLength);
264 std::optional<ChunkSMPL> chunk = std::nullopt;
265 if (stream.size() >=
sizeof(uint32_t) * 10) {
267 stream >> chunk->
manufacturer >> chunk->product >> chunk->samplePeriod >> chunk->midiUnityNote >> chunk->midiPitchFraction >> chunk->smpteFormat >> chunk->smpteOffset >> chunk->sampleLoops >> chunk->samplerData;
268 const auto smplNumLoops = stream.read<uint32_t>();
269 for (uint32_t i = 0; i < smplNumLoops; i++) {
271 auto& sampleLoop = chunk->loops.emplace_back();
272 stream >> sampleLoop.id >> sampleLoop.type >> sampleLoop.start >> sampleLoop.end >> sampleLoop.fraction >> sampleLoop.playCount;
277 std::optional<ChunkINST> chunk = std::nullopt;
278 if (stream.size() ==
sizeof(uint8_t) * 7) {
280 stream >> chunk->
unshiftedNote >> chunk->fineTune >> chunk->gain >> chunk->lowNote >> chunk->highNote >> chunk->lowVelocity >> chunk->highVelocity;
284 std::optional<ChunkCSET> chunk = std::nullopt;
285 if (stream.size() ==
sizeof(uint16_t) * 4) {
287 stream >> chunk->
codePage >> chunk->countryCode >> chunk->language >> chunk->dialect;
290 }
else if constexpr (Type ==
CHUNK_MD5) {
291 std::optional<ChunkMD5> chunk = std::nullopt;
292 if (stream.size() ==
sizeof(uint8_t) * 16) {
294 stream >> chunk->
md5;
298 std::optional<ChunkVDAT> chunk = std::nullopt;
299 if (stream.size() > 0) {
301 const auto getToken = [&stream] {
303 if (stream.tell() >= stream.size()) {
306 bool gotToken =
false;
307 char c = stream.read<
char>();
309 if (!gotToken && std::isspace(c)) {
311 }
else if (!gotToken && !std::isspace(c)) {
314 }
else if (gotToken && !std::isspace(c)) {
316 }
else if (gotToken && std::isspace(c)) {
319 c = stream.read<
char>();
323 std::string token = getToken();
324 while (!token.empty()) {
325 if (token ==
"VERSION") {
327 chunk->version = std::stof(token);
328 }
else if (token ==
"PLAINTEXT") {
332 chunk->plaintext += token;
334 if (token.empty() || token ==
"}")
336 chunk->plaintext +=
' ';
338 }
else if (token ==
"WORDS") {
341 while (token ==
"WORD") {
343 word.
word = getToken();
345 word.
endTime = std::stof(getToken());
348 while (token !=
"}") {
350 phoneme.
code = std::stoi(token);
351 phoneme.
name = getToken();
352 phoneme.
startTime = std::stof(getToken());
353 phoneme.
endTime = std::stof(getToken());
354 phoneme.
volume = std::stof(getToken());
358 chunk->words.push_back(word);
361 }
else if (token ==
"EMPHASIS") {
364 while (token !=
"}") {
366 emphasis.
time = std::stof(token);
367 emphasis.
value = std::stof(getToken());
368 chunk->emphasis.push_back(emphasis);
371 }
else if (token ==
"OPTIONS") {
374 while (token !=
"}") {
375 chunk->options[token] = getToken();
384 return this->
hasNthChunk(Type, n) ? std::optional{std::move(chunkData)} : std::nullopt;