00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef _LABELLER_H_
00017 #define _LABELLER_H_
00018
00019 #include "SparseModel.h"
00020 #include "SparseValueModel.h"
00021
00022 #include "base/Selection.h"
00023
00024 #include <QObject>
00025
00026 #include <map>
00027 #include <iostream>
00028
00029 class Labeller : public QObject
00030 {
00031 public:
00032 enum ValueType {
00033 ValueNone,
00034 ValueFromSimpleCounter,
00035 ValueFromCyclicalCounter,
00036 ValueFromTwoLevelCounter,
00037 ValueFromFrameNumber,
00038 ValueFromRealTime,
00039 ValueFromDurationFromPrevious,
00040 ValueFromDurationToNext,
00041 ValueFromTempoFromPrevious,
00042 ValueFromTempoToNext,
00043 ValueFromExistingNeighbour,
00044 ValueFromLabel
00045 };
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 Labeller(ValueType type = ValueNone) :
00065 m_type(type),
00066 m_counter(1),
00067 m_counter2(1),
00068 m_cycle(4),
00069 m_dp(10),
00070 m_rate(0) { }
00071
00072 Labeller(const Labeller &l) :
00073 QObject(),
00074 m_type(l.m_type),
00075 m_counter(l.m_counter),
00076 m_counter2(l.m_counter2),
00077 m_cycle(l.m_cycle),
00078 m_dp(l.m_dp),
00079 m_rate(l.m_rate) { }
00080
00081 virtual ~Labeller() { }
00082
00083 typedef std::map<ValueType, QString> TypeNameMap;
00084 TypeNameMap getTypeNames() const {
00085 TypeNameMap m;
00086 m[ValueNone]
00087 = tr("No numbering");
00088 m[ValueFromSimpleCounter]
00089 = tr("Simple counter");
00090 m[ValueFromCyclicalCounter]
00091 = tr("Cyclical counter");
00092 m[ValueFromTwoLevelCounter]
00093 = tr("Cyclical two-level counter (bar/beat)");
00094 m[ValueFromFrameNumber]
00095 = tr("Audio sample frame number");
00096 m[ValueFromRealTime]
00097 = tr("Time in seconds");
00098 m[ValueFromDurationToNext]
00099 = tr("Duration to the following item");
00100 m[ValueFromTempoToNext]
00101 = tr("Tempo (bpm) based on duration to following item");
00102 m[ValueFromDurationFromPrevious]
00103 = tr("Duration since the previous item");
00104 m[ValueFromTempoFromPrevious]
00105 = tr("Tempo (bpm) based on duration since previous item");
00106 m[ValueFromExistingNeighbour]
00107 = tr("Same as the nearest previous item");
00108 m[ValueFromLabel]
00109 = tr("Value extracted from the item's label (where possible)");
00110 return m;
00111 }
00112
00113 ValueType getType() const { return m_type; }
00114 void setType(ValueType type) { m_type = type; }
00115
00116 int getCounterValue() const { return m_counter; }
00117 void setCounterValue(int v) { m_counter = v; }
00118
00119 int getSecondLevelCounterValue() const { return m_counter2; }
00120 void setSecondLevelCounterValue(int v) { m_counter2 = v; }
00121
00122 int getCounterCycleSize() const { return m_cycle; }
00123 void setCounterCycleSize(int s) {
00124 m_cycle = s;
00125 m_dp = 1;
00126 while (s > 0) {
00127 s /= 10;
00128 m_dp *= 10;
00129 }
00130 if (m_counter > m_cycle) m_counter = 1;
00131 }
00132
00133 void setSampleRate(float rate) { m_rate = rate; }
00134
00135 void incrementCounter() {
00136 m_counter++;
00137 if (m_type == ValueFromCyclicalCounter ||
00138 m_type == ValueFromTwoLevelCounter) {
00139 if (m_counter > m_cycle) {
00140 m_counter = 1;
00141 m_counter2++;
00142 }
00143 }
00144 }
00145
00146 template <typename PointType>
00147 void label(PointType &newPoint, PointType *prevPoint = 0) {
00148 if (m_type == ValueNone) {
00149 newPoint.label = "";
00150 } else if (m_type == ValueFromTwoLevelCounter) {
00151 newPoint.label = tr("%1.%2").arg(m_counter2).arg(m_counter);
00152 incrementCounter();
00153 } else if (m_type == ValueFromFrameNumber) {
00154
00155 newPoint.label = tr("%1").arg(newPoint.frame);
00156 } else {
00157 float value = getValueFor<PointType>(newPoint, prevPoint);
00158 if (actingOnPrevPoint() && prevPoint) {
00159 prevPoint->label = QString("%1").arg(value);
00160 } else {
00161 newPoint.label = QString("%1").arg(value);
00162 }
00163 }
00164 }
00165
00166 template <typename PointType>
00167 void labelAll(SparseModel<PointType> &model, MultiSelection *ms) {
00168
00169 typename SparseModel<PointType>::PointList::iterator i;
00170 typename SparseModel<PointType>::PointList pl(model.getPoints());
00171
00172 typename SparseModel<PointType>::EditCommand *command =
00173 new typename SparseModel<PointType>::EditCommand
00174 (&model, tr("Label Points"));
00175
00176 PointType prevPoint(0);
00177
00178 for (i = pl.begin(); i != pl.end(); ++i) {
00179
00180 bool inRange = true;
00181 if (ms) {
00182 Selection s(ms->getContainingSelection(i->frame, false));
00183 if (s.isEmpty() || !s.contains(i->frame)) {
00184 inRange = false;
00185 }
00186 }
00187
00188 PointType p(*i);
00189
00190 if (!inRange) {
00191 prevPoint = p;
00192 continue;
00193 }
00194
00195 if (actingOnPrevPoint()) {
00196 if (i != pl.begin()) {
00197 command->deletePoint(prevPoint);
00198 label<PointType>(p, &prevPoint);
00199 command->addPoint(prevPoint);
00200 }
00201 } else {
00202 command->deletePoint(p);
00203 label<PointType>(p, &prevPoint);
00204 command->addPoint(p);
00205 }
00206
00207 prevPoint = p;
00208 }
00209
00210 command->finish();
00211 }
00212
00213 template <typename PointType>
00214 void setValue(PointType &newPoint, PointType *prevPoint = 0) {
00215 if (m_type == ValueFromExistingNeighbour) {
00216 if (!prevPoint) {
00217 std::cerr << "ERROR: Labeller::setValue: Previous point required but not provided" << std::endl;
00218 } else {
00219 newPoint.value = prevPoint->value;
00220 }
00221 } else {
00222 float value = getValueFor<PointType>(newPoint, prevPoint);
00223 if (actingOnPrevPoint() && prevPoint) {
00224 prevPoint->value = value;
00225 } else {
00226 newPoint.value = value;
00227 }
00228 }
00229 }
00230
00231 bool requiresPrevPoint() const {
00232 return (m_type == ValueFromDurationFromPrevious ||
00233 m_type == ValueFromDurationToNext ||
00234 m_type == ValueFromTempoFromPrevious ||
00235 m_type == ValueFromDurationToNext);
00236 }
00237
00238 bool actingOnPrevPoint() const {
00239 return (m_type == ValueFromDurationToNext ||
00240 m_type == ValueFromTempoToNext);
00241 }
00242
00243 protected:
00244 template <typename PointType>
00245 float getValueFor(PointType &newPoint, PointType *prevPoint)
00246 {
00247 float value = 0.f;
00248
00249 switch (m_type) {
00250
00251 case ValueNone:
00252 value = 0;
00253 break;
00254
00255 case ValueFromSimpleCounter:
00256 case ValueFromCyclicalCounter:
00257 value = m_counter;
00258 incrementCounter();
00259 break;
00260
00261 case ValueFromTwoLevelCounter:
00262 value = m_counter2 + double(m_counter) / double(m_dp);
00263 incrementCounter();
00264 break;
00265
00266 case ValueFromFrameNumber:
00267 value = newPoint.frame;
00268 break;
00269
00270 case ValueFromRealTime:
00271 if (m_rate == 0.f) {
00272 std::cerr << "ERROR: Labeller::getValueFor: Real-time conversion required, but no sample rate set" << std::endl;
00273 } else {
00274 value = float(newPoint.frame) / float(m_rate);
00275 }
00276 break;
00277
00278 case ValueFromDurationToNext:
00279 case ValueFromTempoToNext:
00280 case ValueFromDurationFromPrevious:
00281 case ValueFromTempoFromPrevious:
00282 if (m_rate == 0.f) {
00283 std::cerr << "ERROR: Labeller::getValueFor: Real-time conversion required, but no sample rate set" << std::endl;
00284 } else if (!prevPoint) {
00285 std::cerr << "ERROR: Labeller::getValueFor: Time difference required, but only one point provided" << std::endl;
00286 } else {
00287 size_t f0 = prevPoint->frame, f1 = newPoint.frame;
00288 if (m_type == ValueFromDurationToNext ||
00289 m_type == ValueFromDurationFromPrevious) {
00290 value = float(f1 - f0) / m_rate;
00291 } else {
00292 if (f1 > f0) {
00293 value = (60.f * m_rate) / (f1 - f0);
00294 }
00295 }
00296 }
00297 break;
00298
00299 case ValueFromExistingNeighbour:
00300
00301
00302
00303 break;
00304
00305 case ValueFromLabel:
00306 if (newPoint.label != "") {
00307
00308 value = atof(newPoint.label.toLocal8Bit());
00309 } else {
00310 value = 0.f;
00311 }
00312 break;
00313 }
00314
00315 return value;
00316 }
00317
00318 ValueType m_type;
00319 int m_counter;
00320 int m_counter2;
00321 int m_cycle;
00322 int m_dp;
00323 float m_rate;
00324 };
00325
00326 #endif