mirror of
https://github.com/mhx/dwarfs.git
synced 2025-09-10 21:10:02 -04:00
CAF format support
This commit is contained in:
parent
e08bbb5e94
commit
4bcbb3bfe9
@ -31,6 +31,7 @@
|
|||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <folly/Synchronized.h>
|
#include <folly/Synchronized.h>
|
||||||
|
#include <folly/lang/Bits.h>
|
||||||
|
|
||||||
#include "dwarfs/categorizer.h"
|
#include "dwarfs/categorizer.h"
|
||||||
#include "dwarfs/error.h"
|
#include "dwarfs/error.h"
|
||||||
@ -38,21 +39,31 @@
|
|||||||
|
|
||||||
namespace dwarfs {
|
namespace dwarfs {
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr std::string_view const METADATA_CATEGORY{"metadata"};
|
||||||
constexpr std::string_view const PCMAUDIO_CATEGORY{"pcmaudio"};
|
constexpr std::string_view const PCMAUDIO_CATEGORY{"pcmaudio"};
|
||||||
|
|
||||||
|
constexpr size_t const MIN_PCMAUDIO_SIZE{512};
|
||||||
|
|
||||||
enum class endianness : uint8_t {
|
enum class endianness : uint8_t {
|
||||||
BIG,
|
BIG,
|
||||||
LITTLE,
|
LITTLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class signedness : uint8_t {
|
enum class signedness : uint8_t {
|
||||||
SIGNED,
|
SIGNED,
|
||||||
UNSIGNED,
|
UNSIGNED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class padding : uint8_t {
|
||||||
|
LSB,
|
||||||
|
MSB,
|
||||||
|
};
|
||||||
|
|
||||||
char const* endianness_string(endianness e) {
|
char const* endianness_string(endianness e) {
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case endianness::BIG:
|
case endianness::BIG:
|
||||||
@ -71,10 +82,21 @@ char const* signedness_string(signedness s) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char const* padding_string(padding p) {
|
||||||
|
switch (p) {
|
||||||
|
case padding::LSB:
|
||||||
|
return "lsb";
|
||||||
|
case padding::MSB:
|
||||||
|
return "msb";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct pcmaudio_metadata {
|
struct pcmaudio_metadata {
|
||||||
endianness sample_endianness;
|
endianness sample_endianness;
|
||||||
signedness sample_signedness;
|
signedness sample_signedness;
|
||||||
|
padding sample_padding;
|
||||||
uint8_t bits_per_sample;
|
uint8_t bits_per_sample;
|
||||||
|
uint8_t bytes_per_sample;
|
||||||
uint16_t number_of_channels;
|
uint16_t number_of_channels;
|
||||||
|
|
||||||
//// Sample rate should be irrelevant
|
//// Sample rate should be irrelevant
|
||||||
@ -83,6 +105,16 @@ struct pcmaudio_metadata {
|
|||||||
auto operator<=>(pcmaudio_metadata const&) const = default;
|
auto operator<=>(pcmaudio_metadata const&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, pcmaudio_metadata const& m) {
|
||||||
|
os << "[" << endianness_string(m.sample_endianness) << ", "
|
||||||
|
<< signedness_string(m.sample_signedness) << ", "
|
||||||
|
<< padding_string(m.sample_padding) << ", "
|
||||||
|
<< "bits=" << static_cast<int>(m.bits_per_sample) << ", "
|
||||||
|
<< "bytes=" << static_cast<int>(m.bytes_per_sample) << ", "
|
||||||
|
<< "channels=" << static_cast<int>(m.number_of_channels) << "]";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
class pcmaudio_metadata_store {
|
class pcmaudio_metadata_store {
|
||||||
public:
|
public:
|
||||||
pcmaudio_metadata_store() = default;
|
pcmaudio_metadata_store() = default;
|
||||||
@ -103,6 +135,8 @@ class pcmaudio_metadata_store {
|
|||||||
folly::dynamic obj = folly::dynamic::object;
|
folly::dynamic obj = folly::dynamic::object;
|
||||||
obj.insert("endianness", endianness_string(m.sample_endianness));
|
obj.insert("endianness", endianness_string(m.sample_endianness));
|
||||||
obj.insert("signedness", signedness_string(m.sample_signedness));
|
obj.insert("signedness", signedness_string(m.sample_signedness));
|
||||||
|
obj.insert("padding", padding_string(m.sample_padding));
|
||||||
|
obj.insert("bytes_per_sample", m.bytes_per_sample);
|
||||||
obj.insert("bits_per_sample", m.bits_per_sample);
|
obj.insert("bits_per_sample", m.bits_per_sample);
|
||||||
obj.insert("number_of_channels", m.number_of_channels);
|
obj.insert("number_of_channels", m.number_of_channels);
|
||||||
return obj;
|
return obj;
|
||||||
@ -125,7 +159,7 @@ class pcmaudio_categorizer_ final : public pcmaudio_categorizer_base {
|
|||||||
: LOG_PROXY_INIT(lgr) {}
|
: LOG_PROXY_INIT(lgr) {}
|
||||||
|
|
||||||
inode_fragments
|
inode_fragments
|
||||||
categorize(std::filesystem::path const& path, std::span<uint8_t const> data,
|
categorize(fs::path const& path, std::span<uint8_t const> data,
|
||||||
category_mapper const& mapper) const override;
|
category_mapper const& mapper) const override;
|
||||||
|
|
||||||
bool is_single_fragment() const override { return false; }
|
bool is_single_fragment() const override { return false; }
|
||||||
@ -141,6 +175,19 @@ class pcmaudio_categorizer_ final : public pcmaudio_categorizer_base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool check_aiff(inode_fragments& frag, fs::path const& path,
|
||||||
|
std::span<uint8_t const> data,
|
||||||
|
category_mapper const& mapper) const;
|
||||||
|
bool
|
||||||
|
check_caf(inode_fragments& frag, fs::path const& path,
|
||||||
|
std::span<uint8_t const> data, category_mapper const& mapper) const;
|
||||||
|
bool
|
||||||
|
check_wav(inode_fragments& frag, fs::path const& path,
|
||||||
|
std::span<uint8_t const> data, category_mapper const& mapper) const;
|
||||||
|
bool check_wav64(inode_fragments& frag, fs::path const& path,
|
||||||
|
std::span<uint8_t const> data,
|
||||||
|
category_mapper const& mapper) const;
|
||||||
|
|
||||||
LOG_PROXY_DECL(LoggerPolicy);
|
LOG_PROXY_DECL(LoggerPolicy);
|
||||||
folly::Synchronized<pcmaudio_metadata_store> mutable meta_;
|
folly::Synchronized<pcmaudio_metadata_store> mutable meta_;
|
||||||
};
|
};
|
||||||
@ -148,18 +195,367 @@ class pcmaudio_categorizer_ final : public pcmaudio_categorizer_base {
|
|||||||
std::span<std::string_view const>
|
std::span<std::string_view const>
|
||||||
pcmaudio_categorizer_base::categories() const {
|
pcmaudio_categorizer_base::categories() const {
|
||||||
static constexpr std::array const s_categories{
|
static constexpr std::array const s_categories{
|
||||||
|
METADATA_CATEGORY,
|
||||||
PCMAUDIO_CATEGORY,
|
PCMAUDIO_CATEGORY,
|
||||||
};
|
};
|
||||||
return s_categories;
|
return s_categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename LoggerPolicy>
|
||||||
|
bool pcmaudio_categorizer_<LoggerPolicy>::check_aiff(
|
||||||
|
inode_fragments& frag, fs::path const& path, std::span<uint8_t const> data,
|
||||||
|
category_mapper const& mapper) const {
|
||||||
|
if (std::memcmp(data.data(), "FORM", 4) != 0 ||
|
||||||
|
std::memcmp(data.data() + 8, "AIFF", 4) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOLLY_PACK_PUSH
|
||||||
|
|
||||||
|
struct chk_hdr_t {
|
||||||
|
char id[4];
|
||||||
|
uint32_t size;
|
||||||
|
} FOLLY_PACK_ATTR;
|
||||||
|
|
||||||
|
struct comm_chk_t {
|
||||||
|
uint16_t num_chan;
|
||||||
|
uint32_t num_sample_frames;
|
||||||
|
uint16_t sample_size;
|
||||||
|
// long double sample_rate; // we can't pack this :/
|
||||||
|
} FOLLY_PACK_ATTR;
|
||||||
|
|
||||||
|
struct ssnd_chk_t {
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t block_size;
|
||||||
|
} FOLLY_PACK_ATTR;
|
||||||
|
|
||||||
|
FOLLY_PACK_POP
|
||||||
|
|
||||||
|
static_assert(sizeof(chk_hdr_t) == 8);
|
||||||
|
static_assert(sizeof(comm_chk_t) == 8);
|
||||||
|
static_assert(sizeof(ssnd_chk_t) == 8);
|
||||||
|
|
||||||
|
bool meta_valid{false};
|
||||||
|
uint32_t num_sample_frames;
|
||||||
|
pcmaudio_metadata meta;
|
||||||
|
size_t pos = 12;
|
||||||
|
chk_hdr_t chk_hdr;
|
||||||
|
|
||||||
|
while (pos + sizeof(chk_hdr) <= data.size()) {
|
||||||
|
std::memcpy(&chk_hdr, data.data() + pos, sizeof(chk_hdr));
|
||||||
|
uint32_t chk_size = folly::Endian::big(chk_hdr.size);
|
||||||
|
|
||||||
|
LOG_TRACE << "[AIFF] " << path << ": " << std::string_view(chk_hdr.id, 4)
|
||||||
|
<< " (len=" << chk_size << ")";
|
||||||
|
|
||||||
|
if (pos + sizeof(chk_hdr) + chk_size > data.size()) {
|
||||||
|
LOG_WARN << "[AIFF] " << path << ": unexpected end of file";
|
||||||
|
// corrupt AIFF? -> skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::memcmp(chk_hdr.id, "COMM", 4) == 0) {
|
||||||
|
if (chk_size != 18) {
|
||||||
|
LOG_WARN << "[AIFF] " << path
|
||||||
|
<< ": unexpected size for COMM chunk: " << chk_size
|
||||||
|
<< " (expected 18)";
|
||||||
|
// corrupt AIFF? -> skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meta_valid) {
|
||||||
|
LOG_WARN << "[AIFF] " << path << ": unexpected second COMM chunk";
|
||||||
|
// corrupt AIFF? -> skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
comm_chk_t comm;
|
||||||
|
std::memcpy(&comm, data.data() + pos + sizeof(chk_hdr), sizeof(comm));
|
||||||
|
|
||||||
|
meta.sample_endianness = endianness::BIG;
|
||||||
|
meta.sample_signedness = signedness::SIGNED;
|
||||||
|
meta.sample_padding = padding::LSB;
|
||||||
|
meta.bits_per_sample = folly::Endian::big(comm.sample_size);
|
||||||
|
meta.bytes_per_sample = (meta.bits_per_sample + 7) / 8;
|
||||||
|
meta.number_of_channels = folly::Endian::big(comm.num_chan);
|
||||||
|
num_sample_frames = folly::Endian::big(comm.num_sample_frames);
|
||||||
|
|
||||||
|
meta_valid = true;
|
||||||
|
|
||||||
|
LOG_TRACE << "[AIFF] " << path << ": meta=" << meta;
|
||||||
|
} else if (std::memcmp(chk_hdr.id, "SSND", 4) == 0) {
|
||||||
|
if (!meta_valid) {
|
||||||
|
LOG_WARN << "[AIFF] " << path << ": got SSND chunk without COMM chunk";
|
||||||
|
// corrupt AIFF? -> skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssnd_chk_t ssnd;
|
||||||
|
std::memcpy(&ssnd, data.data() + pos + sizeof(chk_hdr), sizeof(ssnd));
|
||||||
|
ssnd.offset = folly::Endian::big(ssnd.offset);
|
||||||
|
ssnd.block_size = folly::Endian::big(ssnd.block_size);
|
||||||
|
|
||||||
|
size_t pcm_start = pos + sizeof(chk_hdr) + sizeof(ssnd) + ssnd.offset;
|
||||||
|
size_t pcm_length =
|
||||||
|
num_sample_frames * (meta.number_of_channels * meta.bytes_per_sample);
|
||||||
|
|
||||||
|
if (sizeof(ssnd) + ssnd.offset + pcm_length > chk_size) {
|
||||||
|
LOG_WARN << "[AIFF] " << path
|
||||||
|
<< ": SSND invalid chunk size (offset=" << ssnd.offset
|
||||||
|
<< ", pcm_len=" << pcm_length << ", chk_size" << chk_size
|
||||||
|
<< ")";
|
||||||
|
// corrupt AIFF? -> skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment_category::value_type subcategory = meta_.wlock()->add(meta);
|
||||||
|
|
||||||
|
frag.emplace_back(fragment_category(mapper(METADATA_CATEGORY)),
|
||||||
|
pcm_start);
|
||||||
|
frag.emplace_back(
|
||||||
|
fragment_category(mapper(PCMAUDIO_CATEGORY), subcategory),
|
||||||
|
pcm_length);
|
||||||
|
|
||||||
|
if (pcm_start + pcm_length < data.size()) {
|
||||||
|
frag.emplace_back(fragment_category(mapper(METADATA_CATEGORY)),
|
||||||
|
data.size() - (pcm_start + pcm_length));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += sizeof(chk_hdr) + chk_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename LoggerPolicy>
|
||||||
|
bool pcmaudio_categorizer_<LoggerPolicy>::check_caf(
|
||||||
|
inode_fragments& frag, fs::path const& path, std::span<uint8_t const> data,
|
||||||
|
category_mapper const& mapper) const {
|
||||||
|
if (std::memcmp(data.data(), "caff", 4) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOLLY_PACK_PUSH
|
||||||
|
|
||||||
|
struct caff_hdr_t {
|
||||||
|
uint16_t version;
|
||||||
|
uint16_t flags;
|
||||||
|
} FOLLY_PACK_ATTR;
|
||||||
|
|
||||||
|
struct chk_hdr_t {
|
||||||
|
char id[4];
|
||||||
|
uint64_t size;
|
||||||
|
} FOLLY_PACK_ATTR;
|
||||||
|
|
||||||
|
struct format_chk_t {
|
||||||
|
double sample_rate;
|
||||||
|
char format_id[4];
|
||||||
|
uint32_t format_flags;
|
||||||
|
uint32_t bytes_per_packet;
|
||||||
|
uint32_t frames_per_packet;
|
||||||
|
uint32_t channels_per_frame;
|
||||||
|
uint32_t bits_per_channel;
|
||||||
|
} FOLLY_PACK_ATTR;
|
||||||
|
|
||||||
|
struct data_chk_t {
|
||||||
|
uint32_t edit_count;
|
||||||
|
} FOLLY_PACK_ATTR;
|
||||||
|
|
||||||
|
FOLLY_PACK_POP
|
||||||
|
|
||||||
|
static_assert(sizeof(caff_hdr_t) == 4);
|
||||||
|
static_assert(sizeof(chk_hdr_t) == 12);
|
||||||
|
static_assert(sizeof(format_chk_t) == 32);
|
||||||
|
static_assert(sizeof(data_chk_t) == 4);
|
||||||
|
|
||||||
|
static constexpr uint32_t const kCAFLinearPCMFormatFlagIsFloat{1L << 0};
|
||||||
|
static constexpr uint32_t const kCAFLinearPCMFormatFlagIsLittleEndian{1L
|
||||||
|
<< 1};
|
||||||
|
|
||||||
|
caff_hdr_t caff_hdr;
|
||||||
|
std::memcpy(&caff_hdr, data.data() + 4, sizeof(caff_hdr));
|
||||||
|
caff_hdr.version = folly::Endian::big(caff_hdr.version);
|
||||||
|
caff_hdr.flags = folly::Endian::big(caff_hdr.flags);
|
||||||
|
|
||||||
|
if (caff_hdr.version != 1 || caff_hdr.flags != 0) {
|
||||||
|
LOG_WARN << "[CAF] " << path
|
||||||
|
<< ": unsupported file version/flags: " << caff_hdr.version << "/"
|
||||||
|
<< caff_hdr.flags;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool meta_valid{false};
|
||||||
|
pcmaudio_metadata meta;
|
||||||
|
size_t pos = 8;
|
||||||
|
chk_hdr_t chk_hdr;
|
||||||
|
|
||||||
|
while (pos + sizeof(chk_hdr) <= data.size()) {
|
||||||
|
std::memcpy(&chk_hdr, data.data() + pos, sizeof(chk_hdr));
|
||||||
|
uint64_t chk_size = folly::Endian::big(chk_hdr.size);
|
||||||
|
|
||||||
|
LOG_TRACE << "[CAF] " << path << ": " << std::string_view(chk_hdr.id, 4)
|
||||||
|
<< " (len=" << chk_size << ")";
|
||||||
|
|
||||||
|
if (chk_size == std::numeric_limits<uint64_t>::max() &&
|
||||||
|
std::memcmp(chk_hdr.id, "data", 4) == 0) {
|
||||||
|
chk_size = data.size() - (pos + sizeof(chk_hdr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos + sizeof(chk_hdr) + chk_size > data.size()) {
|
||||||
|
LOG_WARN << "[CAF] " << path << ": unexpected end of file";
|
||||||
|
// corrupt CAF? -> skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::memcmp(chk_hdr.id, "desc", 4) == 0) {
|
||||||
|
if (chk_size != sizeof(format_chk_t)) {
|
||||||
|
LOG_WARN << "[CAF] " << path
|
||||||
|
<< ": unexpected size for desc chunk: " << chk_size
|
||||||
|
<< " (expected " << sizeof(format_chk_t) << ")";
|
||||||
|
// corrupt CAF? -> skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meta_valid) {
|
||||||
|
LOG_WARN << "[CAF] " << path << ": unexpected second desc chunk";
|
||||||
|
// corrupt CAF? -> skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
format_chk_t fmt;
|
||||||
|
std::memcpy(&fmt, data.data() + pos + sizeof(chk_hdr), sizeof(fmt));
|
||||||
|
|
||||||
|
if (std::memcmp(fmt.format_id, "lpcm", 4) != 0) {
|
||||||
|
// TODO: alaw, ulaw?
|
||||||
|
LOG_DEBUG << "[CAF] " << path << ": found compressed format";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.format_flags = folly::Endian::big(fmt.format_flags);
|
||||||
|
|
||||||
|
if (fmt.format_flags & kCAFLinearPCMFormatFlagIsFloat) {
|
||||||
|
LOG_DEBUG << "[CAF] " << path << ": floating point is unsupported";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.frames_per_packet = folly::Endian::big(fmt.frames_per_packet);
|
||||||
|
|
||||||
|
if (fmt.frames_per_packet != 1) {
|
||||||
|
LOG_WARN << "[CAF] " << path
|
||||||
|
<< ": unsupported frames/packet: " << fmt.frames_per_packet;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.bytes_per_packet = folly::Endian::big(fmt.bytes_per_packet);
|
||||||
|
|
||||||
|
meta.sample_endianness =
|
||||||
|
(fmt.format_flags & kCAFLinearPCMFormatFlagIsLittleEndian)
|
||||||
|
? endianness::LITTLE
|
||||||
|
: endianness::BIG;
|
||||||
|
meta.sample_signedness = signedness::SIGNED;
|
||||||
|
meta.sample_padding = padding::LSB;
|
||||||
|
meta.bits_per_sample = folly::Endian::big(fmt.bits_per_channel);
|
||||||
|
meta.number_of_channels = folly::Endian::big(fmt.channels_per_frame);
|
||||||
|
meta.bytes_per_sample = fmt.bytes_per_packet / meta.number_of_channels;
|
||||||
|
|
||||||
|
if (fmt.bytes_per_packet % meta.number_of_channels != 0) {
|
||||||
|
LOG_WARN << "[CAF] " << path
|
||||||
|
<< ": unsupported packet size: " << fmt.bytes_per_packet
|
||||||
|
<< " (" << meta.number_of_channels << " channels)";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_valid = true;
|
||||||
|
|
||||||
|
LOG_TRACE << "[CAF] " << path << ": meta=" << meta;
|
||||||
|
} else if (std::memcmp(chk_hdr.id, "data", 4) == 0) {
|
||||||
|
if (!meta_valid) {
|
||||||
|
LOG_WARN << "[CAF] " << path << ": got data chunk without desc chunk";
|
||||||
|
// corrupt CAF? -> skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pcm_start = pos + sizeof(chk_hdr) + sizeof(data_chk_t);
|
||||||
|
size_t pcm_length = chk_size - sizeof(data_chk_t);
|
||||||
|
|
||||||
|
if (pcm_length % (meta.number_of_channels * meta.bytes_per_sample)) {
|
||||||
|
LOG_WARN << "[CAF] " << path
|
||||||
|
<< ": data chunk size mismatch (pcm_len=" << pcm_length
|
||||||
|
<< ", #chan=" << meta.number_of_channels
|
||||||
|
<< ", bytes_per_sample=" << meta.bytes_per_sample << ")";
|
||||||
|
// corrupt CAF? -> skip
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment_category::value_type subcategory = meta_.wlock()->add(meta);
|
||||||
|
|
||||||
|
frag.emplace_back(fragment_category(mapper(METADATA_CATEGORY)),
|
||||||
|
pcm_start);
|
||||||
|
frag.emplace_back(
|
||||||
|
fragment_category(mapper(PCMAUDIO_CATEGORY), subcategory),
|
||||||
|
pcm_length);
|
||||||
|
|
||||||
|
if (pcm_start + pcm_length < data.size()) {
|
||||||
|
frag.emplace_back(fragment_category(mapper(METADATA_CATEGORY)),
|
||||||
|
data.size() - (pcm_start + pcm_length));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += sizeof(chk_hdr) + chk_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename LoggerPolicy>
|
||||||
|
bool pcmaudio_categorizer_<LoggerPolicy>::check_wav(
|
||||||
|
inode_fragments& frag, fs::path const& path, std::span<uint8_t const> data,
|
||||||
|
category_mapper const& mapper) const {
|
||||||
|
if (std::memcmp(data.data(), "RIFF", 4) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename LoggerPolicy>
|
||||||
|
bool pcmaudio_categorizer_<LoggerPolicy>::check_wav64(
|
||||||
|
inode_fragments& frag, fs::path const& path, std::span<uint8_t const> data,
|
||||||
|
category_mapper const& mapper) const {
|
||||||
|
if (std::memcmp(data.data(), "riff", 4) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename LoggerPolicy>
|
template <typename LoggerPolicy>
|
||||||
inode_fragments pcmaudio_categorizer_<LoggerPolicy>::categorize(
|
inode_fragments pcmaudio_categorizer_<LoggerPolicy>::categorize(
|
||||||
std::filesystem::path const&,
|
fs::path const& path, std::span<uint8_t const> data,
|
||||||
std::span<uint8_t const> data [[maybe_unused]],
|
category_mapper const& mapper) const {
|
||||||
category_mapper const& /*mapper*/) const {
|
|
||||||
inode_fragments fragments;
|
inode_fragments fragments;
|
||||||
|
|
||||||
|
if (data.size() >= MIN_PCMAUDIO_SIZE) {
|
||||||
|
for (auto f : {
|
||||||
|
// clang-format off
|
||||||
|
&pcmaudio_categorizer_::check_aiff,
|
||||||
|
&pcmaudio_categorizer_::check_caf,
|
||||||
|
&pcmaudio_categorizer_::check_wav,
|
||||||
|
&pcmaudio_categorizer_::check_wav64,
|
||||||
|
// clang-format on
|
||||||
|
}) {
|
||||||
|
if ((this->*f)(fragments, path, data, mapper)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up
|
||||||
|
fragments.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return fragments;
|
return fragments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user