changeset 1679:0d89abd631ac single-point

Re-add the toDelimitedDataString stuff
author Chris Cannam
date Thu, 28 Mar 2019 16:03:36 +0000
parents 1078f0ef3012
children c9a15ee5dc1d
files base/EventSeries.cpp base/EventSeries.h data/fileio/CSVStreamWriter.h data/fileio/test/CSVStreamWriterTest.h data/model/AlignmentModel.h data/model/Dense3DModelPeakCache.h data/model/DenseTimeValueModel.cpp data/model/DenseTimeValueModel.h data/model/EditableDenseThreeDimensionalModel.cpp data/model/EditableDenseThreeDimensionalModel.h data/model/FFTModel.h data/model/ImageModel.h data/model/Model.h data/model/NoteModel.h data/model/PathModel.h data/model/RegionModel.h data/model/SparseOneDimensionalModel.h data/model/SparseTimeValueModel.h data/model/TextModel.h data/model/test/TestSparseModels.h
diffstat 20 files changed, 232 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/base/EventSeries.cpp	Thu Mar 28 13:37:09 2019 +0000
+++ b/base/EventSeries.cpp	Thu Mar 28 16:03:36 2019 +0000
@@ -14,6 +14,16 @@
 
 #include "EventSeries.h"
 
+EventSeries
+EventSeries::fromEvents(const EventVector &v)
+{
+    EventSeries s;
+    for (const auto &e: v) {
+        s.add(e);
+    }
+    return s;
+}
+
 bool
 EventSeries::isEmpty() const
 {
@@ -505,4 +515,68 @@
     out << indent << "</dataset>\n";
 }
 
+QString
+EventSeries::toDelimitedDataString(QString delimiter,
+                                   DataExportOptions options,
+                                   sv_frame_t startFrame,
+                                   sv_frame_t duration,
+                                   sv_samplerate_t sampleRate,
+                                   sv_frame_t resolution,
+                                   Event fillEvent) const
+{
+    QString s;
 
+    const sv_frame_t end = startFrame + duration;
+
+    auto pitr = lower_bound(m_events.begin(), m_events.end(),
+                            Event(startFrame));
+            
+    if (!(options & DataExportFillGaps)) {
+        
+        while (pitr != m_events.end() && pitr->getFrame() < end) {
+            s += pitr->toDelimitedDataString(delimiter,
+                                             options,
+                                             sampleRate);
+            s += "\n";
+            ++pitr;
+        }
+
+    } else {
+        
+        // find frame time of first point in range (if any)
+        sv_frame_t first = startFrame;
+        if (pitr != m_events.end()) {
+            first = pitr->getFrame();
+        }
+
+        // project back to first frame time in range according to
+        // resolution.  e.g. if f0 = 2, first = 9, resolution = 4 then
+        // we start at 5 (because 1 is too early and we need to arrive
+        // at 9 to match the first actual point). This method is
+        // stupid but easy to understand:
+        sv_frame_t f = first;
+        while (f >= startFrame + resolution) f -= resolution;
+        
+        // now progress, either writing the next point (if within
+        // distance) or a default fill point
+        while (f < end) {
+            if (pitr != m_events.end() && pitr->getFrame() <= f) {
+                s += pitr->toDelimitedDataString
+                    (delimiter,
+                     options & ~DataExportFillGaps,
+                     sampleRate);
+                ++pitr;
+            } else {
+                s += fillEvent.withFrame(f).toDelimitedDataString
+                    (delimiter,
+                     options & ~DataExportFillGaps,
+                     sampleRate);
+            }
+            s += "\n";
+            f += resolution;
+        }
+    }
+    
+    return s;
+}
+
--- a/base/EventSeries.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/base/EventSeries.h	Thu Mar 28 16:03:36 2019 +0000
@@ -52,6 +52,8 @@
     bool operator==(const EventSeries &other) const {
         return m_events == other.m_events;
     }
+
+    static EventSeries fromEvents(const EventVector &ee);
     
     void clear();
     void add(const Event &e);
@@ -213,6 +215,18 @@
                QString indent,
                QString extraAttributes,
                Event::ExportNameOptions) const;
