svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #ifndef _FLEXINOTE_MODEL_H_ 00017 #define _FLEXINOTE_MODEL_H_ 00018 00019 #include "IntervalModel.h" 00020 #include "NoteData.h" 00021 #include "base/RealTime.h" 00022 #include "base/Pitch.h" 00023 #include "base/PlayParameterRepository.h" 00024 00042 struct FlexiNote 00043 { 00044 public: 00045 FlexiNote(long _frame) : frame(_frame), value(0.0f), duration(0), level(1.f) { } 00046 FlexiNote(long _frame, float _value, int _duration, float _level, QString _label) : 00047 frame(_frame), value(_value), duration(_duration), level(_level), label(_label) { } 00048 00049 int getDimensions() const { return 3; } 00050 00051 long frame; 00052 float value; 00053 int duration; 00054 float level; 00055 QString label; 00056 00057 QString getLabel() const { return label; } 00058 00059 void toXml(QTextStream &stream, 00060 QString indent = "", 00061 QString extraAttributes = "") const 00062 { 00063 stream << 00064 QString("%1<point frame=\"%2\" value=\"%3\" duration=\"%4\" level=\"%5\" label=\"%6\" %7/>\n") 00065 .arg(indent).arg(frame).arg(value).arg(duration).arg(level) 00066 .arg(XmlExportable::encodeEntities(label)).arg(extraAttributes); 00067 } 00068 00069 QString toDelimitedDataString(QString delimiter, int sampleRate) const 00070 { 00071 QStringList list; 00072 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str(); 00073 list << QString("%1").arg(value); 00074 list << RealTime::frame2RealTime(duration, sampleRate).toString().c_str(); 00075 list << QString("%1").arg(level); 00076 if (label != "") list << label; 00077 return list.join(delimiter); 00078 } 00079 00080 struct Comparator { 00081 bool operator()(const FlexiNote &p1, 00082 const FlexiNote &p2) const { 00083 if (p1.frame != p2.frame) return p1.frame < p2.frame; 00084 if (p1.value != p2.value) return p1.value < p2.value; 00085 if (p1.duration != p2.duration) return p1.duration < p2.duration; 00086 if (p1.level != p2.level) return p1.level < p2.level; 00087 return p1.label < p2.label; 00088 } 00089 }; 00090 00091 struct OrderComparator { 00092 bool operator()(const FlexiNote &p1, 00093 const FlexiNote &p2) const { 00094 return p1.frame < p2.frame; 00095 } 00096 }; 00097 }; 00098 00099 00100 class FlexiNoteModel : public IntervalModel<FlexiNote>, public NoteExportable 00101 { 00102 Q_OBJECT 00103 00104 public: 00105 FlexiNoteModel(int sampleRate, int resolution, 00106 bool notifyOnAdd = true) : 00107 IntervalModel<FlexiNote>(sampleRate, resolution, notifyOnAdd), 00108 m_valueQuantization(0) 00109 { 00110 PlayParameterRepository::getInstance()->addPlayable(this); 00111 } 00112 00113 FlexiNoteModel(int sampleRate, int resolution, 00114 float valueMinimum, float valueMaximum, 00115 bool notifyOnAdd = true) : 00116 IntervalModel<FlexiNote>(sampleRate, resolution, 00117 valueMinimum, valueMaximum, 00118 notifyOnAdd), 00119 m_valueQuantization(0) 00120 { 00121 PlayParameterRepository::getInstance()->addPlayable(this); 00122 } 00123 00124 virtual ~FlexiNoteModel() 00125 { 00126 PlayParameterRepository::getInstance()->removePlayable(this); 00127 } 00128 00129 float getValueQuantization() const { return m_valueQuantization; } 00130 void setValueQuantization(float q) { m_valueQuantization = q; } 00131 float getValueMinimum() const { return 33; } 00132 float getValueMaximum() const { return 88; } 00133 00134 QString getTypeName() const { return tr("FlexiNote"); } 00135 00136 virtual bool canPlay() const { return true; } 00137 00138 virtual QString getDefaultPlayClipId() const 00139 { 00140 return "elecpiano"; 00141 } 00142 00143 virtual void toXml(QTextStream &out, 00144 QString indent = "", 00145 QString extraAttributes = "") const 00146 { 00147 std::cerr << "FlexiNoteModel::toXml: extraAttributes = \"" 00148 << extraAttributes.toStdString() << std::endl; 00149 00150 IntervalModel<FlexiNote>::toXml 00151 (out, 00152 indent, 00153 QString("%1 subtype=\"flexinote\" valueQuantization=\"%2\"") 00154 .arg(extraAttributes).arg(m_valueQuantization)); 00155 } 00156 00161 virtual int getColumnCount() const 00162 { 00163 return 6; 00164 } 00165 00166 virtual QString getHeading(int column) const 00167 { 00168 switch (column) { 00169 case 0: return tr("Time"); 00170 case 1: return tr("Frame"); 00171 case 2: return tr("Pitch"); 00172 case 3: return tr("Duration"); 00173 case 4: return tr("Level"); 00174 case 5: return tr("Label"); 00175 default: return tr("Unknown"); 00176 } 00177 } 00178 00179 virtual QVariant getData(int row, int column, int role) const 00180 { 00181 if (column < 4) { 00182 return IntervalModel<FlexiNote>::getData(row, column, role); 00183 } 00184 00185 PointListConstIterator i = getPointListIteratorForRow(row); 00186 if (i == m_points.end()) return QVariant(); 00187 00188 switch (column) { 00189 case 4: return i->level; 00190 case 5: return i->label; 00191 default: return QVariant(); 00192 } 00193 } 00194 00195 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role) 00196 { 00197 if (column < 4) { 00198 return IntervalModel<FlexiNote>::getSetDataCommand 00199 (row, column, value, role); 00200 } 00201 00202 if (role != Qt::EditRole) return 0; 00203 PointListConstIterator i = getPointListIteratorForRow(row); 00204 if (i == m_points.end()) return 0; 00205 EditCommand *command = new EditCommand(this, tr("Edit Data")); 00206 00207 Point point(*i); 00208 command->deletePoint(point); 00209 00210 switch (column) { 00211 case 4: point.level = value.toDouble(); break; 00212 case 5: point.label = value.toString(); break; 00213 } 00214 00215 command->addPoint(point); 00216 return command->finish(); 00217 } 00218 00219 virtual SortType getSortType(int column) const 00220 { 00221 if (column == 5) return SortAlphabetical; 00222 return SortNumeric; 00223 } 00224 00229 NoteList getNotes() const 00230 { 00231 return getNotesWithin(getStartFrame(), getEndFrame()); 00232 } 00233 00234 NoteList getNotesWithin(int startFrame, int endFrame) const 00235 { 00236 PointList points = getPoints(startFrame, endFrame); 00237 NoteList notes; 00238 for (PointList::iterator pli = points.begin(); pli != points.end(); ++pli) { 00239 int duration = pli->duration; 00240 if (duration == 0 || duration == 1) { 00241 duration = getSampleRate() / 20; 00242 } 00243 int pitch = lrintf(pli->value); 00244 00245 int velocity = 100; 00246 if (pli->level > 0.f && pli->level <= 1.f) { 00247 velocity = lrintf(pli->level * 127); 00248 } 00249 00250 NoteData note(pli->frame, duration, pitch, velocity); 00251 00252 if (getScaleUnits() == "Hz") { 00253 note.frequency = pli->value; 00254 note.midiPitch = Pitch::getPitchForFrequency(note.frequency); 00255 note.isMidiPitchQuantized = false; 00256 } 00257 notes.push_back(note); 00258 } 00259 return notes; 00260 } 00261 00262 protected: 00263 float m_valueQuantization; 00264 }; 00265 00266 #endif