comparison data/model/SparseModel.h @ 1069:32ab6c48efaa

Merge from branch tonioni
author Chris Cannam
date Mon, 20 Apr 2015 09:11:34 +0100
parents 9fc8823a73e9
children 882d448c8a6d e22bfe8ca248
comparison
equal deleted inserted replaced
1036:682d64f05e72 1069:32ab6c48efaa
41 template <typename PointType> 41 template <typename PointType>
42 class SparseModel : public Model, 42 class SparseModel : public Model,
43 public TabularModel 43 public TabularModel
44 { 44 {
45 public: 45 public:
46 SparseModel(int sampleRate, int resolution, 46 SparseModel(sv_samplerate_t sampleRate, int resolution,
47 bool notifyOnAdd = true); 47 bool notifyOnAdd = true);
48 virtual ~SparseModel() { } 48 virtual ~SparseModel() { }
49 49
50 virtual bool isOK() const { return true; } 50 virtual bool isOK() const { return true; }
51 virtual int getStartFrame() const; 51 virtual sv_frame_t getStartFrame() const;
52 virtual int getEndFrame() const; 52 virtual sv_frame_t getEndFrame() const;
53 virtual int getSampleRate() const { return m_sampleRate; } 53 virtual sv_samplerate_t getSampleRate() const { return m_sampleRate; }
54
55 virtual Model *clone() const;
56 54
57 // Number of frames of the underlying sample rate that this model 55 // Number of frames of the underlying sample rate that this model
58 // is capable of resolving to. For example, if m_resolution == 10 56 // is capable of resolving to. For example, if m_resolution == 10
59 // then every point in this model will be at a multiple of 10 57 // then every point in this model will be at a multiple of 10
60 // sample frames and should be considered to cover a window ending 58 // sample frames and should be considered to cover a window ending
62 virtual int getResolution() const { 60 virtual int getResolution() const {
63 return m_resolution ? m_resolution : 1; 61 return m_resolution ? m_resolution : 1;
64 } 62 }
65 virtual void setResolution(int resolution); 63 virtual void setResolution(int resolution);
66 64
65 // Extend the end of the model. If this is set to something beyond
66 // the end of the final point in the model, then getEndFrame()
67 // will return this value. Otherwise getEndFrame() will return the
68 // end of the final point.
69 virtual void extendEndFrame(sv_frame_t to) { m_extendTo = to; }
70
67 typedef PointType Point; 71 typedef PointType Point;
68 typedef std::multiset<PointType, 72 typedef std::multiset<PointType,
69 typename PointType::OrderComparator> PointList; 73 typename PointType::OrderComparator> PointList;
70 typedef typename PointList::iterator PointListIterator; 74 typedef typename PointList::iterator PointListIterator;
71 typedef typename PointList::const_iterator PointListConstIterator; 75 typedef typename PointList::const_iterator PointListConstIterator;
89 * Get all of the points in this model between the given 93 * Get all of the points in this model between the given
90 * boundaries (in frames), as well as up to two points before and 94 * boundaries (in frames), as well as up to two points before and
91 * after the boundaries. If you need exact boundaries, check the 95 * after the boundaries. If you need exact boundaries, check the
92 * point coordinates in the returned list. 96 * point coordinates in the returned list.
93 */ 97 */
94 virtual PointList getPoints(long start, long end) const; 98 virtual PointList getPoints(sv_frame_t start, sv_frame_t end) const;
95 99
96 /** 100 /**
97 * Get all points that cover the given frame number, taking the 101 * Get all points that cover the given frame number, taking the
98 * resolution of the model into account. 102 * resolution of the model into account.
99 */ 103 */
100 virtual PointList getPoints(long frame) const; 104 virtual PointList getPoints(sv_frame_t frame) const;
101 105
102 /** 106 /**
103 * Return all points that share the nearest frame number prior to 107 * Return all points that share the nearest frame number prior to
104 * the given one at which there are any points. 108 * the given one at which there are any points.
105 */ 109 */
106 virtual PointList getPreviousPoints(long frame) const; 110 virtual PointList getPreviousPoints(sv_frame_t frame) const;
107 111
108 /** 112 /**
109 * Return all points that share the nearest frame number 113 * Return all points that share the nearest frame number
110 * subsequent to the given one at which there are any points. 114 * subsequent to the given one at which there are any points.
111 */ 115 */
112 virtual PointList getNextPoints(long frame) const; 116 virtual PointList getNextPoints(sv_frame_t frame) const;
113 117
114 /** 118 /**
115 * Remove all points. 119 * Remove all points.
116 */ 120 */
117 virtual void clear(); 121 virtual void clear();
146 150
147 virtual void toXml(QTextStream &out, 151 virtual void toXml(QTextStream &out,
148 QString indent = "", 152 QString indent = "",
149 QString extraAttributes = "") const; 153 QString extraAttributes = "") const;
150 154
151 virtual QString toDelimitedDataString(QString delimiter) const 155 virtual QString toDelimitedDataString(QString delimiter) const {
152 { 156 return toDelimitedDataStringWithOptions(delimiter, DataExportDefaults);
153 QString s; 157 }
154 for (PointListConstIterator i = m_points.begin(); i != m_points.end(); ++i) { 158
155 s += i->toDelimitedDataString(delimiter, m_sampleRate) + "\n"; 159 virtual QString toDelimitedDataStringWithOptions(QString delimiter,
156 } 160 DataExportOptions opts) const {
157 return s; 161 return toDelimitedDataStringSubsetWithOptions
158 } 162 (delimiter, opts,
159 163 std::min(getStartFrame(), sv_frame_t(0)), getEndFrame());
160 virtual QString toDelimitedDataStringSubset(QString delimiter, int f0, int f1) const 164 }
161 { 165
162 QString s; 166 virtual QString toDelimitedDataStringSubset(QString delimiter, sv_frame_t f0, sv_frame_t f1) const {
163 for (PointListConstIterator i = m_points.begin(); i != m_points.end(); ++i) { 167 return toDelimitedDataStringSubsetWithOptions(delimiter, DataExportDefaults, f0, f1);
164 if (i->frame >= (long)f0 && i->frame < (long)f1) { 168 }
165 s += i->toDelimitedDataString(delimiter, m_sampleRate) + "\n"; 169
170 virtual QString toDelimitedDataStringSubsetWithOptions(QString delimiter, DataExportOptions opts, sv_frame_t f0, sv_frame_t f1) const {
171 if (opts & DataExportFillGaps) {
172 return toDelimitedDataStringSubsetFilled(delimiter, opts, f0, f1);
173 } else {
174 QString s;
175 for (PointListConstIterator i = m_points.begin(); i != m_points.end(); ++i) {
176 if (i->frame >= f0 && i->frame < f1) {
177 s += i->toDelimitedDataString(delimiter, opts, m_sampleRate) + "\n";
178 }
166 } 179 }
167 } 180 return s;
168 return s; 181 }
169 } 182 }
170 183
171 /** 184 /**
172 * Command to add a point, with undo. 185 * Command to add a point, with undo.
173 */ 186 */
282 * TabularModel methods. 295 * TabularModel methods.
283 */ 296 */
284 297
285 virtual int getRowCount() const 298 virtual int getRowCount() const
286 { 299 {
287 return m_points.size(); 300 return int(m_points.size());
288 } 301 }
289 302
290 virtual long getFrameForRow(int row) const 303 virtual sv_frame_t getFrameForRow(int row) const
291 { 304 {
292 PointListConstIterator i = getPointListIteratorForRow(row); 305 PointListConstIterator i = getPointListIteratorForRow(row);
293 if (i == m_points.end()) return 0; 306 if (i == m_points.end()) return 0;
294 return i->frame; 307 return i->frame;
295 } 308 }
296 309
297 virtual int getRowForFrame(long frame) const 310 virtual int getRowForFrame(sv_frame_t frame) const
298 { 311 {
299 if (m_rows.empty()) rebuildRowVector(); 312 if (m_rows.empty()) rebuildRowVector();
300 std::vector<long>::iterator i = 313 std::vector<sv_frame_t>::iterator i =
301 std::lower_bound(m_rows.begin(), m_rows.end(), frame); 314 std::lower_bound(m_rows.begin(), m_rows.end(), frame);
302 #if defined(__SUNPRO_CC) && defined(__STD_RW_ITERATOR__) 315 ssize_t row = std::distance(m_rows.begin(), i);
303 int row = 0;
304 std::distance(m_rows.begin(), i, row);
305 #else
306 int row = std::distance(m_rows.begin(), i);
307 #endif
308 if (i != m_rows.begin() && (i == m_rows.end() || *i != frame)) { 316 if (i != m_rows.begin() && (i == m_rows.end() || *i != frame)) {
309 --row; 317 --row;
310 } 318 }
311 return row; 319 return int(row);
312 } 320 }
313 321
314 virtual int getColumnCount() const { return 1; } 322 virtual int getColumnCount() const { return 1; }
315 virtual QVariant getData(int row, int column, int role) const 323 virtual QVariant getData(int row, int column, int role) const
316 { 324 {
369 command->deletePoint(*i); 377 command->deletePoint(*i);
370 return command->finish(); 378 return command->finish();
371 } 379 }
372 380
373 protected: 381 protected:
374 int m_sampleRate; 382 sv_samplerate_t m_sampleRate;
375 int m_resolution; 383 int m_resolution;
384 sv_frame_t m_extendTo;
376 bool m_notifyOnAdd; 385 bool m_notifyOnAdd;
377 long m_sinceLastNotifyMin; 386 sv_frame_t m_sinceLastNotifyMin;
378 long m_sinceLastNotifyMax; 387 sv_frame_t m_sinceLastNotifyMax;
379 bool m_hasTextLabels; 388 bool m_hasTextLabels;
380 389
381 PointList m_points; 390 PointList m_points;
382 int m_pointCount; 391 int m_pointCount;
383 mutable QMutex m_mutex; 392 mutable QMutex m_mutex;
384 int m_completion; 393 int m_completion;
385 394
386 void getPointIterators(long frame, 395 void getPointIterators(sv_frame_t frame,
387 PointListIterator &startItr, 396 PointListIterator &startItr,
388 PointListIterator &endItr); 397 PointListIterator &endItr);
389 void getPointIterators(long frame, 398 void getPointIterators(sv_frame_t frame,
390 PointListConstIterator &startItr, 399 PointListConstIterator &startItr,
391 PointListConstIterator &endItr) const; 400 PointListConstIterator &endItr) const;
392 401
393 // This is only used if the model is called on to act in 402 // This is only used if the model is called on to act in
394 // TabularModel mode 403 // TabularModel mode
395 mutable std::vector<long> m_rows; // map from row number to frame 404 mutable std::vector<sv_frame_t> m_rows; // map from row number to frame
396 void rebuildRowVector() const 405 void rebuildRowVector() const
397 { 406 {
398 m_rows.clear(); 407 m_rows.clear();
399 for (PointListConstIterator i = m_points.begin(); i != m_points.end(); ++i) { 408 for (PointListConstIterator i = m_points.begin(); i != m_points.end(); ++i) {
400 // std::cerr << "rebuildRowVector: row " << m_rows.size() << " -> " << i->frame << std::endl; 409 // std::cerr << "rebuildRowVector: row " << m_rows.size() << " -> " << i->frame << std::endl;
405 PointListIterator getPointListIteratorForRow(int row) 414 PointListIterator getPointListIteratorForRow(int row)
406 { 415 {
407 if (m_rows.empty()) rebuildRowVector(); 416 if (m_rows.empty()) rebuildRowVector();
408 if (row < 0 || row + 1 > int(m_rows.size())) return m_points.end(); 417 if (row < 0 || row + 1 > int(m_rows.size())) return m_points.end();
409 418
410 int frame = m_rows[row]; 419 sv_frame_t frame = m_rows[row];
411 int indexAtFrame = 0; 420 int indexAtFrame = 0;
412 int ri = row; 421 int ri = row;
413 while (ri > 0 && m_rows[ri-1] == m_rows[row]) { --ri; ++indexAtFrame; } 422 while (ri > 0 && m_rows[ri-1] == m_rows[row]) { --ri; ++indexAtFrame; }
414 int initialIndexAtFrame = indexAtFrame; 423 int initialIndexAtFrame = indexAtFrame;
415 424
432 PointListConstIterator getPointListIteratorForRow(int row) const 441 PointListConstIterator getPointListIteratorForRow(int row) const
433 { 442 {
434 if (m_rows.empty()) rebuildRowVector(); 443 if (m_rows.empty()) rebuildRowVector();
435 if (row < 0 || row + 1 > int(m_rows.size())) return m_points.end(); 444 if (row < 0 || row + 1 > int(m_rows.size())) return m_points.end();
436 445
437 int frame = m_rows[row]; 446 sv_frame_t frame = m_rows[row];
438 int indexAtFrame = 0; 447 int indexAtFrame = 0;
439 int ri = row; 448 int ri = row;
440 while (ri > 0 && m_rows[ri-1] == m_rows[row]) { --ri; ++indexAtFrame; } 449 while (ri > 0 && m_rows[ri-1] == m_rows[row]) { --ri; ++indexAtFrame; }
441 int initialIndexAtFrame = indexAtFrame; 450 int initialIndexAtFrame = indexAtFrame;
442 451
459 if (indexAtFrame > 0) { 468 if (indexAtFrame > 0) {
460 std::cerr << "WARNING: SparseModel::getPointListIteratorForRow: No iterator available for row " << row << " (frame = " << frame << ", index at frame = " << initialIndexAtFrame << ", leftover index " << indexAtFrame << ")" << std::endl; 469 std::cerr << "WARNING: SparseModel::getPointListIteratorForRow: No iterator available for row " << row << " (frame = " << frame << ", index at frame = " << initialIndexAtFrame << ", leftover index " << indexAtFrame << ")" << std::endl;
461 } 470 }
462 return i; 471 return i;
463 } 472 }
473
474 QString toDelimitedDataStringSubsetFilled(QString delimiter,
475 DataExportOptions opts,
476 sv_frame_t f0,
477 sv_frame_t f1) const {
478
479 QString s;
480 opts &= ~DataExportFillGaps;
481
482 // find frame time of first point in range (if any)
483 sv_frame_t first = f0;
484 for (auto &p: m_points) {
485 if (p.frame >= f0) {
486 first = p.frame;
487 break;
488 }
489 }
490
491 // project back to first frame time in range according to
492 // resolution. e.g. if f0 = 2, first = 9, resolution = 4 then
493 // we start at 5 (because 1 is too early and we need to arrive
494 // at 9 to match the first actual point). This method is
495 // stupid but easy to understand:
496 sv_frame_t f = first;
497 while (f >= f0 + m_resolution) f -= m_resolution;
498
499 // now progress, either writing the next point (if within
500 // distance) or a default point
501 PointListConstIterator itr = m_points.begin();
502
503 while (f < f1) {
504 if (itr != m_points.end() && itr->frame <= f) {
505 s += itr->toDelimitedDataString(delimiter, opts, m_sampleRate);
506 ++itr;
507 } else {
508 s += Point(f).toDelimitedDataString(delimiter, opts, m_sampleRate);
509 }
510 s += "\n";
511 f += m_resolution;
512 }
513
514 return s;
515 }
464 }; 516 };
465 517
466 518
467 template <typename PointType> 519 template <typename PointType>
468 SparseModel<PointType>::SparseModel(int sampleRate, 520 SparseModel<PointType>::SparseModel(sv_samplerate_t sampleRate,
469 int resolution, 521 int resolution,
470 bool notifyOnAdd) : 522 bool notifyOnAdd) :
471 m_sampleRate(sampleRate), 523 m_sampleRate(sampleRate),
472 m_resolution(resolution), 524 m_resolution(resolution),
525 m_extendTo(0),
473 m_notifyOnAdd(notifyOnAdd), 526 m_notifyOnAdd(notifyOnAdd),
474 m_sinceLastNotifyMin(-1), 527 m_sinceLastNotifyMin(-1),
475 m_sinceLastNotifyMax(-1), 528 m_sinceLastNotifyMax(-1),
476 m_hasTextLabels(false), 529 m_hasTextLabels(false),
477 m_pointCount(0), 530 m_pointCount(0),
478 m_completion(100) 531 m_completion(100)
479 { 532 {
480 } 533 }
481 534
482 template <typename PointType> 535 template <typename PointType>
483 int 536 sv_frame_t
484 SparseModel<PointType>::getStartFrame() const 537 SparseModel<PointType>::getStartFrame() const
485 { 538 {
486 QMutexLocker locker(&m_mutex); 539 QMutexLocker locker(&m_mutex);
487 int f = 0; 540 sv_frame_t f = 0;
488 if (!m_points.empty()) { 541 if (!m_points.empty()) {
489 f = m_points.begin()->frame; 542 f = m_points.begin()->frame;
490 } 543 }
491 return f; 544 return f;
492 } 545 }
493 546
494 template <typename PointType> 547 template <typename PointType>
495 int 548 sv_frame_t
496 SparseModel<PointType>::getEndFrame() const 549 SparseModel<PointType>::getEndFrame() const
497 { 550 {
498 QMutexLocker locker(&m_mutex); 551 QMutexLocker locker(&m_mutex);
499 int f = 0; 552 sv_frame_t f = 0;
500 if (!m_points.empty()) { 553 if (!m_points.empty()) {
501 PointListConstIterator i(m_points.end()); 554 PointListConstIterator i(m_points.end());
502 f = (--i)->frame; 555 f = (--i)->frame;
503 } 556 }
504 return f; 557 if (m_extendTo > f) return m_extendTo;
505 } 558 else return f;
506
507 template <typename PointType>
508 Model *
509 SparseModel<PointType>::clone() const
510 {
511 return 0; //!!! is this ever used?
512 /*
513 SparseModel<PointType> *model =
514 new SparseModel<PointType>(m_sampleRate, m_resolution, m_notifyOnAdd);
515 model->m_points = m_points;
516 model->m_pointCount = m_pointCount;
517 return model;
518 */
519 } 559 }
520 560
521 template <typename PointType> 561 template <typename PointType>
522 bool 562 bool
523 SparseModel<PointType>::isEmpty() const 563 SparseModel<PointType>::isEmpty() const
539 return m_points; 579 return m_points;
540 } 580 }
541 581
542 template <typename PointType> 582 template <typename PointType>
543 typename SparseModel<PointType>::PointList 583 typename SparseModel<PointType>::PointList
544 SparseModel<PointType>::getPoints(long start, long end) const 584 SparseModel<PointType>::getPoints(sv_frame_t start, sv_frame_t end) const
545 { 585 {
546 if (start > end) return PointList(); 586 if (start > end) return PointList();
547 QMutexLocker locker(&m_mutex); 587 QMutexLocker locker(&m_mutex);
548 588
549 PointType startPoint(start), endPoint(end); 589 PointType startPoint(start), endPoint(end);
565 return rv; 605 return rv;
566 } 606 }
567 607
568 template <typename PointType> 608 template <typename PointType>
569 typename SparseModel<PointType>::PointList 609 typename SparseModel<PointType>::PointList
570 SparseModel<PointType>::getPoints(long frame) const 610 SparseModel<PointType>::getPoints(sv_frame_t frame) const
571 { 611 {
572 PointListConstIterator startItr, endItr; 612 PointListConstIterator startItr, endItr;
573 getPointIterators(frame, startItr, endItr); 613 getPointIterators(frame, startItr, endItr);
574 614
575 PointList rv; 615 PointList rv;
581 return rv; 621 return rv;
582 } 622 }
583 623
584 template <typename PointType> 624 template <typename PointType>
585 void 625 void
586 SparseModel<PointType>::getPointIterators(long frame, 626 SparseModel<PointType>::getPointIterators(sv_frame_t frame,
587 PointListIterator &startItr, 627 PointListIterator &startItr,
588 PointListIterator &endItr) 628 PointListIterator &endItr)
589 { 629 {
590 QMutexLocker locker(&m_mutex); 630 QMutexLocker locker(&m_mutex);
591 631
593 startItr = m_points.end(); 633 startItr = m_points.end();
594 endItr = m_points.end(); 634 endItr = m_points.end();
595 return; 635 return;
596 } 636 }
597 637
598 long start = (frame / m_resolution) * m_resolution; 638 sv_frame_t start = (frame / m_resolution) * m_resolution;
599 long end = start + m_resolution; 639 sv_frame_t end = start + m_resolution;
600 640
601 PointType startPoint(start), endPoint(end); 641 PointType startPoint(start), endPoint(end);
602 642
603 startItr = m_points.lower_bound(startPoint); 643 startItr = m_points.lower_bound(startPoint);
604 endItr = m_points.upper_bound(endPoint); 644 endItr = m_points.upper_bound(endPoint);
605 } 645 }
606 646
607 template <typename PointType> 647 template <typename PointType>
608 void 648 void
609 SparseModel<PointType>::getPointIterators(long frame, 649 SparseModel<PointType>::getPointIterators(sv_frame_t frame,
610 PointListConstIterator &startItr, 650 PointListConstIterator &startItr,
611 PointListConstIterator &endItr) const 651 PointListConstIterator &endItr) const
612 { 652 {
613 QMutexLocker locker(&m_mutex); 653 QMutexLocker locker(&m_mutex);
614 654
617 startItr = m_points.end(); 657 startItr = m_points.end();
618 endItr = m_points.end(); 658 endItr = m_points.end();
619 return; 659 return;
620 } 660 }
621 661
622 long start = (frame / m_resolution) * m_resolution; 662 sv_frame_t start = (frame / m_resolution) * m_resolution;
623 long end = start + m_resolution; 663 sv_frame_t end = start + m_resolution;
624 664
625 PointType startPoint(start), endPoint(end); 665 PointType startPoint(start), endPoint(end);
626 666
627 // std::cerr << "getPointIterators: start frame " << start << ", end frame " << end << ", m_resolution " << m_resolution << std::endl; 667 // std::cerr << "getPointIterators: start frame " << start << ", end frame " << end << ", m_resolution " << m_resolution << std::endl;
628 668
630 endItr = m_points.upper_bound(endPoint); 670 endItr = m_points.upper_bound(endPoint);
631 } 671 }
632 672
633 template <typename PointType> 673 template <typename PointType>
634 typename SparseModel<PointType>::PointList 674 typename SparseModel<PointType>::PointList
635 SparseModel<PointType>::getPreviousPoints(long originFrame) const 675 SparseModel<PointType>::getPreviousPoints(sv_frame_t originFrame) const
636 { 676 {
637 QMutexLocker locker(&m_mutex); 677 QMutexLocker locker(&m_mutex);
638 678
639 PointType lookupPoint(originFrame); 679 PointType lookupPoint(originFrame);
640 PointList rv; 680 PointList rv;
641 681
642 PointListConstIterator i = m_points.lower_bound(lookupPoint); 682 PointListConstIterator i = m_points.lower_bound(lookupPoint);
643 if (i == m_points.begin()) return rv; 683 if (i == m_points.begin()) return rv;
644 684
645 --i; 685 --i;
646 long frame = i->frame; 686 sv_frame_t frame = i->frame;
647 while (i->frame == frame) { 687 while (i->frame == frame) {
648 rv.insert(*i); 688 rv.insert(*i);
649 if (i == m_points.begin()) break; 689 if (i == m_points.begin()) break;
650 --i; 690 --i;
651 } 691 }
653 return rv; 693 return rv;
654 } 694 }
655 695
656 template <typename PointType> 696 template <typename PointType>
657 typename SparseModel<PointType>::PointList 697 typename SparseModel<PointType>::PointList
658 SparseModel<PointType>::getNextPoints(long originFrame) const 698 SparseModel<PointType>::getNextPoints(sv_frame_t originFrame) const
659 { 699 {
660 QMutexLocker locker(&m_mutex); 700 QMutexLocker locker(&m_mutex);
661 701
662 PointType lookupPoint(originFrame); 702 PointType lookupPoint(originFrame);
663 PointList rv; 703 PointList rv;
664 704
665 PointListConstIterator i = m_points.upper_bound(lookupPoint); 705 PointListConstIterator i = m_points.upper_bound(lookupPoint);
666 if (i == m_points.end()) return rv; 706 if (i == m_points.end()) return rv;
667 707
668 long frame = i->frame; 708 sv_frame_t frame = i->frame;
669 while (i != m_points.end() && i->frame == frame) { 709 while (i != m_points.end() && i->frame == frame) {
670 rv.insert(*i); 710 rv.insert(*i);
671 ++i; 711 ++i;
672 } 712 }
673 713