changeset 1644:513192aa9b03 single-point

Further API updates
author Chris Cannam
date Wed, 13 Mar 2019 16:00:13 +0000
parents 7a23dfe65d66
children 82596b4deef6
files base/EventSeries.cpp base/EventSeries.h data/fileio/CSVFileReader.cpp data/fileio/MIDIFileReader.cpp data/fileio/test/CSVStreamWriterTest.h data/model/NoteModel.h data/model/test/TestSparseModels.h rdf/RDFExporter.cpp rdf/RDFImporter.cpp transform/FeatureExtractionModelTransformer.cpp
diffstat 10 files changed, 209 insertions(+), 176 deletions(-) [+]
line wrap: on
line diff
--- a/base/EventSeries.cpp	Wed Mar 13 14:50:10 2019 +0000
+++ b/base/EventSeries.cpp	Wed Mar 13 16:00:13 2019 +0000
@@ -363,6 +363,12 @@
     return cover;
 }
 
+EventVector
+EventSeries::getAllEvents() const
+{
+    return m_events;
+}
+
 bool
 EventSeries::getEventPreceding(const Event &e, Event &preceding) const
 {
--- a/base/EventSeries.h	Wed Mar 13 14:50:10 2019 +0000
+++ b/base/EventSeries.h	Wed Mar 13 16:00:13 2019 +0000
@@ -127,6 +127,11 @@
      * than it.
      */
     EventVector getEventsCovering(sv_frame_t frame) const;
+
+    /**
+     * Retrieve all events, in their natural order.
+     */
+    EventVector getAllEvents() const;
     
     /**
      * If e is in the series and is not the first event in it, set
--- a/data/fileio/CSVFileReader.cpp	Wed Mar 13 14:50:10 2019 +0000
+++ b/data/fileio/CSVFileReader.cpp	Wed Mar 13 16:00:13 2019 +0000
@@ -454,7 +454,7 @@
 
                 float level = ((value >= 0.f && value <= 1.f) ? value : 1.f);
                 Event note(frameNo, pitch, duration, level, label);
-                model2b->addPoint(note);
+                model2b->add(note);
 
             } else if (modelType == CSVFormat::ThreeDimensionalModel) {
 
--- a/data/fileio/MIDIFileReader.cpp	Wed Mar 13 14:50:10 2019 +0000
+++ b/data/fileio/MIDIFileReader.cpp	Wed Mar 13 16:00:13 2019 +0000
@@ -1032,7 +1032,7 @@
 
 //                    SVDEBUG << "Adding note " << startFrame << "," << (endFrame-startFrame) << " : " << int((*i)->getPitch()) << endl;
 
-                    model->addPoint(note);
+                    model->add(note);
                     break;
                 }
 
--- a/data/fileio/test/CSVStreamWriterTest.h	Wed Mar 13 14:50:10 2019 +0000
+++ b/data/fileio/test/CSVStreamWriterTest.h	Wed Mar 13 16:00:13 2019 +0000
@@ -297,7 +297,7 @@
         NoteModel notes(8 /* sampleRate */, 4 /* resolution */);
         sv_frame_t startFrame = 0;
         for (const auto& note : cMajorPentatonic) {
-            notes.addPoint({startFrame, note, 4, 1.f, ""});
+            notes.add({startFrame, note, 4, 1.f, ""});
             startFrame += 8;
         }
 //        qDebug("Create Expected Output\n");
--- a/data/model/NoteModel.h	Wed Mar 13 14:50:10 2019 +0000
+++ b/data/model/NoteModel.h	Wed Mar 13 16:00:13 2019 +0000
@@ -37,7 +37,8 @@
     Q_OBJECT
     
 public:
-    NoteModel(sv_samplerate_t sampleRate, int resolution,
+    NoteModel(sv_samplerate_t sampleRate,
+              int resolution,
               bool notifyOnAdd = true) :
         m_sampleRate(sampleRate),
         m_resolution(resolution),
@@ -82,6 +83,7 @@
     sv_frame_t getStartFrame() const override { return m_events.getStartFrame(); }
     sv_frame_t getEndFrame() const override { return m_events.getEndFrame(); }
     sv_samplerate_t getSampleRate() const override { return m_sampleRate; }
+    int getResolution() const { return m_resolution; }
 
     bool canPlay() const override { return true; }
     QString getDefaultPlayClipId() const override {
@@ -145,30 +147,133 @@
             m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
         }        
     }