+
+    /**
+     * Emit events starting within the given range to a delimited
+     * (e.g. comma-separated) data format.
+     */
+    QString toDelimitedDataString(QString delimiter,
+                                  DataExportOptions options,
+                                  sv_frame_t startFrame,
+                                  sv_frame_t duration,
+                                  sv_samplerate_t sampleRate,
+                                  sv_frame_t resolution,
+                                  Event fillEvent) const;
     
 private:
     /**
--- a/data/fileio/CSVStreamWriter.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/fileio/CSVStreamWriter.h	Thu Mar 28 16:03:36 2019 +0000
@@ -68,11 +68,11 @@
 
             const auto start = readPtr;
             const auto end = std::min(start + blockSize, endFrame);
-            const auto data = model.toDelimitedDataStringSubsetWithOptions(
+            const auto data = model.toDelimitedDataString(
                 delimiter,
                 options,
                 start,
-                end
+                end - start
             ).trimmed();
 
             if ( data != "" ) {
--- a/data/fileio/test/CSVStreamWriterTest.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/fileio/test/CSVStreamWriterTest.h	Thu Mar 28 16:03:36 2019 +0000
@@ -303,7 +303,9 @@
 //        qDebug("Create Expected Output\n");
 
         // NB. removed end line break
-        const auto expectedOutput = notes.toDelimitedDataString(",").trimmed();
+        const auto expectedOutput =
+            notes.toDelimitedDataString(",", {}, 0, notes.getEndFrame())
+            .trimmed();
 
         StubReporter reporter { []() -> bool { return false; } };
         std::ostringstream oss;
@@ -321,6 +323,7 @@
 //        qDebug("\n->>%s<<-\n", expectedOutput.toLocal8Bit().data());
 //        qDebug("\n->>%s<<-\n", oss.str().c_str());
         QVERIFY( wroteSparseModel == true );
+        QVERIFY( oss.str() != std::string() );
         QVERIFY( oss.str() == expectedOutput.toStdString() );
     }
 };
--- a/data/model/AlignmentModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/AlignmentModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -63,6 +63,11 @@
                        QString indent = "",
                        QString extraAttributes = "") const override;
 
+    QString toDelimitedDataString(QString, DataExportOptions,
+                                  sv_frame_t, sv_frame_t) const override {
+        return "";
+    }
+
 signals:
     void modelChanged();
     void modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame);
--- a/data/model/Dense3DModelPeakCache.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/Dense3DModelPeakCache.h	Thu Mar 28 16:03:36 2019 +0000
@@ -97,6 +97,11 @@
         return m_source->getCompletion();
     }
 
+    QString toDelimitedDataString(QString, DataExportOptions,
+                                  sv_frame_t, sv_frame_t) const override {
+        return "";
+    }
+
 protected slots:
     void sourceModelChanged();
     void sourceModelAboutToBeDeleted();
--- a/data/model/DenseTimeValueModel.cpp	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/DenseTimeValueModel.cpp	Thu Mar 28 16:03:36 2019 +0000
@@ -29,22 +29,23 @@
 }
         
 QString
-DenseTimeValueModel::toDelimitedDataStringSubset(QString delimiter, sv_frame_t f0, sv_frame_t f1) const
+DenseTimeValueModel::toDelimitedDataString(QString delimiter,
+                                           DataExportOptions,
+                                           sv_frame_t startFrame,
+                                           sv_frame_t duration) const
 {
     int ch = getChannelCount();
 
-//    cerr << "f0 = " << f0 << ", f1 = " << f1 << endl;
+    if (duration <= 0) return "";
 
-    if (f1 <= f0) return "";
-
-    auto data = getMultiChannelData(0, ch - 1, f0, f1 - f0);
+    auto data = getMultiChannelData(0, ch - 1, startFrame, duration);
 
     if (data.empty() || data[0].empty()) return "";
     
     QStringList list;
     for (sv_frame_t i = 0; in_range_for(data[0], i); ++i) {
         QStringList parts;
-        parts << QString("%1").arg(f0 + i);
+        parts << QString("%1").arg(startFrame + i);
         for (int c = 0; in_range_for(data, c); ++c) {
             parts << QString("%1").arg(data[c][i]);
         }
--- a/data/model/DenseTimeValueModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/DenseTimeValueModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -82,8 +82,10 @@
     bool canPlay() const override { return true; }
     QString getDefaultPlayClipId() const override { return ""; }
 
-    QString toDelimitedDataStringSubset(QString delimiter,
-                                        sv_frame_t f0, sv_frame_t f1) const override;
+    QString toDelimitedDataString(QString delimiter,
+                                  DataExportOptions options,
+                                  sv_frame_t startFrame,
+                                  sv_frame_t duration) const override;
 
     QString getTypeName() const override { return tr("Dense Time-Value"); }
 };
--- a/data/model/EditableDenseThreeDimensionalModel.cpp	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/EditableDenseThreeDimensionalModel.cpp	Thu Mar 28 16:03:36 2019 +0000
@@ -487,28 +487,16 @@
 }
 
 QString
-EditableDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter) const
-{
-    QReadLocker locker(&m_lock);
-    QString s;
-    for (int i = 0; in_range_for(m_data, i); ++i) {
-        QStringList list;
-        for (int j = 0; in_range_for(m_data.at(i), j); ++j) {
-            list << QString("%1").arg(m_data.at(i).at(j));
-        }
-        s += list.join(delimiter) + "\n";
-    }
-    return s;
-}
-
-QString
-EditableDenseThreeDimensionalModel::toDelimitedDataStringSubset(QString delimiter, sv_frame_t f0, sv_frame_t f1) const
+EditableDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter,
+                                                          DataExportOptions,
+                                                          sv_frame_t startFrame,
+                                                          sv_frame_t duration) const
 {
     QReadLocker locker(&m_lock);
     QString s;
     for (int i = 0; in_range_for(m_data, i); ++i) {
         sv_frame_t fr = m_startFrame + i * m_resolution;
-        if (fr >= f0 && fr < f1) {
+        if (fr >= startFrame && fr < startFrame + duration) {
             QStringList list;
             for (int j = 0; in_range_for(m_data.at(i), j); ++j) {
                 list << QString("%1").arg(m_data.at(i).at(j));
--- a/data/model/EditableDenseThreeDimensionalModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/EditableDenseThreeDimensionalModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -188,8 +188,10 @@
 
     QString getTypeName() const override { return tr("Editable Dense 3-D"); }
 
-    QString toDelimitedDataString(QString delimiter) const override;
-    QString toDelimitedDataStringSubset(QString delimiter, sv_frame_t f0, sv_frame_t f1) const override;
+    QString toDelimitedDataString(QString delimiter,
+                                  DataExportOptions options,
+                                  sv_frame_t startFrame,
+                                  sv_frame_t duration) const override;
 
     void toXml(QTextStream &out,
                        QString indent = "",
--- a/data/model/FFTModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/FFTModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -88,6 +88,10 @@
     }
     virtual QString getError() const { return ""; } //!!!???
     virtual sv_frame_t getFillExtent() const { return getEndFrame(); }
+    QString toDelimitedDataString(QString, DataExportOptions,
+                                  sv_frame_t, sv_frame_t) const override {
+        return "";
+    }
 
     // FFTModel methods:
     //
--- a/data/model/ImageModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/ImageModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -261,7 +261,20 @@
         
         m_events.toXml(out, indent, QString("dimensions=\"1\""), options);
     }
-  
+
+    QString toDelimitedDataString(QString delimiter,
+                                  DataExportOptions options,
+                                  sv_frame_t startFrame,
+                                  sv_frame_t duration) const override {
+        return m_events.toDelimitedDataString(delimiter,
+                                              options,
+                                              startFrame,
+                                              duration,
+                                              m_sampleRate,
+                                              m_resolution,
+                                              Event().withValue(0.f));
+    }
+    
 protected:
     sv_samplerate_t m_sampleRate;
     int m_resolution;
--- a/data/model/Model.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/Model.h	Thu Mar 28 16:03:36 2019 +0000
@@ -257,21 +257,10 @@
                QString indent = "",
                QString extraAttributes = "") const override;
 
-    virtual QString toDelimitedDataString(QString delimiter) const {
-        return toDelimitedDataStringSubset
-            (delimiter, getStartFrame(), getEndFrame());
-    }
-    virtual QString toDelimitedDataStringWithOptions(QString delimiter, DataExportOptions opts) const {
-        return toDelimitedDataStringSubsetWithOptions
-            (delimiter, opts, getStartFrame(), getEndFrame());
-    }
-    virtual QString toDelimitedDataStringSubset(QString, sv_frame_t /* f0 */, sv_frame_t /* f1 */) const {
-        return "";
-    }
-    virtual QString toDelimitedDataStringSubsetWithOptions(QString delimiter, DataExportOptions, sv_frame_t f0, sv_frame_t f1) const {
-        // Default implementation supports no options
-        return toDelimitedDataStringSubset(delimiter, f0, f1);
-    }
+    virtual QString toDelimitedDataString(QString delimiter,
+                                          DataExportOptions options,
+                                          sv_frame_t startFrame,
+                                          sv_frame_t duration) const = 0;
 
 public slots:
     void aboutToDelete();
