comparison base/Event.h @ 1615:24dc8cb42755 single-point

Rename a number of classes and methods (including Point -> Event); comments
author Chris Cannam
date Thu, 07 Mar 2019 15:44:09 +0000
parents base/Point.h@23a29e5dc0e9
children 2f9deb8d3295
comparison
equal deleted inserted replaced
1614:2e14a7876945 1615:24dc8cb42755
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 Chris Cannam.
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 SV_EVENT_H
17 #define SV_EVENT_H
18
19 #include "BaseTypes.h"
20 #include "NoteData.h"
21 #include "XmlExportable.h"
22
23 #include <vector>
24 #include <stdexcept>
25
26 #include <QString>
27
28 /**
29 * An immutable type used for point and event representation in sparse
30 * models, as well as for interchange within the clipboard. An event
31 * always has a frame and (possibly empty) label, and optionally has
32 * numerical value, level, duration in frames, and a mapped reference
33 * frame. Event has an operator< defining a total ordering, by frame
34 * first and then by the other properties.
35 *
36 * Event is based on the Clipboard::Point type up to SV v3.2.1 and is
37 * intended also to replace the custom point types previously found in
38 * sparse models.
39 */
40 class Event
41 {
42 public:
43 Event(sv_frame_t frame) :
44 m_haveValue(false), m_haveLevel(false), m_haveReferenceFrame(false),
45 m_value(0.f), m_level(0.f), m_frame(frame),
46 m_duration(0), m_referenceFrame(0), m_label() { }
47
48 Event(sv_frame_t frame, QString label) :
49 m_haveValue(false), m_haveLevel(false), m_haveReferenceFrame(false),
50 m_value(0.f), m_level(0.f), m_frame(frame),
51 m_duration(0), m_referenceFrame(0), m_label(label) { }
52
53 Event(sv_frame_t frame, float value, QString label) :
54 m_haveValue(true), m_haveLevel(false), m_haveReferenceFrame(false),
55 m_value(value), m_level(0.f), m_frame(frame),
56 m_duration(0), m_referenceFrame(0), m_label(label) { }
57
58 Event(sv_frame_t frame, float value, sv_frame_t duration, QString label) :
59 m_haveValue(true), m_haveLevel(false), m_haveReferenceFrame(false),
60 m_value(value), m_level(0.f), m_frame(frame),
61 m_duration(duration), m_referenceFrame(0), m_label(label) {
62 if (m_duration < 0) throw std::logic_error("duration must be >= 0");
63 }
64
65 Event(sv_frame_t frame, float value, sv_frame_t duration,
66 float level, QString label) :
67 m_haveValue(true), m_haveLevel(true), m_haveReferenceFrame(false),
68 m_value(value), m_level(level), m_frame(frame),
69 m_duration(duration), m_referenceFrame(0), m_label(label) {
70 if (m_duration < 0) throw std::logic_error("duration must be >= 0");
71 }
72
73 Event(const Event &event) =default;
74 Event &operator=(const Event &event) =default;
75 Event &operator=(Event &&event) =default;
76
77 sv_frame_t getFrame() const { return m_frame; }
78
79 Event withFrame(sv_frame_t frame) const {
80 Event p(*this);
81 p.m_frame = frame;
82 return p;
83 }
84
85 bool hasValue() const { return m_haveValue; }
86 float getValue() const { return m_value; }
87
88 Event withValue(float value) const {
89 Event p(*this);
90 p.m_haveValue = true;
91 p.m_value = value;
92 return p;
93 }
94 Event withoutValue() const {
95 Event p(*this);
96 p.m_haveValue = false;
97 p.m_value = 0.f;
98 return p;
99 }
100
101 bool hasDuration() const { return m_duration != 0; }
102 sv_frame_t getDuration() const { return m_duration; }
103
104 Event withDuration(sv_frame_t duration) const {
105 Event p(*this);
106 p.m_duration = duration;
107 if (duration < 0) throw std::logic_error("duration must be >= 0");
108 return p;
109 }
110 Event withoutDuration() const {
111 Event p(*this);
112 p.m_duration = 0;
113 return p;
114 }
115
116 QString getLabel() const { return m_label; }
117
118 Event withLabel(QString label) const {
119 Event p(*this);
120 p.m_label = label;
121 return p;
122 }
123
124 bool hasLevel() const { return m_haveLevel; }
125 float getLevel() const { return m_level; }
126
127 Event withLevel(float level) const {
128 Event p(*this);
129 p.m_haveLevel = true;
130 p.m_level = level;
131 return p;
132 }
133 Event withoutLevel() const {
134 Event p(*this);
135 p.m_haveLevel = false;
136 p.m_level = 0.f;
137 return p;
138 }
139
140 bool hasReferenceFrame() const { return m_haveReferenceFrame; }
141 sv_frame_t getReferenceFrame() const { return m_referenceFrame; }
142
143 bool referenceFrameDiffers() const { // from event frame
144 return m_haveReferenceFrame && (m_referenceFrame != m_frame);
145 }
146
147 Event withReferenceFrame(sv_frame_t frame) const {
148 Event p(*this);
149 p.m_haveReferenceFrame = true;
150 p.m_referenceFrame = frame;
151 return p;
152 }
153 Event withoutReferenceFrame() const {
154 Event p(*this);
155 p.m_haveReferenceFrame = false;
156 p.m_referenceFrame = 0;
157 return p;
158 }
159
160 bool operator==(const Event &p) const {
161
162 if (m_frame != p.m_frame) return false;
163 if (m_duration != p.m_duration) return false;
164
165 if (m_haveValue != p.m_haveValue) return false;
166 if (m_haveValue && (m_value != p.m_value)) return false;
167
168 if (m_haveLevel != p.m_haveLevel) return false;
169 if (m_haveLevel && (m_level != p.m_level)) return false;
170
171 if (m_haveReferenceFrame != p.m_haveReferenceFrame) return false;
172 if (m_haveReferenceFrame &&
173 (m_referenceFrame != p.m_referenceFrame)) return false;
174
175 if (m_label != p.m_label) return false;
176
177 return true;
178 }
179
180 bool operator<(const Event &p) const {
181
182 if (m_frame != p.m_frame) return m_frame < p.m_frame;
183 if (m_duration != p.m_duration) return m_duration < p.m_duration;
184
185 // events without a property sort before events with that property
186
187 if (m_haveValue != p.m_haveValue) return !m_haveValue;
188 if (m_haveValue && (m_value != p.m_value)) return m_value < p.m_value;
189
190 if (m_haveLevel != p.m_haveLevel) return !m_haveLevel;
191 if (m_haveLevel && (m_level != p.m_level)) return m_level < p.m_level;
192
193 if (m_haveReferenceFrame != p.m_haveReferenceFrame) {
194 return !m_haveReferenceFrame;
195 }
196 if (m_haveReferenceFrame && (m_referenceFrame != p.m_referenceFrame)) {
197 return m_referenceFrame < p.m_referenceFrame;
198 }
199
200 return m_label < p.m_label;
201 }
202
203 void toXml(QTextStream &stream,
204 QString indent = "",
205 QString extraAttributes = "") const {
206
207 // For I/O purposes these are points, not events
208 stream << indent << QString("<point frame=\"%1\" ").arg(m_frame);
209 if (m_haveValue) stream << QString("value=\"%1\" ").arg(m_value);
210 if (m_duration) stream << QString("duration=\"%1\" ").arg(m_duration);
211 if (m_haveLevel) stream << QString("level=\"%1\" ").arg(m_level);
212 if (m_haveReferenceFrame) stream << QString("referenceFrame=\"%1\" ")
213 .arg(m_referenceFrame);
214 stream << QString("label=\"%1\" ")
215 .arg(XmlExportable::encodeEntities(m_label));
216 stream << extraAttributes << ">\n";
217 }
218
219 QString toXmlString(QString indent = "",
220 QString extraAttributes = "") const {
221 QString s;
222 QTextStream out(&s);
223 toXml(out, indent, extraAttributes);
224 out.flush();
225 return s;
226 }
227
228 NoteData toNoteData(sv_samplerate_t sampleRate, bool valueIsMidiPitch) {
229
230 sv_frame_t duration;
231 if (m_duration > 0) {
232 duration = m_duration;
233 } else {
234 duration = sv_frame_t(sampleRate / 6); // arbitrary short duration
235 }
236
237 int midiPitch;
238 float frequency = 0.f;
239 if (m_haveValue) {
240 if (valueIsMidiPitch) {
241 midiPitch = int(roundf(m_value));
242 } else {
243 frequency = m_value;
244 midiPitch = Pitch::getPitchForFrequency(frequency);
245 }
246 } else {
247 midiPitch = 64;
248 valueIsMidiPitch = true;
249 }
250
251 int velocity = 100;
252 if (m_haveLevel) {
253 if (m_level > 0.f && m_level <= 1.f) {
254 velocity = int(roundf(m_level * 127.f));
255 }
256 }
257
258 NoteData n(m_frame, duration, midiPitch, velocity);
259 n.isMidiPitchQuantized = valueIsMidiPitch;
260 if (!valueIsMidiPitch) {
261 n.frequency = frequency;
262 }
263
264 return n;
265 }
266
267 private:
268 // The order of fields here is chosen to minimise overall size of struct.
269 // We potentially store very many of these objects.
270 // If you change something, check what difference it makes to packing.
271 bool m_haveValue : 1;
272 bool m_haveLevel : 1;
273 bool m_haveReferenceFrame : 1;
274 float m_value;
275 float m_level;
276 sv_frame_t m_frame;
277 sv_frame_t m_duration;
278 sv_frame_t m_referenceFrame;
279 QString m_label;
280 };
281
282 typedef std::vector<Event> EventVector;
283
284 #endif