+
+    /**
+     * Query methods.
+     */
+
+    int getEventCount() const {
+        return m_events.count();
+    }
+    bool isEmpty() const {
+        return m_events.isEmpty();
+    }
+    bool containsEvent(const Event &e) const {
+        return m_events.contains(e);
+    }
+    EventVector getAllEvents() const {
+        return m_events.getAllEvents();
+    }
+    EventVector getEventsSpanning(sv_frame_t f, sv_frame_t duration) const {
+        return m_events.getEventsSpanning(f, duration);
+    }
+    EventVector getEventsWithin(sv_frame_t f, sv_frame_t duration) const {
+        return m_events.getEventsWithin(f, duration);
+    }
+    EventVector getEventsStartingWithin(sv_frame_t f, sv_frame_t duration) const {
+        return m_events.getEventsStartingWithin(f, duration);
+    }
+    EventVector getEventsCovering(sv_frame_t f) const {
+        return m_events.getEventsCovering(f);
+    }
+
+    /**
+     * Editing commands and methods.
+     */
     
-    void toXml(QTextStream &out,
-               QString indent = "",
-               QString extraAttributes = "") const override {
+    class EditCommand : public Command
+    {
+    public:
+        //!!! borrowed ptr
+        EditCommand(NoteModel *model, QString name) :
+            m_model(model), m_name(name) { }
 
-        //!!! what is valueQuantization used for?
+        QString getName() const override {
+            return m_name;
+        }
+
+        void add(Event e) {
+            m_add.insert(e);
+        }
+
+        void remove(Event e) {
+            m_remove.insert(e);
+        }
         
-        Model::toXml
-            (out,
-             indent,
-             QString("type=\"sparse\" dimensions=\"3\" resolution=\"%1\" "
-                     "notifyOnAdd=\"%2\" dataset=\"%3\" subtype=\"note\" "
-                     "valueQuantization=\"%4\" minimum=\"%5\" maximum=\"%6\" "
-                     "units=\"%7\" %8")
-             .arg(m_resolution)
-             .arg(m_notifyOnAdd ? "true" : "false")
-             .arg(getObjectExportId(&m_events))
-             .arg(m_valueQuantization)
-             .arg(m_valueMinimum)
-             .arg(m_valueMaximum)
-             .arg(m_units)
-             .arg(extraAttributes));
+        void execute() override {
+            for (const Event &e: m_add) m_model->add(e);
+            for (const Event &e: m_remove) m_model->remove(e);
+        }
 
-        m_events.toXml(out, indent, QString("dimensions=\"3\""));
+        void unexecute() override {
+            for (const Event &e: m_remove) m_model->add(e);
+            for (const Event &e: m_add) m_model->remove(e);
+        }
+
+        EditCommand *finish() {
+            if (m_add.empty() && m_remove.empty()) {
+                delete this;
+                return nullptr;
+            } else {
+                return this;
+            }
+        }
+
+    private:
+        NoteModel *m_model;
+        std::set<Event> m_add;
+        std::set<Event> m_remove;
+        QString m_name;
+    };
+
+    void add(Event e) {
+
+        bool allChange = false;
+           
+        {
+            QMutexLocker locker(&m_mutex);
+            m_events.add(e);
+//!!!???        if (point.getLabel() != "") m_hasTextLabels = true;
+
+            float v = e.getValue();
+            if (!ISNAN(v) && !ISINF(v)) {
+                if (!m_haveExtents || v < m_valueMinimum) {
+                    m_valueMinimum = v; allChange = true;
+                }
+                if (!m_haveExtents || v > m_valueMaximum) {
+                    m_valueMaximum = v; allChange = true;
+                }
+                m_haveExtents = true;
+            }
+            
+            sv_frame_t f = e.getFrame();
+
+            if (!m_notifyOnAdd) {
+                if (m_sinceLastNotifyMin == -1 || f < m_sinceLastNotifyMin) {
+                    m_sinceLastNotifyMin = f;
+                }
+                if (m_sinceLastNotifyMax == -1 || f > m_sinceLastNotifyMax) {
+                    m_sinceLastNotifyMax = f;
+                }
+            }
+        }
+        
+        if (m_notifyOnAdd) {
+            emit modelChangedWithin(e.getFrame(),
+                                    e.getFrame() + e.getDuration() + m_resolution);
+        }
+        if (allChange) {
+            emit modelChanged();
+        }
+    }
+    
+    void remove(Event e) {
+        {
+            QMutexLocker locker(&m_mutex);
+            m_events.remove(e);
+        }
+        emit modelChangedWithin(e.getFrame(),
+                                e.getFrame() + e.getDuration() + m_resolution);
     }
 
     /**
@@ -232,117 +337,6 @@
         }
     }
 
-    class EditCommand : public Command
-    {
-    public:
-        //!!! borrowed ptr
-        EditCommand(NoteModel *model, QString name) :
-            m_model(model), m_name(name) { }
-
-        QString getName() const override {
-            return m_name;
-        }
-
-        void addPoint(Event e) {
-            m_add.insert(e);
-        }
-        void deletePoint(Event e) {
-            m_remove.insert(e);
-        }
-        
-        void execute() override {
-            for (const Event &e: m_add) m_model->addPoint(e);
-            for (const Event &e: m_remove) m_model->deletePoint(e);
-        }
-
-        void unexecute() override {
-            for (const Event &e: m_remove) m_model->addPoint(e);
-            for (const Event &e: m_add) m_model->deletePoint(e);
-        }
-
-    private:
-        NoteModel *m_model;
-        std::set<Event> m_add;
-        std::set<Event> m_remove;
-        QString m_name;
-    };
-
-    //!!! rename Point to Note throughout? Just because we can now?
-    void addPoint(Event e) {
-
-        bool allChange = false;
-           
-        {
-            QMutexLocker locker(&m_mutex);
-            m_events.add(e);
-//!!!???        if (point.getLabel() != "") m_hasTextLabels = true;
-
-            float v = e.getValue();
-            if (!ISNAN(v) && !ISINF(v)) {
-                if (!m_haveExtents || v < m_valueMinimum) {
-                    m_valueMinimum = v; allChange = true;
-                }
-                if (!m_haveExtents || v > m_valueMaximum) {
-                    m_valueMaximum = v; allChange = true;
-                }
-                m_haveExtents = true;
-            }
-            
-            sv_frame_t f = e.getFrame();
-
-            if (!m_notifyOnAdd) {
-                if (m_sinceLastNotifyMin == -1 || f < m_sinceLastNotifyMin) {
-                    m_sinceLastNotifyMin = f;
-                }
-                if (m_sinceLastNotifyMax == -1 || f > m_sinceLastNotifyMax) {
-                    m_sinceLastNotifyMax = f;
-                }
-            }
-        }
-        
-        if (m_notifyOnAdd) {
-            emit modelChangedWithin(e.getFrame(),
-                                    e.getFrame() + e.getDuration() + m_resolution);
-        }
-        if (allChange) {
-            emit modelChanged();
-        }
-    }
-    
-    void deletePoint(Event e) {
-        {
-            QMutexLocker locker(&m_mutex);
-            m_events.remove(e);
-        }
-        emit modelChangedWithin(e.getFrame(),
-                                e.getFrame() + e.getDuration() + m_resolution);
-    }
-    
-    EventVector getPoints() const /*!!! override? - and/or rename? */ {
-        EventVector ee;
-        for (int i = 0; i < m_events.count(); ++i) {
-            ee.push_back(m_events.getEventByIndex(i));
-        }
-        return ee;
-    }
-
-    //!!! bleah
-    EventVector getPoints(sv_frame_t start, sv_frame_t end) const {
-        return m_events.getEventsSpanning(start, end - start);        
-    }
-    
-    int getPointCount() const {
-        return m_events.count();
-    }
-
-    bool isEmpty() const {
-        return m_events.isEmpty();
-    }
-
-    bool containsPoint(const Event &e) const {
-        return m_events.contains(e);
-    }
-
     Command *getSetDataCommand(int row, int column, const QVariant &value, int role) override
     {
         if (row < 0 || row >= m_events.count()) return nullptr;
@@ -362,9 +356,9 @@
         }
 
         EditCommand *command = new EditCommand(this, tr("Edit Data"));
-        command->deletePoint(e0);
-        command->addPoint(e1);
-        return command;
+        command->remove(e0);
+        command->add(e1);
+        return command->finish();
     }
 
     SortType getSortType(int column) const override
