svcore  1.9
Labeller.h
Go to the documentation of this file.
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-2007 Chris Cannam and QMUL.
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 _LABELLER_H_
17 #define _LABELLER_H_
18 
19 #include "SparseModel.h"
20 #include "SparseValueModel.h"
21 
22 #include "base/Selection.h"
23 
24 #include <QObject>
25 
26 #include <map>
27 #include <iostream>
28 
29 class Labeller : public QObject
30 {
31  Q_OBJECT
32 
33 public:
34  enum ValueType {
47  };
48 
49  // uses:
50  //
51  // 1. when adding points to a time-value model, generate values
52  // for those points based on their times or labels or a counter
53  //
54  // 2. when adding a single point to a time-instant model, generate
55  // a label for it based on its time and that of the previous point
56  // or a counter
57  //
58  // 3. when adding a single point to a time-instant model, generate
59  // a label for the previous point based on its time and that of
60  // the point just added (as tempo is based on time to the next
61  // point, not the previous one)
62  //
63  // 4. re-label a set of points that have already been added to a
64  // model
65 
67  m_type(type),
68  m_counter(1),
69  m_counter2(1),
70  m_cycle(4),
71  m_dp(10),
72  m_rate(0) { }
73 
74  Labeller(const Labeller &l) :
75  QObject(),
76  m_type(l.m_type),
79  m_cycle(l.m_cycle),
80  m_dp(l.m_dp),
81  m_rate(l.m_rate) { }
82 
83  virtual ~Labeller() { }
84 
85  typedef std::map<ValueType, QString> TypeNameMap;
87  TypeNameMap m;
88  m[ValueNone]
89  = tr("No numbering");
91  = tr("Simple counter");
93  = tr("Cyclical counter");
95  = tr("Cyclical two-level counter (bar/beat)");
97  = tr("Audio sample frame number");
99  = tr("Time in seconds");
101  = tr("Duration to the following item");
103  = tr("Tempo (bpm) based on duration to following item");
105  = tr("Duration since the previous item");
107  = tr("Tempo (bpm) based on duration since previous item");
109  = tr("Same as the nearest previous item");
110  m[ValueFromLabel]
111  = tr("Value extracted from the item's label (where possible)");
112  return m;
113  }
114 
115  ValueType getType() const { return m_type; }
116  void setType(ValueType type) { m_type = type; }
117 
118  int getCounterValue() const { return m_counter; }
119  void setCounterValue(int v) { m_counter = v; }
120 
121  int getSecondLevelCounterValue() const { return m_counter2; }
123 
124  int getCounterCycleSize() const { return m_cycle; }
125  void setCounterCycleSize(int s) {
126  m_cycle = s;
127  m_dp = 1;
128  while (s > 0) {
129  s /= 10;
130  m_dp *= 10;
131  }
132  if (m_counter > m_cycle) m_counter = 1;
133  }
134 
135  void setSampleRate(float rate) { m_rate = rate; }
136 
137  void resetCounters() {
138  m_counter = 1;
139  m_counter2 = 1;
140  m_cycle = 4;
141  }
142 
144  m_counter++;
147  if (m_counter > m_cycle) {
148  m_counter = 1;
149  m_counter2++;
150  }
151  }
152  }
153 
154  template <typename PointType>
155  void label(PointType &newPoint, PointType *prevPoint = 0) {
156  if (m_type == ValueNone) {
157  newPoint.label = "";
158  } else if (m_type == ValueFromTwoLevelCounter) {
159  newPoint.label = tr("%1.%2").arg(m_counter2).arg(m_counter);
161  } else if (m_type == ValueFromFrameNumber) {
162  // avoid going through floating-point value
163  newPoint.label = tr("%1").arg(newPoint.frame);
164  } else {
165  float value = getValueFor<PointType>(newPoint, prevPoint);
166  if (actingOnPrevPoint() && prevPoint) {
167  prevPoint->label = QString("%1").arg(value);
168  } else {
169  newPoint.label = QString("%1").arg(value);
170  }
171  }
172  }
173 
174  template <typename PointType>
176 
178  typename SparseModel<PointType>::PointList pl(model.getPoints());
179 
180  typename SparseModel<PointType>::EditCommand *command =
182  (&model, tr("Label Points"));
183 
184  PointType prevPoint(0);
185 
186  for (i = pl.begin(); i != pl.end(); ++i) {
187 
188  bool inRange = true;
189  if (ms) {
190  Selection s(ms->getContainingSelection(i->frame, false));
191  if (s.isEmpty() || !s.contains(i->frame)) {
192  inRange = false;
193  }
194  }
195 
196  PointType p(*i);
197 
198  if (!inRange) {
199  prevPoint = p;
200  continue;
201  }
202 
203  if (actingOnPrevPoint()) {
204  if (i != pl.begin()) {
205  command->deletePoint(prevPoint);
206  label<PointType>(p, &prevPoint);
207  command->addPoint(prevPoint);
208  }
209  } else {
210  command->deletePoint(p);
211  label<PointType>(p, &prevPoint);
212  command->addPoint(p);
213  }
214 
215  prevPoint = p;
216  }
217 
218  command->finish();
219  }
220 
221  template <typename PointType>
222  void setValue(PointType &newPoint, PointType *prevPoint = 0) {
224  if (!prevPoint) {
225  std::cerr << "ERROR: Labeller::setValue: Previous point required but not provided" << std::endl;
226  } else {
227  newPoint.value = prevPoint->value;
228  }
229  } else {
230  float value = getValueFor<PointType>(newPoint, prevPoint);
231  if (actingOnPrevPoint() && prevPoint) {
232  prevPoint->value = value;
233  } else {
234  newPoint.value = value;
235  }
236  }
237  }
238 
239  bool requiresPrevPoint() const {
244  }
245 
246  bool actingOnPrevPoint() const {
247  return (m_type == ValueFromDurationToNext ||
249  }
250 
251 protected:
252  template <typename PointType>
253  float getValueFor(PointType &newPoint, PointType *prevPoint)
254  {
255  float value = 0.f;
256 
257  switch (m_type) {
258 
259  case ValueNone:
260  value = 0;
261  break;
262 
265  value = m_counter;
267  break;
268 
270  value = m_counter2 + double(m_counter) / double(m_dp);
272  break;
273 
275  value = newPoint.frame;
276  break;
277 
278  case ValueFromRealTime:
279  if (m_rate == 0.f) {
280  std::cerr << "ERROR: Labeller::getValueFor: Real-time conversion required, but no sample rate set" << std::endl;
281  } else {
282  value = float(newPoint.frame) / float(m_rate);
283  }
284  break;
285 
290  if (m_rate == 0.f) {
291  std::cerr << "ERROR: Labeller::getValueFor: Real-time conversion required, but no sample rate set" << std::endl;
292  } else if (!prevPoint) {
293  std::cerr << "ERROR: Labeller::getValueFor: Time difference required, but only one point provided" << std::endl;
294  } else {
295  int f0 = prevPoint->frame, f1 = newPoint.frame;
298  value = float(f1 - f0) / m_rate;
299  } else {
300  if (f1 > f0) {
301  value = (60.f * m_rate) / (f1 - f0);
302  }
303  }
304  }
305  break;
306 
308  // need to deal with this in the calling function, as this
309  // function must handle points that don't have values to
310  // read from
311  break;
312 
313  case ValueFromLabel:
314  if (newPoint.label != "") {
315  // more forgiving than QString::toFloat()
316  value = atof(newPoint.label.toLocal8Bit());
317  } else {
318  value = 0.f;
319  }
320  break;
321  }
322 
323  return value;
324  }
325 
329  int m_cycle;
330  int m_dp;
331  float m_rate;
332 };
333 
334 #endif
std::multiset< PointType, typename PointType::OrderComparator > PointList
Definition: SparseModel.h:69
int getCounterCycleSize() const
Definition: Labeller.h:124
A selection object simply represents a range in time, via start and end frame.
Definition: Selection.h:39
void setCounterCycleSize(int s)
Definition: Labeller.h:125
void setType(ValueType type)
Definition: Labeller.h:116
virtual void addPoint(const PointType &point)
Add a point.
Definition: SparseModel.h:704
int m_counter
Definition: Labeller.h:327
void incrementCounter()
Definition: Labeller.h:143
std::map< ValueType, QString > TypeNameMap
Definition: Labeller.h:85
int m_counter2
Definition: Labeller.h:328
Command to add or remove a series of points, with undo.
Definition: SparseModel.h:225
Labeller(const Labeller &l)
Definition: Labeller.h:74
virtual const PointList & getPoints() const
Get all points.
Definition: SparseModel.h:537
int getCounterValue() const
Definition: Labeller.h:118
Selection getContainingSelection(int frame, bool defaultToFollowing) const
Return the selection that contains a given frame.
Definition: Selection.cpp:196
virtual ~Labeller()
Definition: Labeller.h:83
bool requiresPrevPoint() const
Definition: Labeller.h:239
bool actingOnPrevPoint() const
Definition: Labeller.h:246
void setCounterValue(int v)
Definition: Labeller.h:119
void label(PointType &newPoint, PointType *prevPoint=0)
Definition: Labeller.h:155
Labeller(ValueType type=ValueNone)
Definition: Labeller.h:66
ValueType m_type
Definition: Labeller.h:326
float getValueFor(PointType &newPoint, PointType *prevPoint)
Definition: Labeller.h:253
void labelAll(SparseModel< PointType > &model, MultiSelection *ms)
Definition: Labeller.h:175
int m_cycle
Definition: Labeller.h:329
TypeNameMap getTypeNames() const
Definition: Labeller.h:86
virtual void deletePoint(const PointType &point)
Remove a point.
Definition: SparseModel.h:736
int getSecondLevelCounterValue() const
Definition: Labeller.h:121
ValueType getType() const
Definition: Labeller.h:115
Model containing sparse data (points with some properties).
Definition: SparseModel.h:42
void setValue(PointType &newPoint, PointType *prevPoint=0)
Definition: Labeller.h:222
void setSecondLevelCounterValue(int v)
Definition: Labeller.h:122
void resetCounters()
Definition: Labeller.h:137
int m_dp
Definition: Labeller.h:330
float m_rate
Definition: Labeller.h:331
void setSampleRate(float rate)
Definition: Labeller.h:135