annotate data/model/RegionModel.h @ 1008:d9e0e59a1581

When using an aggregate model to pass data to a transform, zero-pad the shorter input to the duration of the longer rather than truncating the longer. (This is better behaviour for e.g. MATCH, and in any case the code was previously truncating incorrectly and ending up with garbage data at the end.)
author Chris Cannam
date Fri, 14 Nov 2014 13:51:33 +0000
parents 59e7fe1b1003
children cc27f35aa75c
rev   line source
Chris@441 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@441 2
Chris@441 3 /*
Chris@441 4 Sonic Visualiser
Chris@441 5 An audio file viewer and annotation editor.
Chris@441 6 Centre for Digital Music, Queen Mary, University of London.
Chris@441 7 This file copyright 2006 Chris Cannam.
Chris@441 8
Chris@441 9 This program is free software; you can redistribute it and/or
Chris@441 10 modify it under the terms of the GNU General Public License as
Chris@441 11 published by the Free Software Foundation; either version 2 of the
Chris@441 12 License, or (at your option) any later version. See the file
Chris@441 13 COPYING included with this distribution for more information.
Chris@441 14 */
Chris@441 15
Chris@441 16 #ifndef _REGION_MODEL_H_
Chris@441 17 #define _REGION_MODEL_H_
Chris@441 18
Chris@441 19 #include "IntervalModel.h"
Chris@441 20 #include "base/RealTime.h"
Chris@441 21
Chris@441 22 /**
Chris@441 23 * RegionModel -- a concrete IntervalModel for intervals associated
Chris@441 24 * with a value, which we call regions for no very compelling reason.
Chris@441 25 */
Chris@441 26
Chris@441 27 /**
Chris@441 28 * Region "point" type. A region is something that has an onset time,
Chris@441 29 * a single value, and a duration. Like other points, it can also
Chris@441 30 * have a label.
Chris@441 31 *
Chris@441 32 * This is called RegionRec instead of Region to avoid name collisions
Chris@441 33 * with the X11 Region struct. Bah.
Chris@441 34 */
Chris@441 35
Chris@441 36 struct RegionRec
Chris@441 37 {
Chris@441 38 public:
Chris@631 39 RegionRec() : frame(0), value(0.f), duration(0) { }
Chris@441 40 RegionRec(long _frame) : frame(_frame), value(0.0f), duration(0) { }
Chris@929 41 RegionRec(long _frame, float _value, int _duration, QString _label) :
Chris@441 42 frame(_frame), value(_value), duration(_duration), label(_label) { }
Chris@441 43
Chris@441 44 int getDimensions() const { return 3; }
Chris@441 45
Chris@441 46 long frame;
Chris@441 47 float value;
Chris@929 48 int duration;
Chris@441 49 QString label;
Chris@441 50
Chris@441 51 QString getLabel() const { return label; }
Chris@441 52
Chris@441 53 void toXml(QTextStream &stream,
Chris@441 54 QString indent = "",
Chris@441 55 QString extraAttributes = "") const
Chris@441 56 {
Chris@441 57 stream <<
Chris@441 58 QString("%1<point frame=\"%2\" value=\"%3\" duration=\"%4\" label=\"%5\" %6/>\n")
Chris@627 59 .arg(indent).arg(frame).arg(value).arg(duration)
Chris@627 60 .arg(XmlExportable::encodeEntities(label)).arg(extraAttributes);
Chris@441 61 }
Chris@441 62
Chris@929 63 QString toDelimitedDataString(QString delimiter, int sampleRate) const
Chris@441 64 {
Chris@441 65 QStringList list;
Chris@441 66 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
Chris@441 67 list << QString("%1").arg(value);
Chris@441 68 list << RealTime::frame2RealTime(duration, sampleRate).toString().c_str();
Chris@441 69 if (label != "") list << label;
Chris@441 70 return list.join(delimiter);
Chris@441 71 }
Chris@441 72
Chris@441 73 struct Comparator {
Chris@441 74 bool operator()(const RegionRec &p1,
Chris@441 75 const RegionRec &p2) const {
Chris@441 76 if (p1.frame != p2.frame) return p1.frame < p2.frame;
Chris@441 77 if (p1.value != p2.value) return p1.value < p2.value;
Chris@441 78 if (p1.duration != p2.duration) return p1.duration < p2.duration;
Chris@441 79 return p1.label < p2.label;
Chris@441 80 }
Chris@441 81 };
Chris@441 82
Chris@441 83 struct OrderComparator {
Chris@441 84 bool operator()(const RegionRec &p1,
Chris@441 85 const RegionRec &p2) const {
Chris@441 86 return p1.frame < p2.frame;
Chris@441 87 }
Chris@441 88 };
Chris@441 89 };
Chris@441 90
Chris@441 91
Chris@441 92 class RegionModel : public IntervalModel<RegionRec>
Chris@441 93 {
Chris@441 94 Q_OBJECT
Chris@441 95
Chris@441 96 public:
Chris@929 97 RegionModel(int sampleRate, int resolution,
Chris@441 98 bool notifyOnAdd = true) :
Chris@441 99 IntervalModel<RegionRec>(sampleRate, resolution, notifyOnAdd),
Chris@442 100 m_valueQuantization(0),
Chris@442 101 m_haveDistinctValues(false)
Chris@441 102 {
Chris@441 103 }
Chris@441 104
Chris@929 105 RegionModel(int sampleRate, int resolution,
Chris@459 106 float valueMinimum, float valueMaximum,
Chris@459 107 bool notifyOnAdd = true) :
Chris@441 108 IntervalModel<RegionRec>(sampleRate, resolution,
Chris@441 109 valueMinimum, valueMaximum,
Chris@441 110 notifyOnAdd),
Chris@442 111 m_valueQuantization(0),
Chris@442 112 m_haveDistinctValues(false)
Chris@441 113 {
Chris@441 114 }
Chris@441 115
Chris@441 116 virtual ~RegionModel()
Chris@441 117 {
Chris@441 118 }
Chris@441 119
Chris@441 120 float getValueQuantization() const { return m_valueQuantization; }
Chris@441 121 void setValueQuantization(float q) { m_valueQuantization = q; }
Chris@441 122
Chris@442 123 bool haveDistinctValues() const { return m_haveDistinctValues; }
Chris@442 124
Chris@441 125 QString getTypeName() const { return tr("Region"); }
Chris@441 126
Chris@441 127 virtual void toXml(QTextStream &out,
Chris@441 128 QString indent = "",
Chris@441 129 QString extraAttributes = "") const
Chris@441 130 {
Chris@441 131 std::cerr << "RegionModel::toXml: extraAttributes = \""
Chris@441 132 << extraAttributes.toStdString() << std::endl;
Chris@441 133
Chris@441 134 IntervalModel<RegionRec>::toXml
Chris@441 135 (out,
Chris@441 136 indent,
Chris@452 137 QString("%1 subtype=\"region\" valueQuantization=\"%2\"")
Chris@441 138 .arg(extraAttributes).arg(m_valueQuantization));
Chris@441 139 }
Chris@441 140
Chris@441 141 /**
Chris@441 142 * TabularModel methods.
Chris@441 143 */
Chris@441 144
Chris@441 145 virtual int getColumnCount() const
Chris@441 146 {
Chris@618 147 return 5;
Chris@441 148 }
Chris@441 149
Chris@441 150 virtual QString getHeading(int column) const
Chris@441 151 {
Chris@441 152 switch (column) {
Chris@441 153 case 0: return tr("Time");
Chris@441 154 case 1: return tr("Frame");
Chris@441 155 case 2: return tr("Value");
Chris@441 156 case 3: return tr("Duration");
Chris@441 157 case 4: return tr("Label");
Chris@441 158 default: return tr("Unknown");
Chris@441 159 }
Chris@441 160 }
Chris@441 161
Chris@441 162 virtual QVariant getData(int row, int column, int role) const
Chris@441 163 {
Chris@441 164 if (column < 4) {
Chris@441 165 return IntervalModel<RegionRec>::getData(row, column, role);
Chris@441 166 }
Chris@441 167
Chris@608 168 PointListConstIterator i = getPointListIteratorForRow(row);
Chris@441 169 if (i == m_points.end()) return QVariant();
Chris@441 170
Chris@441 171 switch (column) {
Chris@441 172 case 4: return i->label;
Chris@441 173 default: return QVariant();
Chris@441 174 }
Chris@441 175 }
Chris@441 176
Chris@441 177 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
Chris@441 178 {
Chris@441 179 if (column < 4) {
Chris@441 180 return IntervalModel<RegionRec>::getSetDataCommand
Chris@441 181 (row, column, value, role);
Chris@441 182 }
Chris@441 183
Chris@740 184 if (role != Qt::EditRole) return 0;
Chris@441 185 PointListIterator i = getPointListIteratorForRow(row);
Chris@740 186 if (i == m_points.end()) return 0;
Chris@441 187 EditCommand *command = new EditCommand(this, tr("Edit Data"));
Chris@441 188
Chris@441 189 Point point(*i);
Chris@441 190 command->deletePoint(point);
Chris@441 191
Chris@441 192 switch (column) {
Chris@441 193 case 4: point.label = value.toString(); break;
Chris@441 194 }
Chris@441 195
Chris@441 196 command->addPoint(point);
Chris@441 197 return command->finish();
Chris@441 198 }
Chris@441 199
Chris@441 200 virtual SortType getSortType(int column) const
Chris@441 201 {
Chris@618 202 if (column == 4) return SortAlphabetical;
Chris@441 203 return SortNumeric;
Chris@441 204 }
Chris@441 205
Chris@442 206 virtual void addPoint(const Point &point)
Chris@442 207 {
Chris@442 208 if (point.value != 0.f) m_haveDistinctValues = true;
Chris@442 209 IntervalModel<RegionRec>::addPoint(point);
Chris@442 210 }
Chris@442 211
Chris@441 212 protected:
Chris@441 213 float m_valueQuantization;
Chris@442 214 bool m_haveDistinctValues;
Chris@441 215 };
Chris@441 216
Chris@441 217 #endif