--- a/data/model/NoteModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/NoteModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -384,6 +384,20 @@
         m_events.toXml(out, indent, QString("dimensions=\"3\""));
     }
 
+    QString toDelimitedDataString(QString delimiter,
+                                  DataExportOptions options,
+                                  sv_frame_t startFrame,
+                                  sv_frame_t duration) const override {
+        return m_events.toDelimitedDataString
+            (delimiter,
+             options,
+             startFrame,
+             duration,
+             m_sampleRate,
+             m_resolution,
+             Event().withValue(0.f).withDuration(0.f).withLevel(0.f));
+    }
+
 protected:
     Subtype m_subtype;
     sv_samplerate_t m_sampleRate;
--- a/data/model/PathModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/PathModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -192,6 +192,24 @@
 
         out << indent << "</dataset>\n";
     }
+
+    QString toDelimitedDataString(QString delimiter,
+                                  DataExportOptions,
+                                  sv_frame_t startFrame,
+                                  sv_frame_t duration) const override {
+
+        QString s;
+        for (PathPoint p: m_points) {
+            if (p.frame < startFrame) continue;
+            if (p.frame >= startFrame + duration) break;
+            s += QString("%1%2%3\n")
+                .arg(p.frame)
+                .arg(delimiter)
+                .arg(p.mapframe);
+        }
+
+        return s;
+    }
     
 protected:
     sv_samplerate_t m_sampleRate;
