changeset 1626:895186c43fce single-point

Experiment with storing vectors of event ids in seam map for compactness
author Chris Cannam
date Mon, 11 Mar 2019 13:44:35 +0000
parents 7dbb2a7b592e
children 1c21ddac220e
files base/BaseTypes.h base/Event.cpp base/Event.h base/EventSeries.h files.pri
diffstat 5 files changed, 92 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/base/BaseTypes.h	Mon Mar 11 11:25:17 2019 +0000
+++ b/base/BaseTypes.h	Mon Mar 11 13:44:35 2019 +0000
@@ -55,5 +55,11 @@
 typedef std::vector<std::complex<float>,
                     breakfastquay::StlAllocator<std::complex<float>>> complexvec_t;
 
+typedef uint64_t sv_id_t;
+
+enum {
+    ID_NOTHING = 0
+};
+
 #endif
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base/Event.cpp	Mon Mar 11 13:44:35 2019 +0000
@@ -0,0 +1,21 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    Sonic Visualiser
+    An audio file viewer and annotation editor.
+    Centre for Digital Music, Queen Mary, University of London.
+    This file copyright 2006 Chris Cannam.
+    
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2 of the
+    License, or (at your option) any later version.  See the file
+    COPYING included with this distribution for more information.
+*/
+
+#include "Event.h"
+
+sv_id_t Event::m_nextId = 1;
+QHash<Event, sv_id_t> Event::m_ids;
+QHash<sv_id_t, Event> Event::m_rids;
+
--- a/base/Event.h	Mon Mar 11 11:25:17 2019 +0000
+++ b/base/Event.h	Mon Mar 11 13:44:35 2019 +0000
@@ -279,6 +279,27 @@
         if (m_haveReferenceFrame) h ^= qHash(m_referenceFrame);
         return h;
     }
+
+    static sv_id_t getId(const Event &ev) {
+        sv_id_t id;
+        if (!m_ids.contains(ev)) {
+            id = m_nextId;
+            ++m_nextId;
+            m_ids[ev] = id;
+            m_rids[id] = ev;
+            return id;
+        } else {
+            return m_ids.value(ev);
+        }
+    }
+
+    static Event getEventForId(sv_id_t id) {
+        if (!m_rids.contains(id)) {
+            throw std::runtime_error("unknown event id");
+        } else {
+            return m_rids.value(id);
+        }
+    }
     
 private:
     // The order of fields here is chosen to minimise overall size of struct.
@@ -293,6 +314,10 @@
     sv_frame_t m_duration;
     sv_frame_t m_referenceFrame;
     QString m_label;
+
+    static sv_id_t m_nextId;
+    static QHash<Event, sv_id_t> m_ids;
+    static QHash<sv_id_t, Event> m_rids;
 };
 
 inline uint qHash(const Event &e, uint seed = 0) {
--- a/base/EventSeries.h	Mon Mar 11 11:25:17 2019 +0000
+++ b/base/EventSeries.h	Mon Mar 11 13:44:35 2019 +0000
@@ -59,6 +59,8 @@
         ++m_events[p];
         ++m_count;
 
+        sv_id_t id = Event::getId(p);
+        
         if (p.hasDuration()) {
 
             const sv_frame_t frame = p.getFrame();
@@ -78,7 +80,16 @@
                            << endl;
                     break;
                 }
-                i->second.insert(p);
+/*                bool found = false;
+                for (auto eid: i->second) {
+                    if (eid == id) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {*/
+                    i->second.push_back(id);
+//                }
             }
         }
 
@@ -107,6 +118,8 @@
             --m_count;
         }
 
+        sv_id_t id = Event::getId(p);
+        
         if (p.hasDuration() && isUnique) {
             
             const sv_frame_t frame = p.getFrame();
@@ -131,13 +144,20 @@
                     // duration, which Event forbids
                     throw std::logic_error("unexpectedly reached end of map");
                 }
-                
-                i->second.erase(p);
+                for (size_t j = 0; j < i->second.size(); ) {
+                    if (i->second[j] == id) {
+                        i->second.erase(i->second.begin() + j);
+                    } else {
+                        ++j;
+                    }
+                }
             }
 
             // Tidy up by removing any entries that are now identical
             // to their predecessors
 
+//!!! won't work as vector is not consistently ordered
+            
             std::vector<sv_frame_t> redundant;
 
             auto pitr = m_seams.end();
@@ -232,8 +252,8 @@
             }                
         }
         while (sitr != m_seams.end() && sitr->first < end) {
-            for (const auto &p: sitr->second) {
-                found.insert(p);
+            for (const auto &id: sitr->second) {
+                found.insert(Event::getEventForId(id));
             }
             ++sitr;
         }
@@ -274,6 +294,7 @@
 
         // now any non-zero-duration ones from the seam map
         
+        std::set<Event> found;
         auto sitr = m_seams.lower_bound(frame);
         if (sitr == m_seams.end() || sitr->first > frame) {
             if (sitr != m_seams.begin()) {
@@ -281,14 +302,18 @@
             }                
         }
         if (sitr != m_seams.end() && sitr->first <= frame) {
-            for (const auto &p: sitr->second) {
-                int n = m_events.at(p);
-                if (n < 1) {
-                    throw std::logic_error("event is in seams but not events");
-                }
-                for (int i = 0; i < n; ++i) {
-                    cover.push_back(p);
-                }
+            for (const auto &id: sitr->second) {
+                found.insert(Event::getEventForId(id));
+            }
+            ++sitr;
+        }
+        for (const auto &p: found) {
+            int n = m_events.at(p);
+            if (n < 1) {
+                throw std::logic_error("event is in seams but not events");
+            }
+            for (int i = 0; i < n; ++i) {
+                cover.push_back(p);
             }
         }
         
@@ -331,7 +356,7 @@
      * Only events with duration appear in this map; point events
      * appear only in m_events.
      */
-    typedef std::map<sv_frame_t, std::set<Event>> FrameEventMap;
+    typedef std::map<sv_frame_t, std::vector<sv_id_t>> FrameEventMap;
     FrameEventMap m_seams;
 
     /** Create a seam at the given frame, copying from the prior seam
--- a/files.pri	Mon Mar 11 11:25:17 2019 +0000
+++ b/files.pri	Mon Mar 11 13:44:35 2019 +0000
@@ -152,6 +152,7 @@
            base/ColumnOp.cpp \
            base/Command.cpp \
            base/Debug.cpp \
+           base/Event.cpp \
            base/Exceptions.cpp \
            base/HelperExecPath.cpp \
            base/LogRange.cpp \