decoder/dsdlib: add class DsdUint64
Merge lots of duplicate code.
This commit is contained in:
parent
0e8a15e813
commit
0ad2eb34c7
|
@ -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 {
|
||||||
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 @@
|
||||||
|
|
||||||
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 {
|
||||||
/** 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 {
|
||||||
/** 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 {
|
||||||
/** 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 {
|
||||||
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
|
||||||
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,
|
||||||
!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,
|
||||||
/* 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;
|
||||||
|
|
Loading…
Reference in New Issue