Commit 0ad2eb34 authored by Max Kellermann's avatar Max Kellermann

decoder/dsdlib: add class DsdUint64

Merge lots of duplicate code.
parent 0e8a15e8
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#ifndef MPD_DECODER_DSDLIB_HXX #ifndef MPD_DECODER_DSDLIB_HXX
#define MPD_DECODER_DSDLIB_HXX #define MPD_DECODER_DSDLIB_HXX
#include "system/ByteOrder.hxx"
#include "Compiler.h" #include "Compiler.h"
#include <stddef.h> #include <stddef.h>
...@@ -35,6 +36,17 @@ struct DsdId { ...@@ -35,6 +36,17 @@ struct DsdId {
bool Equals(const char *s) const; bool Equals(const char *s) const;
}; };
class DsdUint64 {
uint32_t lo;
uint32_t hi;
public:
constexpr uint64_t Read() const {
return (uint64_t(FromLE32(hi)) << 32) |
uint64_t(FromLE32(lo));
}
};
bool bool
dsdlib_read(Decoder *decoder, InputStream &is, dsdlib_read(Decoder *decoder, InputStream &is,
void *data, size_t length); void *data, size_t length);
......
...@@ -43,22 +43,21 @@ ...@@ -43,22 +43,21 @@
struct DsdiffHeader { struct DsdiffHeader {
DsdId id; DsdId id;
uint32_t size_high, size_low; DsdUint64 size;
DsdId format; DsdId format;
}; };
struct DsdiffChunkHeader { struct DsdiffChunkHeader {
DsdId id; DsdId id;
uint32_t size_high, size_low; DsdUint64 size;
/** /**
* Read the "size" attribute from the specified header, converting it * Read the "size" attribute from the specified header, converting it
* to the host byte order if needed. * to the host byte order if needed.
*/ */
gcc_const constexpr
uint64_t GetSize() const { uint64_t GetSize() const {
return (uint64_t(FromBE32(size_high)) << 32) | return size.Read();
uint64_t(FromBE32(size_low));
} }
}; };
......
...@@ -56,11 +56,11 @@ struct DsfHeader { ...@@ -56,11 +56,11 @@ struct DsfHeader {
/** DSF header id: "DSD " */ /** DSF header id: "DSD " */
DsdId id; DsdId id;
/** DSD chunk size, including id = 28 */ /** DSD chunk size, including id = 28 */
uint32_t size_low, size_high; DsdUint64 size;
/** total file size */ /** total file size */
uint32_t fsize_low, fsize_high; DsdUint64 fsize;
/** pointer to id3v2 metadata, should be at the end of the file */ /** pointer to id3v2 metadata, should be at the end of the file */
uint32_t pmeta_low, pmeta_high; DsdUint64 pmeta;
}; };
/** DSF file fmt chunk */ /** DSF file fmt chunk */
...@@ -68,7 +68,7 @@ struct DsfFmtChunk { ...@@ -68,7 +68,7 @@ struct DsfFmtChunk {
/** id: "fmt " */ /** id: "fmt " */
DsdId id; DsdId id;
/** fmt chunk size, including id, normally 52 */ /** fmt chunk size, including id, normally 52 */
uint32_t size_low, size_high; DsdUint64 size;
/** version of this format = 1 */ /** version of this format = 1 */
uint32_t version; uint32_t version;
/** 0: DSD raw */ /** 0: DSD raw */
...@@ -82,7 +82,7 @@ struct DsfFmtChunk { ...@@ -82,7 +82,7 @@ struct DsfFmtChunk {
/** bits per sample 1 or 8 */ /** bits per sample 1 or 8 */
uint32_t bitssample; uint32_t bitssample;
/** Sample count per channel in bytes */ /** Sample count per channel in bytes */
uint32_t scnt_low, scnt_high; DsdUint64 scnt;
/** block size per channel = 4096 */ /** block size per channel = 4096 */
uint32_t block_size; uint32_t block_size;
/** reserved, should be all zero */ /** reserved, should be all zero */
...@@ -92,7 +92,7 @@ struct DsfFmtChunk { ...@@ -92,7 +92,7 @@ struct DsfFmtChunk {
struct DsfDataChunk { struct DsfDataChunk {
DsdId id; DsdId id;
/** "data" chunk size, includes header (id+size) */ /** "data" chunk size, includes header (id+size) */
uint32_t size_low, size_high; DsdUint64 size;
}; };
/** /**
...@@ -102,22 +102,17 @@ static bool ...@@ -102,22 +102,17 @@ static bool
dsf_read_metadata(Decoder *decoder, InputStream &is, dsf_read_metadata(Decoder *decoder, InputStream &is,
DsfMetaData *metadata) DsfMetaData *metadata)
{ {
uint64_t chunk_size;
DsfHeader dsf_header; DsfHeader dsf_header;
if (!dsdlib_read(decoder, is, &dsf_header, sizeof(dsf_header)) || if (!dsdlib_read(decoder, is, &dsf_header, sizeof(dsf_header)) ||
!dsf_header.id.Equals("DSD ")) !dsf_header.id.Equals("DSD "))
return false; return false;
chunk_size = (uint64_t(FromLE32(dsf_header.size_high)) << 32) | const uint64_t chunk_size = dsf_header.size.Read();
uint64_t(FromLE32(dsf_header.size_low));
if (sizeof(dsf_header) != chunk_size) if (sizeof(dsf_header) != chunk_size)
return false; return false;
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
uint64_t metadata_offset; const uint64_t metadata_offset = dsf_header.pmeta.Read();
metadata_offset = (uint64_t(FromLE32(dsf_header.pmeta_high)) << 32) |
uint64_t(FromLE32(dsf_header.pmeta_low));
#endif #endif
/* read the 'fmt ' chunk of the DSF file */ /* read the 'fmt ' chunk of the DSF file */
...@@ -126,10 +121,7 @@ dsf_read_metadata(Decoder *decoder, InputStream &is, ...@@ -126,10 +121,7 @@ dsf_read_metadata(Decoder *decoder, InputStream &is,
!dsf_fmt_chunk.id.Equals("fmt ")) !dsf_fmt_chunk.id.Equals("fmt "))
return false; return false;
uint64_t fmt_chunk_size; const uint64_t fmt_chunk_size = dsf_fmt_chunk.size.Read();
fmt_chunk_size = (uint64_t(FromLE32(dsf_fmt_chunk.size_high)) << 32) |
uint64_t(FromLE32(dsf_fmt_chunk.size_low));
if (fmt_chunk_size != sizeof(dsf_fmt_chunk)) if (fmt_chunk_size != sizeof(dsf_fmt_chunk))
return false; return false;
...@@ -158,9 +150,7 @@ dsf_read_metadata(Decoder *decoder, InputStream &is, ...@@ -158,9 +150,7 @@ dsf_read_metadata(Decoder *decoder, InputStream &is,
/* data size of DSF files are padded to multiple of 4096, /* data size of DSF files are padded to multiple of 4096,
we use the actual data size as chunk size */ we use the actual data size as chunk size */
uint64_t data_size; uint64_t data_size = data_chunk.size.Read();
data_size = (uint64_t(FromLE32(data_chunk.size_high)) << 32) |
uint64_t(FromLE32(data_chunk.size_low));
data_size -= sizeof(data_chunk); data_size -= sizeof(data_chunk);
metadata->chunk_size = data_size; metadata->chunk_size = data_size;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment