annotate data/model/NoteModel.h @ 458:f60360209e5c

* Fix race condition in FFTFileCache when reading from the same FFT model from multiple threads (e.g. when applying more than one plugin at once)
author Chris Cannam
date Wed, 15 Oct 2008 12:08:02 +0000
parents 325112751f0e
children 1415e35881f6
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@340 59 .arg(indent).arg(frame).arg(value).arg(duration).arg(level).arg(label).arg(extraAttributes);
Chris@147 60 }
Chris@147 61
Chris@147 62 QString toDelimitedDataString(QString delimiter, size_t sampleRate) const
Chris@147 63 {
Chris@147 64 QStringList list;
Chris@147 65 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
Chris@147 66 list << QString("%1").arg(value);
Chris@340 67 list << RealTime::frame2RealTime(duration, sampleRate).toString().c_str();
Chris@340 68 list << QString("%1").arg(level);
Chris@318 69 if (label != "") list << label;
Chris@147 70 return list.join(delimiter);
Chris@147 71 }
Chris@147 72
Chris@147 73 struct Comparator {
Chris@147 74 bool operator()(const Note &p1,
Chris@147 75 const Note &p2) const {
Chris@147 76 if (p1.frame != p2.frame) return p1.frame < p2.frame;
Chris@147 77 if (p1.value != p2.value) return p1.value < p2.value;
Chris@147 78 if (p1.duration != p2.duration) return p1.duration < p2.duration;
Chris@340 79 if (p1.level != p2.level) return p1.level < p2.level;
Chris@147 80 return p1.label < p2.label;
Chris@147 81 }
Chris@147 82 };
Chris@147 83
Chris@147 84 struct OrderComparator {
Chris@147 85 bool operator()(const Note &p1,
Chris@147 86 const Note &p2) const {
Chris@147 87 return p1.frame < p2.frame;
Chris@147 88 }
Chris@147 89 };
Chris@147 90 };
Chris@147 91
Chris@147 92
Chris@437 93 class NoteModel : public IntervalModel<Note>
Chris@147 94 {
Chris@423 95 Q_OBJECT
Chris@423 96
Chris@147 97 public:
Chris@147 98 NoteModel(size_t sampleRate, size_t resolution,
Chris@256 99 bool notifyOnAdd = true) :
Chris@437 100 IntervalModel<Note>(sampleRate, resolution, notifyOnAdd),
Chris@256 101 m_valueQuantization(0)
Chris@256 102 {
Chris@391 103 PlayParameterRepository::getInstance()->addPlayable(this);
Chris@256 104 }
Chris@256 105
Chris@256 106 NoteModel(size_t sampleRate, size_t resolution,
Chris@147 107 float valueMinimum, float valueMaximum,
Chris@147 108 bool notifyOnAdd = true) :
Chris@437 109 IntervalModel<Note>(sampleRate, resolution,
Chris@437 110 valueMinimum, valueMaximum,
Chris@437 111 notifyOnAdd),
Chris@147 112 m_valueQuantization(0)
Chris@147 113 {
Chris@391 114 PlayParameterRepository::getInstance()->addPlayable(this);
Chris@391 115 }
Chris@391 116
Chris@391 117 virtual ~NoteModel()
Chris@391 118 {
Chris@391 119 PlayParameterRepository::getInstance()->removePlayable(this);
Chris@147 120 }
Chris@147 121
Chris@147 122 float getValueQuantization() const { return m_valueQuantization; }
Chris@147 123 void setValueQuantization(float q) { m_valueQuantization = q; }
Chris@147 124
Chris@345 125 QString getTypeName() const { return tr("Note"); }
Chris@345 126
Chris@391 127 virtual bool canPlay() const { return true; }
Chris@391 128
Chris@391 129 virtual QString getDefaultPlayPluginId() const
Chris@391 130 {
Chris@391 131 return "dssi:_builtin:sample_player";
Chris@391 132 }
Chris@391 133
Chris@391 134 virtual QString getDefaultPlayPluginConfiguration() const
Chris@391 135 {
Chris@391 136 return "<plugin program=\"piano\"/>";
Chris@391 137 }
Chris@391 138
Chris@288 139 virtual void toXml(QTextStream &out,
Chris@288 140 QString indent = "",
Chris@288 141 QString extraAttributes = "") const
Chris@147 142 {
Chris@318 143 std::cerr << "NoteModel::toXml: extraAttributes = \""
Chris@318 144 << extraAttributes.toStdString() << std::endl;
Chris@318 145
Chris@437 146 IntervalModel<Note>::toXml
Chris@288 147 (out,
Chris@288 148 indent,
Chris@452 149 QString("%1 subtype=\"note\" valueQuantization=\"%2\"")
Chris@147 150 .arg(extraAttributes).arg(m_valueQuantization));
Chris@147 151 }
Chris@147 152
Chris@424 153 /**
Chris@424 154 * TabularModel methods.
Chris@424 155 */
Chris@424 156
Chris@424 157 virtual int getColumnCount() const
Chris@424 158 {
Chris@424 159 return 6;
Chris@424 160 }
Chris@424 161
Chris@424 162 virtual QString getHeading(int column) const
Chris@424 163 {
Chris@424 164 switch (column) {
Chris@424 165 case 0: return tr("Time");
Chris@424 166 case 1: return tr("Frame");
Chris@424 167 case 2: return tr("Pitch");
Chris@424 168 case 3: return tr("Duration");
Chris@424 169 case 4: return tr("Level");
Chris@424 170 case 5: return tr("Label");
Chris@424 171 default: return tr("Unknown");
Chris@424 172 }
Chris@424 173 }
Chris@424 174
Chris@424 175 virtual QVariant getData(int row, int column, int role) const
Chris@424 176 {
Chris@437 177 if (column < 4) {
Chris@437 178 return IntervalModel<Note>::getData(row, column, role);
Chris@425 179 }
Chris@425 180
Chris@424 181 PointListIterator i = getPointListIteratorForRow(row);
Chris@424 182 if (i == m_points.end()) return QVariant();
Chris@424 183
Chris@424 184 switch (column) {
Chris@424 185 case 4: return i->level;
Chris@424 186 case 5: return i->label;
Chris@424 187 default: return QVariant();
Chris@424 188 }
Chris@424 189 }
Chris@424 190
Chris@424 191 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
Chris@424 192 {
Chris@437 193 if (column < 4) {
Chris@437 194 return IntervalModel<Note>::getSetDataCommand
Chris@425 195 (row, column, value, role);
Chris@425 196 }
Chris@425 197
Chris@424 198 if (role != Qt::EditRole) return false;
Chris@424 199 PointListIterator i = getPointListIteratorForRow(row);
Chris@424 200 if (i == m_points.end()) return false;
Chris@424 201 EditCommand *command = new EditCommand(this, tr("Edit Data"));
Chris@424 202
Chris@424 203 Point point(*i);
Chris@424 204 command->deletePoint(point);
Chris@424 205
Chris@424 206 switch (column) {
Chris@424 207 case 4: point.level = value.toDouble(); break;
Chris@424 208 case 5: point.label = value.toString(); break;
Chris@424 209 }
Chris@424 210
Chris@424 211 command->addPoint(point);
Chris@424 212 return command->finish();
Chris@424 213 }
Chris@424 214
Chris@424 215 virtual SortType getSortType(int column) const
Chris@424 216 {
Chris@424 217 if (column == 5) return SortAlphabetical;
Chris@424 218 return SortNumeric;
Chris@424 219 }
Chris@424 220
Chris@147 221 protected:
Chris@147 222 float m_valueQuantization;
Chris@147 223 };
Chris@147 224
Chris@147 225 #endif