annotate data/model/SparseTimeValueModel.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 ad14e7ed096d
children cc27f35aa75c
rev   line source
Chris@147 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@147 2
Chris@147 3 /*
Chris@147 4 Sonic Visualiser
Chris@147 5 An audio file viewer and annotation editor.
Chris@147 6 Centre for Digital Music, Queen Mary, University of London.
Chris@147 7 This file copyright 2006 Chris Cannam.
Chris@147 8
Chris@147 9 This program is free software; you can redistribute it and/or
Chris@147 10 modify it under the terms of the GNU General Public License as
Chris@147 11 published by the Free Software Foundation; either version 2 of the
Chris@147 12 License, or (at your option) any later version. See the file
Chris@147 13 COPYING included with this distribution for more information.
Chris@147 14 */
Chris@147 15
Chris@147 16 #ifndef _SPARSE_TIME_VALUE_MODEL_H_
Chris@147 17 #define _SPARSE_TIME_VALUE_MODEL_H_
Chris@147 18
Chris@147 19 #include "SparseValueModel.h"
Chris@150 20 #include "base/PlayParameterRepository.h"
Chris@147 21 #include "base/RealTime.h"
Chris@147 22
Chris@147 23 /**
Chris@147 24 * Time/value point type for use in a SparseModel or SparseValueModel.
Chris@147 25 * With this point type, the model basically represents a wiggly-line
Chris@147 26 * plot with points at arbitrary intervals of the model resolution.
Chris@147 27 */
Chris@147 28
Chris@147 29 struct TimeValuePoint
Chris@147 30 {
Chris@147 31 public:
Chris@147 32 TimeValuePoint(long _frame) : frame(_frame), value(0.0f) { }
Chris@147 33 TimeValuePoint(long _frame, float _value, QString _label) :
Chris@147 34 frame(_frame), value(_value), label(_label) { }
Chris@147 35
Chris@147 36 int getDimensions() const { return 2; }
Chris@147 37
Chris@147 38 long frame;
Chris@147 39 float value;
Chris@147 40 QString label;
Chris@338 41
Chris@338 42 QString getLabel() const { return label; }
Chris@147 43
Chris@314 44 void toXml(QTextStream &stream, QString indent = "",
Chris@314 45 QString extraAttributes = "") const
Chris@147 46 {
Chris@314 47 stream << QString("%1<point frame=\"%2\" value=\"%3\" label=\"%4\" %5/>\n")
Chris@603 48 .arg(indent).arg(frame).arg(value).arg(XmlExportable::encodeEntities(label))
Chris@603 49 .arg(extraAttributes);
Chris@147 50 }
Chris@147 51
Chris@929 52 QString toDelimitedDataString(QString delimiter, int sampleRate) const
Chris@147 53 {
Chris@147 54 QStringList list;
Chris@147 55 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
Chris@147 56 list << QString("%1").arg(value);
Chris@318 57 if (label != "") list << label;
Chris@147 58 return list.join(delimiter);
Chris@147 59 }
Chris@147 60
Chris@147 61 struct Comparator {
Chris@147 62 bool operator()(const TimeValuePoint &p1,
Chris@147 63 const TimeValuePoint &p2) const {
Chris@147 64 if (p1.frame != p2.frame) return p1.frame < p2.frame;
Chris@147 65 if (p1.value != p2.value) return p1.value < p2.value;
Chris@147 66 return p1.label < p2.label;
Chris@147 67 }
Chris@147 68 };
Chris@147 69
Chris@147 70 struct OrderComparator {
Chris@147 71 bool operator()(const TimeValuePoint &p1,
Chris@147 72 const TimeValuePoint &p2) const {
Chris@147 73 return p1.frame < p2.frame;
Chris@147 74 }
Chris@147 75 };
Chris@147 76 };
Chris@147 77
Chris@147 78
Chris@147 79 class SparseTimeValueModel : public SparseValueModel<TimeValuePoint>
Chris@147 80 {
Chris@423 81 Q_OBJECT
Chris@423 82
Chris@147 83 public:
Chris@929 84 SparseTimeValueModel(int sampleRate, int resolution,
Chris@256 85 bool notifyOnAdd = true) :
Chris@256 86 SparseValueModel<TimeValuePoint>(sampleRate, resolution,
Chris@256 87 notifyOnAdd)
Chris@256 88 {
Chris@868 89 // Model is playable, but may not sound (if units not Hz or
Chris@868 90 // range unsuitable)
Chris@868 91 PlayParameterRepository::getInstance()->addPlayable(this);
Chris@256 92 }
Chris@256 93
Chris@929 94 SparseTimeValueModel(int sampleRate, int resolution,
Chris@147 95 float valueMinimum, float valueMaximum,
Chris@147 96 bool notifyOnAdd = true) :
Chris@147 97 SparseValueModel<TimeValuePoint>(sampleRate, resolution,
Chris@147 98 valueMinimum, valueMaximum,
Chris@147 99 notifyOnAdd)
Chris@147 100 {
Chris@868 101 // Model is playable, but may not sound (if units not Hz or
Chris@868 102 // range unsuitable)
Chris@868 103 PlayParameterRepository::getInstance()->addPlayable(this);
Chris@868 104 }
Chris@868 105
Chris@868 106 virtual ~SparseTimeValueModel()
Chris@868 107 {
Chris@868 108 PlayParameterRepository::getInstance()->removePlayable(this);
Chris@147 109 }
Chris@345 110
Chris@345 111 QString getTypeName() const { return tr("Sparse Time-Value"); }
Chris@420 112
Chris@868 113 virtual bool canPlay() const { return true; }
Chris@952 114 virtual bool getDefaultPlayAudible() const { return false; } // user must unmute
Chris@868 115
Chris@420 116 /**
Chris@420 117 * TabularModel methods.
Chris@420 118 */
Chris@420 119
Chris@420 120 virtual int getColumnCount() const
Chris@420 121 {
Chris@420 122 return 4;
Chris@420 123 }
Chris@420 124
Chris@420 125 virtual QString getHeading(int column) const
Chris@420 126 {
Chris@420 127 switch (column) {
Chris@420 128 case 0: return tr("Time");
Chris@420 129 case 1: return tr("Frame");
Chris@420 130 case 2: return tr("Value");
Chris@420 131 case 3: return tr("Label");
Chris@420 132 default: return tr("Unknown");
Chris@420 133 }
Chris@420 134 }
Chris@420 135
Chris@420 136 virtual QVariant getData(int row, int column, int role) const
Chris@420 137 {
Chris@425 138 if (column < 2) {
Chris@425 139 return SparseValueModel<TimeValuePoint>::getData
Chris@425 140 (row, column, role);
Chris@425 141 }
Chris@425 142
Chris@606 143 PointListConstIterator i = getPointListIteratorForRow(row);
Chris@420 144 if (i == m_points.end()) return QVariant();
Chris@420 145
Chris@420 146 switch (column) {
Chris@420 147 case 2:
Chris@422 148 if (role == Qt::EditRole || role == SortRole) return i->value;
Chris@420 149 else return QString("%1 %2").arg(i->value).arg(getScaleUnits());
Chris@420 150 case 3: return i->label;
Chris@420 151 default: return QVariant();
Chris@420 152 }
Chris@420 153 }
Chris@420 154
Chris@424 155 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
Chris@420 156 {
Chris@425 157 if (column < 2) {
Chris@425 158 return SparseValueModel<TimeValuePoint>::getSetDataCommand
Chris@425 159 (row, column, value, role);
Chris@425 160 }
Chris@425 161
Chris@740 162 if (role != Qt::EditRole) return 0;
Chris@606 163 PointListConstIterator i = getPointListIteratorForRow(row);
Chris@740 164 if (i == m_points.end()) return 0;
Chris@420 165 EditCommand *command = new EditCommand(this, tr("Edit Data"));
Chris@420 166
Chris@420 167 Point point(*i);
Chris@420 168 command->deletePoint(point);
Chris@420 169
Chris@420 170 switch (column) {
Chris@423 171 case 2: point.value = value.toDouble(); break;
Chris@420 172 case 3: point.label = value.toString(); break;
Chris@420 173 }
Chris@420 174
Chris@420 175 command->addPoint(point);
Chris@420 176 return command->finish();
Chris@420 177 }
Chris@420 178
Chris@420 179 virtual bool isColumnTimeValue(int column) const
Chris@420 180 {
Chris@420 181 return (column < 2);
Chris@420 182 }
Chris@422 183
Chris@422 184 virtual SortType getSortType(int column) const
Chris@422 185 {
Chris@422 186 if (column == 3) return SortAlphabetical;
Chris@422 187 return SortNumeric;
Chris@422 188 }
Chris@147 189 };
Chris@147 190
Chris@147 191
Chris@147 192 #endif
Chris@147 193
Chris@147 194
Chris@147 195