comparison data/model/FlexiNoteModel.h @ 874:862fe7b20df7 tony_integration

Merge from tonioni branch
author Chris Cannam
date Tue, 28 Jan 2014 15:01:54 +0000
parents 4dce43294740
children ecb34638ce1b
comparison
equal deleted inserted replaced
862:786ee8d1f30e 874:862fe7b20df7
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Chris Cannam.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #ifndef _FLEXINOTE_MODEL_H_
17 #define _FLEXINOTE_MODEL_H_
18
19 #include "IntervalModel.h"
20 #include "NoteData.h"
21 #include "base/RealTime.h"
22 #include "base/Pitch.h"
23 #include "base/PlayParameterRepository.h"
24
25 /**
26 * FlexiNoteModel -- a concrete IntervalModel for notes.
27 */
28
29 /**
30 * Extension of the NoteModel for more flexible note interaction.
31 * The original NoteModel rationale is given below, will need to be
32 * updated for FlexiNoteModel:
33 *
34 * Note type for use in a sparse model. All we mean by a "note" is
35 * something that has an onset time, a single value, a duration, and a
36 * level. Like other points, it can also have a label. With this
37 * point type, the model can be thought of as representing a simple
38 * MIDI-type piano roll, except that the y coordinates (values) do not
39 * have to be discrete integers.
40 */
41
42 struct FlexiNote
43 {
44 public:
45 FlexiNote(long _frame) : frame(_frame), value(0.0f), duration(0), level(1.f) { }
46 FlexiNote(long _frame, float _value, size_t _duration, float _level, QString _label) :
47 frame(_frame), value(_value), duration(_duration), level(_level), label(_label) { }
48
49 int getDimensions() const { return 3; }
50
51 long frame;
52 float value;
53 size_t duration;
54 float level;
55 QString label;
56
57 QString getLabel() const { return label; }
58
59 void toXml(QTextStream &stream,
60 QString indent = "",
61 QString extraAttributes = "") const
62 {
63 stream <<
64 QString("%1<point frame=\"%2\" value=\"%3\" duration=\"%4\" level=\"%5\" label=\"%6\" %7/>\n")
65 .arg(indent).arg(frame).arg(value).arg(duration).arg(level)
66 .arg(XmlExportable::encodeEntities(label)).arg(extraAttributes);
67 }
68
69 QString toDelimitedDataString(QString delimiter, size_t sampleRate) const
70 {
71 QStringList list;
72 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
73 list << QString("%1").arg(value);
74 list << RealTime::frame2RealTime(duration, sampleRate).toString().c_str();
75 list << QString("%1").arg(level);
76 if (label != "") list << label;
77 return list.join(delimiter);
78 }
79
80 struct Comparator {
81 bool operator()(const FlexiNote &p1,
82 const FlexiNote &p2) const {
83 if (p1.frame != p2.frame) return p1.frame < p2.frame;
84 if (p1.value != p2.value) return p1.value < p2.value;
85 if (p1.duration != p2.duration) return p1.duration < p2.duration;
86 if (p1.level != p2.level) return p1.level < p2.level;
87 return p1.label < p2.label;
88 }
89 };
90
91 struct OrderComparator {
92 bool operator()(const FlexiNote &p1,
93 const FlexiNote &p2) const {
94 return p1.frame < p2.frame;
95 }
96 };
97 };
98
99
100 class FlexiNoteModel : public IntervalModel<FlexiNote>, public NoteExportable
101 {
102 Q_OBJECT
103
104 public:
105 FlexiNoteModel(size_t sampleRate, size_t resolution,
106 bool notifyOnAdd = true) :
107 IntervalModel<FlexiNote>(sampleRate, resolution, notifyOnAdd),
108 m_valueQuantization(0)
109 {
110 PlayParameterRepository::getInstance()->addPlayable(this);
111 }
112
113 FlexiNoteModel(size_t sampleRate, size_t resolution,
114 float valueMinimum, float valueMaximum,
115 bool notifyOnAdd = true) :
116 IntervalModel<FlexiNote>(sampleRate, resolution,
117 valueMinimum, valueMaximum,
118 notifyOnAdd),
119 m_valueQuantization(0)
120 {
121 PlayParameterRepository::getInstance()->addPlayable(this);
122 }
123
124 virtual ~FlexiNoteModel()
125 {
126 PlayParameterRepository::getInstance()->removePlayable(this);
127 }
128
129 float getValueQuantization() const { return m_valueQuantization; }
130 void setValueQuantization(float q) { m_valueQuantization = q; }
131 float getValueMinimum() const { return 33; }
132 float getValueMaximum() const { return 88; }
133
134 QString getTypeName() const { return tr("FlexiNote"); }
135
136 virtual bool canPlay() const { return true; }
137
138 virtual QString getDefaultPlayClipId() const
139 {
140 return "elecpiano";
141 }
142
143 virtual void toXml(QTextStream &out,
144 QString indent = "",
145 QString extraAttributes = "") const
146 {
147 std::cerr << "FlexiNoteModel::toXml: extraAttributes = \""
148 << extraAttributes.toStdString() << std::endl;
149
150 IntervalModel<FlexiNote>::toXml
151 (out,
152 indent,
153 QString("%1 subtype=\"note\" valueQuantization=\"%2\"")
154 .arg(extraAttributes).arg(m_valueQuantization));
155 }
156
157 /**
158 * TabularModel methods.
159 */
160
161 virtual int getColumnCount() const
162 {
163 return 6;
164 }
165
166 virtual QString getHeading(int column) const
167 {
168 switch (column) {
169 case 0: return tr("Time");
170 case 1: return tr("Frame");
171 case 2: return tr("Pitch");
172 case 3: return tr("Duration");
173 case 4: return tr("Level");
174 case 5: return tr("Label");
175 default: return tr("Unknown");
176 }
177 }
178
179 virtual QVariant getData(int row, int column, int role) const
180 {
181 if (column < 4) {
182 return IntervalModel<FlexiNote>::getData(row, column, role);
183 }
184
185 PointListConstIterator i = getPointListIteratorForRow(row);
186 if (i == m_points.end()) return QVariant();
187
188 switch (column) {
189 case 4: return i->level;
190 case 5: return i->label;
191 default: return QVariant();
192 }
193 }
194
195 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
196 {
197 if (column < 4) {
198 return IntervalModel<FlexiNote>::getSetDataCommand
199 (row, column, value, role);
200 }
201
202 if (role != Qt::EditRole) return 0;
203 PointListConstIterator i = getPointListIteratorForRow(row);
204 if (i == m_points.end()) return 0;
205 EditCommand *command = new EditCommand(this, tr("Edit Data"));
206
207 Point point(*i);
208 command->deletePoint(point);
209
210 switch (column) {
211 case 4: point.level = value.toDouble(); break;
212 case 5: point.label = value.toString(); break;
213 }
214
215 command->addPoint(point);
216 return command->finish();
217 }
218
219 virtual SortType getSortType(int column) const
220 {
221 if (column == 5) return SortAlphabetical;
222 return SortNumeric;
223 }
224
225 /**
226 * NoteExportable methods.
227 */
228
229 NoteList getNotes() const {
230 return getNotes(getStartFrame(), getEndFrame());
231 }
232
233 NoteList getNotes(size_t startFrame, size_t endFrame) const {
234
235 PointList points = getPoints(startFrame, endFrame);
236 NoteList notes;
237
238 for (PointList::iterator pli =
239 points.begin(); pli != points.end(); ++pli) {
240
241 size_t duration = pli->duration;
242 if (duration == 0 || duration == 1) {
243 duration = getSampleRate() / 20;
244 }
245
246 int pitch = lrintf(pli->value);
247
248 int velocity = 100;
249 if (pli->level > 0.f && pli->level <= 1.f) {
250 velocity = lrintf(pli->level * 127);
251 }
252
253 NoteData note(pli->frame, duration, pitch, velocity);
254
255 if (getScaleUnits() == "Hz") {
256 note.frequency = pli->value;
257 note.midiPitch = Pitch::getPitchForFrequency(note.frequency);
258 note.isMidiPitchQuantized = false;
259 }
260
261 notes.push_back(note);
262 }
263
264 return notes;
265 }
266
267 protected:
268 float m_valueQuantization;
269 };
270
271 #endif