void DSFHeader::parse(const TagLib::ByteVector &data) { if (data.size() < DSD_HEADER_SIZE + FMT_HEADER_SIZE) { std::cerr <<"DSFHeader::parse(): header size incorrect" << std::endl; return; } const char *hdr = data.data(); size_t offset = 0; // // ******** DSD chunk header ******** // DSD header chunk should start with "DSD ". // if (hdr[0] != 'D' || hdr[1] != 'S' || hdr[2] != 'D' || hdr[3] != ' ') { std::cerr <<"DSD::Header::parse(): DSD header's first 4 bytes != 'DSD '" << std::endl; return; } offset += 4; // The next 8 bytes contain the size of DSD header // (numerical data is stored in little endian) if (data.toLongLong(offset, false) != DSD_HEADER_SIZE) { std::cerr <<"DSD::Header::parse(): DSD header size is incorrect" << std::endl; return; } offset += LONG_INT_SIZE; // The next 8 bytes contains the file size d->fileSize = bytesToUInt64(&hdr[0], offset); offset += LONG_INT_SIZE; // The next 8 bytes contains the offset to id3v2 tag (0 if not exists) d->ID3v2Offset = bytesToUInt64(&hdr[0], offset); offset += LONG_INT_SIZE; // // ********* FMT chunk ******** // // FMT header chunk should start with "fmt ". // if (hdr[offset] != 'f' || hdr[offset + 1] != 'm' || hdr[offset + 2] != 't' || hdr[offset + 3] != ' ') { std::cerr <<"DSD::Header::parse(): FMT header's first 4 bytes != 'fmt '" << std::endl; return; } offset += 4; // The next 8 bytes contain the size of FMT header, which should be 52 if (data.toLongLong(offset, false) != FMT_HEADER_SIZE) { std::cerr <<"DSD::Header::parse(): FMT header size is incorrect" << std::endl; return; } offset += LONG_INT_SIZE; // Format version // There's only version 1 for now... unsigned int ver = data.toUInt(offset, false); if (ver != 1) { std::cerr <<"DSD::Header::parse(): format version != 1" << std::endl; return; } d->version = static_cast<Version>(ver); offset += INT_SIZE; // Format ID if (data.toUInt(offset, false) != 0) { std::cerr <<"DSD::Header::parse(): format ID != 0" << std::endl; return; } offset += INT_SIZE; // Channel Type unsigned int ct = data.toUInt(offset, false); if (ct < 1 || ct > 7) { std::cerr <<"DSD::Header::parse(): channel type out of range" << std::endl; return; } d->channelType = static_cast<ChannelType>(ct); offset += INT_SIZE; // Channel Num d->channelNum = data.toUInt(offset, false); if (d->channelNum < MinType || d->channelNum > MaxType) { std::cerr <<"DSD::Header::parse(): channel num out of range" << std::endl; return; } offset += INT_SIZE; // Sampling frequency d->sampleRate = data.toUInt(offset, false); if (d->sampleRate != 2822400 && d->sampleRate != 5644800) { std::cerr <<"DSD::Header::parse(): invalid sampling frequency" << std::endl; return; } offset += INT_SIZE; // Bits per sample d->bitsPerSample = data.toUInt(offset, false); if (d->bitsPerSample != 1 && d->bitsPerSample != 8) { std::cerr <<"DSD::Header::parse(): bits per sample invalid" << std::endl; return; } offset += INT_SIZE; // Sample count d->sampleCount = bytesToUInt64(&hdr[0], offset); offset += LONG_INT_SIZE; // Block size per channel if (data.toUInt(offset, false) != 4096) { std::cerr <<"DSD::Header::parse(): block size != 4096" << std::endl; return; } //offset += 4; // Reserved // offset += 4; d->isValid = true; }