Chris@1612
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@1612
|
2
|
Chris@1612
|
3 /*
|
Chris@1612
|
4 Sonic Visualiser
|
Chris@1612
|
5 An audio file viewer and annotation editor.
|
Chris@1612
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@1612
|
7
|
Chris@1612
|
8 This program is free software; you can redistribute it and/or
|
Chris@1612
|
9 modify it under the terms of the GNU General Public License as
|
Chris@1612
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@1612
|
11 License, or (at your option) any later version. See the file
|
Chris@1612
|
12 COPYING included with this distribution for more information.
|
Chris@1612
|
13 */
|
Chris@1612
|
14
|
Chris@1612
|
15 #ifndef SV_POINT_SERIES_H
|
Chris@1612
|
16 #define SV_POINT_SERIES_H
|
Chris@1612
|
17
|
Chris@1612
|
18 #include "Point.h"
|
Chris@1612
|
19
|
Chris@1612
|
20 #include <set>
|
Chris@1612
|
21
|
Chris@1612
|
22 class PointSeries
|
Chris@1612
|
23 {
|
Chris@1612
|
24 public:
|
Chris@1612
|
25 PointSeries() : m_count(0) { }
|
Chris@1612
|
26
|
Chris@1612
|
27 void add(const Point &p) {
|
Chris@1612
|
28
|
Chris@1612
|
29 m_points.insert(p);
|
Chris@1612
|
30 ++m_count;
|
Chris@1612
|
31
|
Chris@1612
|
32 if (p.haveDuration()) {
|
Chris@1612
|
33 sv_frame_t frame = p.getFrame();
|
Chris@1612
|
34 sv_frame_t endFrame = p.getFrame() + p.getDuration();
|
Chris@1612
|
35
|
Chris@1612
|
36 std::set<Point> active;
|
Chris@1612
|
37 auto itr = m_seams.lower_bound(frame);
|
Chris@1612
|
38 if (itr == m_seams.end() || itr->first > frame) {
|
Chris@1612
|
39 if (itr != m_seams.begin()) {
|
Chris@1612
|
40 --itr;
|
Chris@1612
|
41 }
|
Chris@1612
|
42 }
|
Chris@1612
|
43 if (itr != m_seams.end()) {
|
Chris@1612
|
44 active = itr->second;
|
Chris@1612
|
45 }
|
Chris@1612
|
46 active.insert(p);
|
Chris@1612
|
47 m_seams[frame] = active;
|
Chris@1612
|
48
|
Chris@1612
|
49 for (itr = m_seams.find(frame); itr->first < endFrame; ++itr) {
|
Chris@1612
|
50 active = itr->second;
|
Chris@1612
|
51 itr->second.insert(p);
|
Chris@1612
|
52 }
|
Chris@1612
|
53
|
Chris@1612
|
54 m_seams[endFrame] = active;
|
Chris@1612
|
55 }
|
Chris@1612
|
56 }
|
Chris@1612
|
57
|
Chris@1612
|
58 void remove(const Point &p) {
|
Chris@1612
|
59
|
Chris@1612
|
60 // erase first itr that matches p; if there is more than one
|
Chris@1612
|
61 // p, erase(p) would remove all of them, but we only want to
|
Chris@1612
|
62 // remove (any) one
|
Chris@1612
|
63 auto pitr = m_points.find(p);
|
Chris@1612
|
64 if (pitr == m_points.end()) {
|
Chris@1612
|
65 return; // we don't know this point
|
Chris@1612
|
66 } else {
|
Chris@1612
|
67 m_points.erase(pitr);
|
Chris@1612
|
68 --m_count;
|
Chris@1612
|
69 }
|
Chris@1612
|
70
|
Chris@1612
|
71 if (p.haveDuration()) {
|
Chris@1612
|
72 sv_frame_t frame = p.getFrame();
|
Chris@1612
|
73 sv_frame_t endFrame = p.getFrame() + p.getDuration();
|
Chris@1612
|
74
|
Chris@1612
|
75 auto itr = m_seams.find(frame);
|
Chris@1612
|
76 if (itr == m_seams.end()) {
|
Chris@1612
|
77 SVCERR << "WARNING: PointSeries::remove: frame " << frame
|
Chris@1612
|
78 << " for point not found in seam map: point is "
|
Chris@1612
|
79 << p.toXmlString() << endl;
|
Chris@1612
|
80 return;
|
Chris@1612
|
81 }
|
Chris@1612
|
82
|
Chris@1612
|
83 while (itr != m_seams.end() && itr->first <= endFrame) {
|
Chris@1612
|
84 itr->second.erase(p);
|
Chris@1612
|
85 ++itr;
|
Chris@1612
|
86 }
|
Chris@1612
|
87
|
Chris@1612
|
88 // Shall we "garbage-collect" here? We could be leaving
|
Chris@1612
|
89 // lots of empty point-sets, or consecutive identical
|
Chris@1612
|
90 // ones, which are a pure irrelevance that take space and
|
Chris@1612
|
91 // slow us down. But a lot depends on whether callers ever
|
Chris@1612
|
92 // really delete anything much.
|
Chris@1612
|
93 }
|
Chris@1612
|
94 }
|
Chris@1612
|
95
|
Chris@1612
|
96 bool contains(const Point &p) {
|
Chris@1612
|
97 return m_points.find(p) != m_points.end();
|
Chris@1612
|
98 }
|
Chris@1612
|
99
|
Chris@1612
|
100 int count() const {
|
Chris@1612
|
101 return m_count;
|
Chris@1612
|
102 }
|
Chris@1612
|
103
|
Chris@1612
|
104 bool isEmpty() const {
|
Chris@1612
|
105 return m_count == 0;
|
Chris@1612
|
106 }
|
Chris@1612
|
107
|
Chris@1612
|
108 void clear() {
|
Chris@1612
|
109 m_points.clear();
|
Chris@1612
|
110 m_seams.clear();
|
Chris@1612
|
111 m_count = 0;
|
Chris@1612
|
112 }
|
Chris@1612
|
113
|
Chris@1612
|
114 /**
|
Chris@1612
|
115 * Retrieve all points that span the given frame. A point without
|
Chris@1612
|
116 * duration spans a frame if its own frame is equal to it. A point
|
Chris@1612
|
117 * with duration spans a frame if its start frame is less than or
|
Chris@1612
|
118 * equal to it and its end frame (start + duration) is greater
|
Chris@1612
|
119 * than it.
|
Chris@1612
|
120 */
|
Chris@1612
|
121 PointVector getPointsSpanning(sv_frame_t frame) {
|
Chris@1612
|
122 return {};
|
Chris@1612
|
123 }
|
Chris@1612
|
124
|
Chris@1612
|
125 private:
|
Chris@1612
|
126 int m_count;
|
Chris@1612
|
127 std::multiset<Point> m_points;
|
Chris@1612
|
128 std::map<sv_frame_t, std::set<Point>> m_seams;
|
Chris@1612
|
129 };
|
Chris@1612
|
130
|
Chris@1612
|
131 #endif
|