--- a/data/model/RegionModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/RegionModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -326,7 +326,21 @@
         
         m_events.toXml(out, indent, QString("dimensions=\"3\""));
     }
-    
+
+    QString toDelimitedDataString(QString delimiter,
+                                  DataExportOptions options,
+                                  sv_frame_t startFrame,
+                                  sv_frame_t duration) const override {
+        return m_events.toDelimitedDataString
+            (delimiter,
+             options,
+             startFrame,
+             duration,
+             m_sampleRate,
+             m_resolution,
+             Event().withValue(0.f).withDuration(m_resolution));
+    }
+
 protected:
     sv_samplerate_t m_sampleRate;
     int m_resolution;
--- a/data/model/SparseOneDimensionalModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/SparseOneDimensionalModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -290,6 +290,19 @@
         
         m_events.toXml(out, indent, QString("dimensions=\"1\""));
     }
+
+    QString toDelimitedDataString(QString delimiter,
+                                  DataExportOptions options,
+                                  sv_frame_t startFrame,
+                                  sv_frame_t duration) const override {
+        return m_events.toDelimitedDataString(delimiter,
+                                              options,
+                                              startFrame,
+                                              duration,
+                                              m_sampleRate,
+                                              m_resolution,
+                                              Event());
+    }
     
 protected:
     sv_samplerate_t m_sampleRate;
--- a/data/model/SparseTimeValueModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/SparseTimeValueModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -321,6 +321,19 @@
         
         m_events.toXml(out, indent, QString("dimensions=\"2\""));
     }
+
+    QString toDelimitedDataString(QString delimiter,
+                                  DataExportOptions options,
+                                  sv_frame_t startFrame,
+                                  sv_frame_t duration) const override {
+        return m_events.toDelimitedDataString(delimiter,
+                                              options,
+                                              startFrame,
+                                              duration,
+                                              m_sampleRate,
+                                              m_resolution,
+                                              Event().withValue(0.f));
+    }
   
 protected:
     sv_samplerate_t m_sampleRate;
--- a/data/model/TextModel.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/TextModel.h	Thu Mar 28 16:03:36 2019 +0000
@@ -256,6 +256,19 @@
         
         m_events.toXml(out, indent, QString("dimensions=\"2\""), options);
     }
+
+    QString toDelimitedDataString(QString delimiter,
+                                  DataExportOptions options,
+                                  sv_frame_t startFrame,
+                                  sv_frame_t duration) const override {
+        return m_events.toDelimitedDataString(delimiter,
+                                              options,
+                                              startFrame,
+                                              duration,
+                                              m_sampleRate,
+                                              m_resolution,
+                                              Event().withValue(0.f));
+    }
   
 protected:
     sv_samplerate_t m_sampleRate;
--- a/data/model/test/TestSparseModels.h	Thu Mar 28 13:37:09 2019 +0000
+++ b/data/model/test/TestSparseModels.h	Thu Mar 28 16:03:36 2019 +0000
@@ -300,7 +300,6 @@
         }
         QCOMPARE(xml, expected);
     }
-
 };
 
 #endif