extend channel-map
authorRobin Gareus <robin@gareus.org>
Tue, 29 Mar 2016 17:12:29 +0000 (19:12 +0200)
committerRobin Gareus <robin@gareus.org>
Tue, 29 Mar 2016 17:49:37 +0000 (19:49 +0200)
add tests for identity matrix, monotonic, subset,
which are handy to verify if inplace processing is possible.
add `unset()` for upcoming GUI work.

libs/ardour/ardour/chan_mapping.h
libs/ardour/chan_mapping.cc
libs/ardour/luabindings.cc

index 6fbf8bc96e420b72d2f4369ea5f3e75d81ef6707..4b0b930b0215cb97398865f1a41a9f0ac2e9dc52 100644 (file)
@@ -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<uint32_t, uint32_t>    TypeMapping;
        typedef std::map<DataType, TypeMapping> Mappings;
 
index 83ded4141cb5d3475fcb612af6bc0ac684192581..bc6c4051fc75c6b33202c499af7e547739d9dbbd 100644 (file)
@@ -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)
index 9639f37a744547fe7004353cbad7bc3d8997e55c..dfcdfaec61b34e2549e8a35668258a3f0330c207 100644 (file)
@@ -181,7 +181,7 @@ LuaBindings::common (lua_State* L)
 
                .beginClass <ChanMapping> ("ChanMapping")
                .addVoidConstructor ()
-               .addFunction ("get", static_cast<uint32_t(ChanMapping::*)(DataType, uint32_t)>(&ChanMapping::get))
+               .addFunction ("get", static_cast<uint32_t(ChanMapping::*)(DataType, uint32_t) const>(&ChanMapping::get))
                .addFunction ("set", &ChanMapping::set)
                .addConst ("Invalid", 4294967295) // UINT32_MAX
                .endClass ()