# HG changeset patch # User Chris Cannam # Date 1552492813 0 # Node ID 513192aa9b03f99fa53ed9c690ffba069454ffad # Parent 7a23dfe65d6629a681099ed889ff007d57a2e0ea Further API updates diff -r 7a23dfe65d66 -r 513192aa9b03 base/EventSeries.cpp --- 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 { diff -r 7a23dfe65d66 -r 513192aa9b03 base/EventSeries.h --- 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 diff -r 7a23dfe65d66 -r 513192aa9b03 data/fileio/CSVFileReader.cpp --- 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) { diff -r 7a23dfe65d66 -r 513192aa9b03 data/fileio/MIDIFileReader.cpp --- 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; } diff -r 7a23dfe65d66 -r 513192aa9b03 data/fileio/test/CSVStreamWriterTest.h --- 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"); diff -r 7a23dfe65d66 -r 513192aa9b03 data/model/NoteModel.h --- 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 m_add; + std::set 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 m_add; - std::set 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; diff -r 7a23dfe65d66 -r 513192aa9b03 data/model/test/TestSparseModels.h --- 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); diff -r 7a23dfe65d66 -r 513192aa9b03 rdf/RDFExporter.cpp --- 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(); diff -r 7a23dfe65d66 -r 513192aa9b03 rdf/RDFImporter.cpp --- 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; } diff -r 7a23dfe65d66 -r 513192aa9b03 transform/FeatureExtractionModelTransformer.cpp --- 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(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(n);