@@ -405,6 +399,35 @@
         return notes;
     }
 
+    /**
+     * XmlExportable methods.
+     */
+    
+    void toXml(QTextStream &out,
+               QString indent = "",
+               QString extraAttributes = "") const override {
+
+        //!!! what is valueQuantization used for?
+        
+        Model::toXml
+            (out,
+             indent,
+             QString("type=\"sparse\" dimensions=\"3\" resolution=\"%1\" "
+                     "notifyOnAdd=\"%2\" dataset=\"%3\" subtype=\"note\" "
+                     "valueQuantization=\"%4\" minimum=\"%5\" maximum=\"%6\" "
+                     "units=\"%7\" %8")
+             .arg(m_resolution)
+             .arg(m_notifyOnAdd ? "true" : "false")
+             .arg(getObjectExportId(&m_events))
+             .arg(m_valueQuantization)
+             .arg(m_valueMinimum)
+             .arg(m_valueMaximum)
+             .arg(m_units)
+             .arg(extraAttributes));
+
+        m_events.toXml(out, indent, QString("dimensions=\"3\""));
+    }
+
 protected:
     sv_samplerate_t m_sampleRate;
     int m_resolution;
--- a/data/model/test/TestSparseModels.h	Wed Mar 13 14:50:10 2019 +0000
+++ b/data/model/test/TestSparseModels.h	Wed Mar 13 16:00:13 2019 +0000
@@ -138,28 +138,28 @@
     void note_extents() {
         NoteModel m(100, 10, false);
         Event p1(20, 123.4f, 40, 0.8f, "note 1");
-        m.addPoint(p1);
+        m.add(p1);
         QCOMPARE(m.isEmpty(), false);
-        QCOMPARE(m.getPointCount(), 1);
+        QCOMPARE(m.getEventCount(), 1);
         Event p2(50, 124.3f, 30, 0.9f, "note 2");
-        m.addPoint(p2);
+        m.add(p2);
         QCOMPARE(m.isEmpty(), false);
-        QCOMPARE(m.getPointCount(), 2);
-        QCOMPARE(m.getPoints().size(), 2);
-        QCOMPARE(*m.getPoints().begin(), p1);
-        QCOMPARE(*m.getPoints().rbegin(), p2);
+        QCOMPARE(m.getEventCount(), 2);
+        QCOMPARE(m.getAllEvents().size(), 2);
+        QCOMPARE(*m.getAllEvents().begin(), p1);
+        QCOMPARE(*m.getAllEvents().rbegin(), p2);
         QCOMPARE(m.getStartFrame(), 20);
         QCOMPARE(m.getEndFrame(), 80);
-        QCOMPARE(m.containsPoint(p1), true);
+        QCOMPARE(m.containsEvent(p1), true);
         QCOMPARE(m.getValueMinimum(), 123.4f);
         QCOMPARE(m.getValueMaximum(), 124.3f);
-        m.deletePoint(p1);
-        QCOMPARE(m.getPointCount(), 1);
-        QCOMPARE(m.getPoints().size(), 1);
-        QCOMPARE(*m.getPoints().begin(), p2);
+        m.remove(p1);
+        QCOMPARE(m.getEventCount(), 1);
+        QCOMPARE(m.getAllEvents().size(), 1);
+        QCOMPARE(*m.getAllEvents().begin(), p2);
         QCOMPARE(m.getStartFrame(), 50);
         QCOMPARE(m.getEndFrame(), 80);
-        QCOMPARE(m.containsPoint(p1), false);
+        QCOMPARE(m.containsEvent(p1), false);
     }
              
     void note_sample() {
@@ -167,30 +167,29 @@
         Event p1(20, 123.4f, 10, 0.8f, "note 1");
         Event p2(20, 124.3f, 20, 0.9f, "note 2");
         Event p3(50, 126.3f, 30, 0.9f, "note 3");
-        m.addPoint(p1);
-        m.addPoint(p2);
-        m.addPoint(p3);
+        m.add(p1);
+        m.add(p2);
+        m.add(p3);
 
-        QCOMPARE(m.getPoints().size(), 3);
-        QCOMPARE(*m.getPoints().begin(), p1);
-        QCOMPARE(*m.getPoints().rbegin(), p3);
+        QCOMPARE(m.getAllEvents().size(), 3);
+        QCOMPARE(*m.getAllEvents().begin(), p1);
+        QCOMPARE(*m.getAllEvents().rbegin(), p3);
 
-        auto pp = m.getPoints(20, 30);
+        auto pp = m.getEventsSpanning(20, 10);
         QCOMPARE(pp.size(), 2);
         QCOMPARE(*pp.begin(), p1);
         QCOMPARE(*pp.rbegin(), p2);
 
-        pp = m.getPoints(30, 50);
+        pp = m.getEventsSpanning(30, 20);
         QCOMPARE(pp.size(), 1);
         QCOMPARE(*pp.begin(), p2);
 
-        pp = m.getPoints(40, 50);
+        pp = m.getEventsSpanning(40, 10);
         QCOMPARE(pp.size(), 0);
 
-        //!!! this is a poor api
-        pp = m.getPoints(50, 50);
-        QCOMPARE(pp.size(), 0);
-//        QCOMPARE(*pp.begin(), p3);
+        pp = m.getEventsCovering(50);
+        QCOMPARE(pp.size(), 1);
+        QCOMPARE(*pp.begin(), p3);
     }
 
     void note_xml() {
@@ -199,9 +198,9 @@
         Event p2(20, 124.3f, 10, 0.9f, "note 2");
         Event p3(50, 126.3f, 30, 0.9f, "note 3");
         m.setScaleUnits("Hz");
-        m.addPoint(p1);
-        m.addPoint(p2);
-        m.addPoint(p3);
+        m.add(p1);
+        m.add(p2);
+        m.add(p3);
         QString xml;
         QTextStream str(&xml, QIODevice::WriteOnly);
         m.toXml(str);
--- a/rdf/RDFExporter.cpp	Wed Mar 13 14:50:10 2019 +0000
+++ b/rdf/RDFExporter.cpp	Wed Mar 13 16:00:13 2019 +0000
@@ -103,7 +103,7 @@
         if (m) {
             f.hasTimestamp = true;
             f.hasDuration = true;
-            EventVector ee(m->getPoints());
+            EventVector ee(m->getAllEvents());
             for (auto e: ee) {
                 f.timestamp = RealTime::frame2RealTime(e.getFrame(), sr).toVampRealTime();
                 f.duration = RealTime::frame2RealTime(e.getDuration(), sr).toVampRealTime();
--- a/rdf/RDFImporter.cpp	Wed Mar 13 14:50:10 2019 +0000
+++ b/rdf/RDFImporter.cpp	Wed Mar 13 16:00:13 2019 +0000
@@ -745,8 +745,8 @@
                     level = values[1];
                 }
             }
-            Event point(ftime, value, fduration, level, label);
-            nm->addPoint(point);
+            Event e(ftime, value, fduration, level, label);
+            nm->add(e);
         } else {
             float value = 0.f, duration = 1.f, level = 1.f;
             if (!values.empty()) {
@@ -758,9 +758,9 @@
                     }
                 }
             }
-            Event point(ftime, value, sv_frame_t(lrintf(duration)),
+            Event e(ftime, value, sv_frame_t(lrintf(duration)),
                         level, label);
-            nm->addPoint(point);
+            nm->add(e);
         }
         return;
     }
--- a/transform/FeatureExtractionModelTransformer.cpp	Wed Mar 13 14:50:10 2019 +0000
+++ b/transform/FeatureExtractionModelTransformer.cpp	Wed Mar 13 16:00:13 2019 +0000
@@ -1073,10 +1073,10 @@
 
             NoteModel *model = getConformingOutput<NoteModel>(n);
             if (!model) return;
-            model->addPoint(Event(frame, value, // value is pitch
-                                  duration,
-                                  velocity / 127.f,
-                                  feature.label.c_str()));
+            model->add(Event(frame, value, // value is pitch
+                             duration,
+                             velocity / 127.f,
+                             feature.label.c_str()));
         } else {
 
             RegionModel *model = getConformingOutput<RegionModel>(n);