diff --git a/src/dwarfs/categorizer/pcmaudio_categorizer.cpp b/src/dwarfs/categorizer/pcmaudio_categorizer.cpp index d0bf0c2d..bce7b63a 100644 --- a/src/dwarfs/categorizer/pcmaudio_categorizer.cpp +++ b/src/dwarfs/categorizer/pcmaudio_categorizer.cpp @@ -30,6 +30,8 @@ #include +#include + #include "dwarfs/categorizer.h" #include "dwarfs/error.h" #include "dwarfs/logger.h" @@ -40,8 +42,76 @@ namespace po = boost::program_options; namespace { -constexpr std::string_view const AIFF_CATEGORY{"aiff"}; -constexpr std::string_view const WAV_CATEGORY{"wav"}; +constexpr std::string_view const PCMAUDIO_CATEGORY{"pcmaudio"}; + +enum class endianness : uint8_t { + BIG, + LITTLE, +}; +enum class signedness : uint8_t { + SIGNED, + UNSIGNED, +}; + +char const* endianness_string(endianness e) { + switch (e) { + case endianness::BIG: + return "big"; + case endianness::LITTLE: + return "little"; + } +} + +char const* signedness_string(signedness s) { + switch (s) { + case signedness::SIGNED: + return "signed"; + case signedness::UNSIGNED: + return "unsigned"; + } +} + +struct pcmaudio_metadata { + endianness sample_endianness; + signedness sample_signedness; + uint8_t bits_per_sample; + uint16_t number_of_channels; + + //// Sample rate should be irrelevant + // uint32_t samples_per_second; + + auto operator<=>(pcmaudio_metadata const&) const = default; +}; + +class pcmaudio_metadata_store { + public: + pcmaudio_metadata_store() = default; + + size_t add(pcmaudio_metadata const& m) { + auto it = reverse_index_.find(m); + if (it == reverse_index_.end()) { + auto r = reverse_index_.emplace(m, forward_index_.size()); + assert(r.second); + forward_index_.emplace_back(m); + it = r.first; + } + return it->second; + } + + folly::dynamic lookup(size_t ix) const { + auto const& m = DWARFS_NOTHROW(forward_index_.at(ix)); + folly::dynamic obj = folly::dynamic::object; + obj.insert("endianness", endianness_string(m.sample_endianness)); + obj.insert("signedness", signedness_string(m.sample_signedness)); + obj.insert("bits_per_sample", m.bits_per_sample); + obj.insert("number_of_channels", m.number_of_channels); + return obj; + } + + private: + std::vector forward_index_; + std::map reverse_index_; +}; class pcmaudio_categorizer_base : public random_access_categorizer { public: @@ -60,20 +130,20 @@ class pcmaudio_categorizer_ final : public pcmaudio_categorizer_base { bool is_single_fragment() const override { return false; } - folly::dynamic category_metadata(fragment_category) const override { - // TODO - return folly::dynamic(); + folly::dynamic category_metadata(fragment_category c) const override { + DWARFS_CHECK(c.has_subcategory(), "expected pcmaudio to have subcategory"); + return meta_.rlock()->lookup(c.subcategory()); } private: LOG_PROXY_DECL(LoggerPolicy); + folly::Synchronized mutable meta_; }; std::span pcmaudio_categorizer_base::categories() const { static constexpr std::array const s_categories{ - AIFF_CATEGORY, - WAV_CATEGORY, + PCMAUDIO_CATEGORY, }; return s_categories; }