diff --git a/libs/ardour/ardour/chan_mapping.h b/libs/ardour/ardour/chan_mapping.h index 6fbf8bc96e..4b0b930b02 100644 --- a/libs/ardour/ardour/chan_mapping.h +++ b/libs/ardour/ardour/chan_mapping.h @@ -42,14 +42,14 @@ public: ChanMapping(ARDOUR::ChanCount identity); ChanMapping(const ChanMapping&); - uint32_t get(DataType t, uint32_t from, bool* valid); + uint32_t get(DataType t, uint32_t from, bool* valid) const; /** get buffer mapping for given data type and pin * @param type data type * @param from pin * @returns mapped buffer number (or ChanMapping::Invalid) */ - uint32_t get(DataType t, uint32_t from) { return get (t, from, NULL); } + uint32_t get(DataType t, uint32_t from) const { return get (t, from, NULL); } /** set buffer mapping for given data type * @param type data type * @param from pin @@ -59,6 +59,30 @@ public: void offset_from(DataType t, int32_t delta); void offset_to(DataType t, int32_t delta); + /** remove mapping + * @param type data type + * @param from source to remove from mapping + */ + void unset(DataType t, uint32_t from); + + /** Test mapping matrix for identity + * @param offset per data-type offset to take into account + * @returns true if the mapping is a channel identity map + */ + bool is_identity (ARDOUR::ChanCount offset = ARDOUR::ChanCount()) const; + + /** Test if this mapping is monotonic (useful to see if inplace processing is feasible) + * @returns true if the map is a strict monotonic set + */ + bool is_monotonic () const; + + + /** Test if this mapping is a subset + * @param superset to test against + * @returns true if all mapping are also present in the superset + */ + bool is_subset (const ChanMapping& superset) const; + typedef std::map TypeMapping; typedef std::map Mappings; diff --git a/libs/ardour/chan_mapping.cc b/libs/ardour/chan_mapping.cc index 83ded4141c..bc6c4051fc 100644 --- a/libs/ardour/chan_mapping.cc +++ b/libs/ardour/chan_mapping.cc @@ -46,14 +46,14 @@ ChanMapping::ChanMapping (const ChanMapping& other ) } uint32_t -ChanMapping::get(DataType t, uint32_t from, bool* valid) +ChanMapping::get(DataType t, uint32_t from, bool* valid) const { - Mappings::iterator tm = _mappings.find(t); + Mappings::const_iterator tm = _mappings.find(t); if (tm == _mappings.end()) { if (valid) { *valid = false; } return -1; } - TypeMapping::iterator m = tm->second.find(from); + TypeMapping::const_iterator m = tm->second.find(from); if (m == tm->second.end()) { if (valid) { *valid = false; } return -1; @@ -73,6 +73,17 @@ ChanMapping::set(DataType t, uint32_t from, uint32_t to) tm->second.insert(std::make_pair(from, to)); } +void +ChanMapping::unset(DataType t, uint32_t from) +{ + assert(t != DataType::NIL); + Mappings::iterator tm = _mappings.find(t); + if (tm == _mappings.end()) { + return; + } + tm->second.erase(from); +} + /** Offset the 'from' field of every mapping for type @a t by @a delta */ void ChanMapping::offset_from(DataType t, int32_t delta) @@ -99,6 +110,52 @@ ChanMapping::offset_to(DataType t, int32_t delta) } } +bool +ChanMapping::is_subset (const ChanMapping& superset) const +{ + for (ARDOUR::ChanMapping::Mappings::const_iterator tm = mappings().begin(); tm != mappings().end(); ++tm) { + for (ARDOUR::ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) { + bool valid; + if (i->second != superset.get (tm->first, i->first, &valid)) { + return false; + } + if (!valid) { + return false; + } + } + } + return true; +} + +bool +ChanMapping::is_monotonic () const +{ + for (ARDOUR::ChanMapping::Mappings::const_iterator tm = mappings().begin(); tm != mappings().end(); ++tm) { + uint32_t prev = UINT32_MAX; + for (ARDOUR::ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) { + // set keys are strictly weak ordered + if (i->first < i->second || i->second == prev) { + return false; + } + prev = i->second; + } + } + return true; +} + +bool +ChanMapping::is_identity (ChanCount offset) const +{ + for (ARDOUR::ChanMapping::Mappings::const_iterator tm = mappings().begin(); tm != mappings().end(); ++tm) { + for (ARDOUR::ChanMapping::TypeMapping::const_iterator i = tm->second.begin(); i != tm->second.end(); ++i) { + if (i->first + offset.get (tm->first) != i->second) { + return false; + } + } + } + return true; +} + } // namespace ARDOUR std::ostream& operator<<(std::ostream& o, const ARDOUR::ChanMapping& cm) diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index 9639f37a74..dfcdfaec61 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -181,7 +181,7 @@ LuaBindings::common (lua_State* L) .beginClass ("ChanMapping") .addVoidConstructor () - .addFunction ("get", static_cast(&ChanMapping::get)) + .addFunction ("get", static_cast(&ChanMapping::get)) .addFunction ("set", &ChanMapping::set) .addConst ("Invalid", 4294967295) // UINT32_MAX .endClass ()