annotate data/model/NoteModel.h @ 631:3a5ee4b6c9ad

* Complete the overhaul of CSV file import; now you can pick the purpose for each column in the file, and SV should do the rest. The most significant practical improvement here is that we can now handle files in which time and duration do not necessarily appear in known columns.
author Chris Cannam
date Mon, 19 Jul 2010 17:08:56 +0000
parents 080d8bdd8762
children e22b6e89a7f7
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 _NOTE_MODEL_H_
Chris@147 17 #define _NOTE_MODEL_H_
Chris@147 18
Chris@437 19 #include "IntervalModel.h"
Chris@391 20 #include "base/RealTime.h"
Chris@150 21 #include "base/PlayParameterRepository.h"
Chris@147 22
Chris@147 23 /**
Chris@441 24 * NoteModel -- a concrete IntervalModel for notes.
Chris@441 25 */
Chris@441 26
Chris@441 27 /**
Chris@441 28 * Note type for use in a sparse model. All we mean by a "note" is
Chris@441 29 * something that has an onset time, a single value, a duration, and a
Chris@441 30 * level. Like other points, it can also have a label. With this
Chris@441 31 * point type, the model can be thought of as representing a simple
Chris@441 32 * MIDI-type piano roll, except that the y coordinates (values) do not
Chris@441 33 * have to be discrete integers.
Chris@147 34 */
Chris@147 35
Chris@147 36 struct Note
Chris@147 37 {
Chris@147 38 public:
Chris@340 39 Note(long _frame) : frame(_frame), value(0.0f), duration(0), level(1.f) { }
Chris@340 40 Note(long _frame, float _value, size_t _duration, float _level, QString _label) :
Chris@340 41 frame(_frame), value(_value), duration(_duration), level(_level), label(_label) { }
Chris@147 42
Chris@147 43 int getDimensions() const { return 3; }
Chris@147 44
Chris@147 45 long frame;
Chris@147 46 float value;
Chris@147 47 size_t duration;
Chris@340 48 float level;
Chris@147 49 QString label;
Chris@147 50
Chris@338 51 QString getLabel() const { return label; }
Chris@338 52
Chris@314 53 void toXml(QTextStream &stream,
Chris@314 54 QString indent = "",
Chris@314 55 QString extraAttributes = "") const
Chris@147 56 {
Chris@314 57 stream <<
Chris@340 58 QString("%1<point frame=\"%2\" value=\"%3\" duration=\"%4\" level=\"%5\" label=\"%6\" %7/>\n")
Chris@627 59 .arg(indent).arg(frame).arg(value).arg(duration).arg(level)
Chris@627 60 .arg(XmlExportable::encodeEntities(label)).arg(extraAttributes);
Chris@147 61 }
Chris@147 62
Chris@147 63 QString toDelimitedDataString(QString delimiter, size_t sampleRate) const
Chris@147 64 {
Chris@147 65 QStringList list;
Chris@147 66 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
Chris@147 67 list << QString("%1").arg(value);
Chris@340 68 list << RealTime::frame2RealTime(duration, sampleRate).toString().c_str();
Chris@340 69 list << QString("%1").arg(level);
Chris@318 70 if (label != "") list << label;
Chris@147 71 return list.join(delimiter);
Chris@147 72 }
Chris@147 73
Chris@147 74 struct Comparator {
Chris@147 75 bool operator()(const Note &p1,
Chris@147 76 const Note &p2) const {
Chris@147 77 if (p1.frame != p2.frame) return p1.frame < p2.frame;
Chris@147 78 if (p1.value != p2.value) return p1.value < p2.value;
Chris@147 79 if (p1.duration != p2.duration) return p1.duration < p2.duration;
Chris@340 80 if (p1.level != p2.level) return p1.level < p2.level;
Chris@147 81 return p1.label < p2.label;
Chris@147 82 }
Chris@147 83 };
Chris@147 84
Chris@147 85 struct OrderComparator {
Chris@147 86 bool operator()(const Note &p1,
Chris@147 87 const Note &p2) const {
Chris@147 88 return p1.frame < p2.frame;
Chris@147 89 }
Chris@147 90 };
Chris@147 91 };
Chris@147 92
Chris@147 93
Chris@437 94 class NoteModel : public IntervalModel<Note>
Chris@147 95 {
Chris@423 96 Q_OBJECT
Chris@423 97
Chris@147 98 public:
Chris@147 99 NoteModel(size_t sampleRate, size_t resolution,
Chris@256 100 bool notifyOnAdd = true) :
Chris@437 101 IntervalModel<Note>(sampleRate, resolution, notifyOnAdd),
Chris@256 102 m_valueQuantization(0)
Chris@256 103 {
Chris@391 104 PlayParameterRepository::getInstance()->addPlayable(this);
Chris@256 105 }
Chris@256 106
Chris@256 107 NoteModel(size_t sampleRate, size_t resolution,
Chris@147 108 float valueMinimum, float valueMaximum,
Chris@147 109 bool notifyOnAdd = true) :
Chris@437 110 IntervalModel<Note>(sampleRate, resolution,
Chris@437 111 valueMinimum, valueMaximum,
Chris@437 112 notifyOnAdd),
Chris@147 113 m_valueQuantization(0)
Chris@147 114 {
Chris@391 115 PlayParameterRepository::getInstance()->addPlayable(this);
Chris@391 116 }
Chris@391 117
Chris@391 118 virtual ~NoteModel()
Chris@391 119 {
Chris@391 120 PlayParameterRepository::getInstance()->removePlayable(this);
Chris@147 121 }
Chris@147 122
Chris@147 123 float getValueQuantization() const { return m_valueQuantization; }
Chris@147 124 void setValueQuantization(float q) { m_valueQuantization = q; }
Chris@147 125
Chris@345 126 QString getTypeName() const { return tr("Note"); }
Chris@345 127
Chris@391 128 virtual bool canPlay() const { return true; }
Chris@391 129
Chris@391 130 virtual QString getDefaultPlayPluginId() const
Chris@391 131 {
Chris@391 132 return "dssi:_builtin:sample_player";
Chris@391 133 }
Chris@391 134
Chris@391 135 virtual QString getDefaultPlayPluginConfiguration() const
Chris@391 136 {
Chris@391 137 return "<plugin program=\"piano\"/>";
Chris@391 138 }
Chris@391 139
Chris@288 140 virtual void toXml(QTextStream &out,
Chris@288 141 QString indent = "",
Chris@288 142 QString extraAttributes = "") const
Chris@147 143 {
Chris@318 144 std::cerr << "NoteModel::toXml: extraAttributes = \""
Chris@318 145 << extraAttributes.toStdString() << std::endl;
Chris@318 146
Chris@437 147 IntervalModel<Note>::toXml
Chris@288 148 (out,
Chris@288 149 indent,
Chris@452 150 QString("%1 subtype=\"note\" valueQuantization=\"%2\"")
Chris@147 151 .arg(extraAttributes).arg(m_valueQuantization));
Chris@147 152 }
Chris@147 153
Chris@424 154 /**
Chris@424 155 * TabularModel methods.
Chris@424 156 */
Chris@424 157
Chris@424 158 virtual int getColumnCount() const
Chris@424 159 {
Chris@424 160 return 6;
Chris@424 161 }
Chris@424 162
Chris@424 163 virtual QString getHeading(int column) const
Chris@424 164 {
Chris@424 165 switch (column) {
Chris@424 166 case 0: return tr("Time");
Chris@424 167 case 1: return tr("Frame");
Chris@424 168 case 2: return tr("Pitch");
Chris@424 169 case 3: return tr("Duration");
Chris@424 170 case 4: return tr("Level");
Chris@424 171 case 5: return tr("Label");
Chris@424 172 default: return tr("Unknown");
Chris@424 173 }
Chris@424 174 }
Chris@424 175
Chris@424 176 virtual QVariant getData(int row, int column, int role) const
Chris@424 177 {
Chris@437 178 if (column < 4) {
Chris@437 179 return IntervalModel<Note>::getData(row, column, role);
Chris@425 180 }
Chris@425 181
Chris@606 182 PointListConstIterator i = getPointListIteratorForRow(row);
Chris@424 183 if (i == m_points.end()) return QVariant();
Chris@424 184
Chris@424 185 switch (column) {
Chris@424 186 case 4: return i->level;
Chris@424 187 case 5: return i->label;
Chris@424 188 default: return QVariant();
Chris@424 189 }
Chris@424 190 }
Chris@424 191
Chris@424 192 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
Chris@424 193 {
Chris@437 194 if (column < 4) {
Chris@437 195 return IntervalModel<Note>::getSetDataCommand
Chris@425 196 (row, column, value, role);
Chris@425 197 }
Chris@425 198
Chris@424 199 if (role != Qt::EditRole) return false;
Chris@606 200 PointListConstIterator i = getPointListIteratorForRow(row);
Chris@424 201 if (i == m_points.end()) return false;
Chris@424 202 EditCommand *command = new EditCommand(this, tr("Edit Data"));
Chris@424 203
Chris@424 204 Point point(*i);
Chris@424 205 command->deletePoint(point);
Chris@424 206
Chris@424 207 switch (column) {
Chris@424 208 case 4: point.level = value.toDouble(); break;
Chris@424 209 case 5: point.label = value.toString(); break;
Chris@424 210 }
Chris@424 211
Chris@424 212 command->addPoint(point);
Chris@424 213 return command->finish();
Chris@424 214 }
Chris@424 215
Chris@424 216 virtual SortType getSortType(int column) const
Chris@424 217 {
Chris@424 218 if (column == 5) return SortAlphabetical;
Chris@424 219 return SortNumeric;
Chris@424 220 }
Chris@424 221
Chris@147 222 protected:
Chris@147 223 float m_valueQuantization;
Chris@147 224 };
Chris@147 225
Chris@147 226 #endif