Chris@133
|
1
|
Chris@133
|
2 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@133
|
3
|
Chris@133
|
4 /*
|
Chris@133
|
5 Sonic Visualiser
|
Chris@133
|
6 An audio file viewer and annotation editor.
|
Chris@133
|
7 Centre for Digital Music, Queen Mary, University of London.
|
Chris@133
|
8 This file copyright 2006 Chris Cannam.
|
Chris@133
|
9
|
Chris@133
|
10 This program is free software; you can redistribute it and/or
|
Chris@133
|
11 modify it under the terms of the GNU General Public License as
|
Chris@133
|
12 published by the Free Software Foundation; either version 2 of the
|
Chris@133
|
13 License, or (at your option) any later version. See the file
|
Chris@133
|
14 COPYING included with this distribution for more information.
|
Chris@133
|
15 */
|
Chris@133
|
16
|
Chris@133
|
17 #include "SpectrumLayer.h"
|
Chris@133
|
18
|
Chris@133
|
19 #include "data/model/FFTModel.h"
|
Chris@133
|
20 #include "view/View.h"
|
Chris@153
|
21 #include "base/AudioLevel.h"
|
Chris@153
|
22 #include "base/Preferences.h"
|
Chris@133
|
23
|
Chris@133
|
24 #include <QPainter>
|
Chris@133
|
25 #include <QPainterPath>
|
Chris@133
|
26
|
Chris@133
|
27 SpectrumLayer::SpectrumLayer() :
|
Chris@133
|
28 m_model(0),
|
Chris@153
|
29 m_channelMode(MixChannels),
|
Chris@153
|
30 m_channel(-1),
|
Chris@153
|
31 m_channelSet(false),
|
Chris@153
|
32 m_colour(Qt::darkBlue),
|
Chris@153
|
33 m_energyScale(dBScale),
|
Chris@153
|
34 m_normalize(false),
|
Chris@153
|
35 m_gain(1.0),
|
Chris@153
|
36 m_windowSize(1024),
|
Chris@153
|
37 m_windowType(HanningWindow),
|
Chris@153
|
38 m_windowHopLevel(2)
|
Chris@133
|
39 {
|
Chris@153
|
40 Preferences *prefs = Preferences::getInstance();
|
Chris@153
|
41 connect(prefs, SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
|
Chris@153
|
42 this, SLOT(preferenceChanged(PropertyContainer::PropertyName)));
|
Chris@153
|
43 setWindowType(prefs->getWindowType());
|
Chris@133
|
44 }
|
Chris@133
|
45
|
Chris@133
|
46 SpectrumLayer::~SpectrumLayer()
|
Chris@133
|
47 {
|
Chris@153
|
48 for (size_t i = 0; i < m_fft.size(); ++i) delete m_fft[i];
|
Chris@133
|
49 }
|
Chris@133
|
50
|
Chris@133
|
51 void
|
Chris@133
|
52 SpectrumLayer::setModel(DenseTimeValueModel *model)
|
Chris@133
|
53 {
|
Chris@133
|
54 m_model = model;
|
Chris@153
|
55 setupFFTs();
|
Chris@153
|
56 }
|
Chris@153
|
57
|
Chris@153
|
58 void
|
Chris@153
|
59 SpectrumLayer::setupFFTs()
|
Chris@153
|
60 {
|
Chris@153
|
61 for (size_t i = 0; i < m_fft.size(); ++i) delete m_fft[i];
|
Chris@153
|
62 m_fft.clear();
|
Chris@153
|
63
|
Chris@153
|
64 int minChannel = m_channel, maxChannel = m_channel;
|
Chris@153
|
65
|
Chris@153
|
66 if (m_channel == -1 &&
|
Chris@153
|
67 m_channelMode != MixChannels) {
|
Chris@153
|
68 minChannel = 0;
|
Chris@153
|
69 maxChannel = 0;
|
Chris@153
|
70 if (m_model->getChannelCount() > 1) {
|
Chris@153
|
71 maxChannel = m_model->getChannelCount() - 1;
|
Chris@153
|
72 }
|
Chris@153
|
73 }
|
Chris@153
|
74
|
Chris@153
|
75 for (int c = minChannel; c <= maxChannel; ++c) {
|
Chris@153
|
76
|
Chris@153
|
77 m_fft.push_back(new FFTModel(m_model,
|
Chris@153
|
78 c,
|
Chris@153
|
79 HanningWindow,
|
Chris@153
|
80 m_windowSize,
|
Chris@153
|
81 getWindowIncrement(),
|
Chris@153
|
82 m_windowSize,
|
Chris@153
|
83 true));
|
Chris@153
|
84
|
Chris@153
|
85 if (m_channelSet) m_fft[m_fft.size()-1]->resume();
|
Chris@153
|
86 }
|
Chris@153
|
87 }
|
Chris@153
|
88
|
Chris@153
|
89 void
|
Chris@153
|
90 SpectrumLayer::setChannel(int channel)
|
Chris@153
|
91 {
|
Chris@153
|
92 m_channelSet = true;
|
Chris@153
|
93
|
Chris@153
|
94 if (m_channel == channel) {
|
Chris@153
|
95 for (size_t i = 0; i < m_fft.size(); ++i) {
|
Chris@153
|
96 m_fft[i]->resume();
|
Chris@153
|
97 }
|
Chris@153
|
98 return;
|
Chris@153
|
99 }
|
Chris@153
|
100
|
Chris@153
|
101 m_channel = channel;
|
Chris@153
|
102
|
Chris@153
|
103 if (!m_fft.empty()) setupFFTs();
|
Chris@153
|
104
|
Chris@153
|
105 emit layerParametersChanged();
|
Chris@133
|
106 }
|
Chris@133
|
107
|
Chris@133
|
108 void
|
Chris@133
|
109 SpectrumLayer::paint(View *v, QPainter &paint, QRect rect) const
|
Chris@133
|
110 {
|
Chris@153
|
111 if (m_fft.empty()) return;
|
Chris@153
|
112 if (!m_channelSet) {
|
Chris@153
|
113 for (size_t i = 0; i < m_fft.size(); ++i) {
|
Chris@153
|
114 m_fft[i]->resume();
|
Chris@153
|
115 }
|
Chris@153
|
116 }
|
Chris@133
|
117
|
Chris@153
|
118 FFTModel *fft = m_fft[0]; //!!! for now
|
Chris@153
|
119
|
Chris@153
|
120 int windowIncrement = getWindowIncrement();
|
Chris@133
|
121
|
Chris@133
|
122 size_t f = v->getCentreFrame();
|
Chris@133
|
123
|
Chris@133
|
124 int w = (v->width() * 2) / 3;
|
Chris@133
|
125 int xorigin = (v->width() / 2) - (w / 2);
|
Chris@133
|
126
|
Chris@133
|
127 int h = (v->height() * 2) / 3;
|
Chris@133
|
128 int yorigin = (v->height() / 2) + (h / 2);
|
Chris@133
|
129
|
Chris@133
|
130 size_t column = f / windowIncrement;
|
Chris@133
|
131
|
Chris@133
|
132 paint.save();
|
Chris@133
|
133 paint.setPen(m_colour);
|
Chris@133
|
134 paint.setRenderHint(QPainter::Antialiasing, false);
|
Chris@133
|
135
|
Chris@133
|
136 QPainterPath path;
|
Chris@133
|
137 float thresh = -80.f;
|
Chris@133
|
138
|
Chris@153
|
139 for (size_t bin = 0; bin < fft->getHeight(); ++bin) {
|
Chris@133
|
140
|
Chris@153
|
141 float x = xorigin + (float(w) * bin) / fft->getHeight();
|
Chris@153
|
142 float mag;
|
Chris@153
|
143 if (m_normalize) {
|
Chris@153
|
144 mag = fft->getNormalizedMagnitudeAt(column, bin);
|
Chris@153
|
145 } else {
|
Chris@153
|
146 mag = fft->getMagnitudeAt(column, bin);
|
Chris@153
|
147 }
|
Chris@153
|
148 mag *= m_gain;
|
Chris@153
|
149 float y = 0.f;
|
Chris@153
|
150
|
Chris@153
|
151 switch (m_energyScale) {
|
Chris@153
|
152
|
Chris@153
|
153 case dBScale:
|
Chris@153
|
154 {
|
Chris@153
|
155 float db = thresh;
|
Chris@153
|
156 if (mag > 0.f) db = 10.f * log10f(mag);
|
Chris@153
|
157 if (db < thresh) db = thresh;
|
Chris@153
|
158 float val = (db - thresh) / -thresh;
|
Chris@153
|
159 y = yorigin - (float(h) * val);
|
Chris@153
|
160 break;
|
Chris@153
|
161 }
|
Chris@153
|
162
|
Chris@153
|
163 case MeterScale:
|
Chris@153
|
164 y = yorigin - AudioLevel::multiplier_to_preview(mag, h);
|
Chris@153
|
165 break;
|
Chris@153
|
166
|
Chris@153
|
167 default:
|
Chris@153
|
168 y = yorigin - (float(h) * mag);
|
Chris@153
|
169 break;
|
Chris@153
|
170 }
|
Chris@133
|
171
|
Chris@133
|
172 if (bin == 0) {
|
Chris@133
|
173 path.moveTo(x, y);
|
Chris@133
|
174 } else {
|
Chris@133
|
175 path.lineTo(x, y);
|
Chris@133
|
176 }
|
Chris@133
|
177 }
|
Chris@133
|
178
|
Chris@133
|
179 paint.drawPath(path);
|
Chris@133
|
180 paint.restore();
|
Chris@133
|
181
|
Chris@133
|
182 }
|
Chris@133
|
183
|
Chris@153
|
184 Layer::PropertyList
|
Chris@153
|
185 SpectrumLayer::getProperties() const
|
Chris@153
|
186 {
|
Chris@153
|
187 PropertyList list;
|
Chris@153
|
188 list.push_back("Colour");
|
Chris@153
|
189 list.push_back("Scale");
|
Chris@153
|
190 list.push_back("Normalize");
|
Chris@153
|
191 list.push_back("Gain");
|
Chris@153
|
192 list.push_back("Window Size");
|
Chris@153
|
193 list.push_back("Window Increment");
|
Chris@153
|
194
|
Chris@153
|
195 if (m_model && m_model->getChannelCount() > 1 && m_channel == -1) {
|
Chris@153
|
196 list.push_back("Channels");
|
Chris@153
|
197 }
|
Chris@153
|
198
|
Chris@153
|
199 return list;
|
Chris@153
|
200 }
|
Chris@153
|
201
|
Chris@153
|
202 QString
|
Chris@153
|
203 SpectrumLayer::getPropertyLabel(const PropertyName &name) const
|
Chris@153
|
204 {
|
Chris@153
|
205 if (name == "Colour") return tr("Colour");
|
Chris@153
|
206 if (name == "Energy Scale") return tr("Scale");
|
Chris@153
|
207 if (name == "Channels") return tr("Channels");
|
Chris@153
|
208 if (name == "Window Size") return tr("Window Size");
|
Chris@153
|
209 if (name == "Window Increment") return tr("Window Overlap");
|
Chris@153
|
210 if (name == "Normalize") return tr("Normalize");
|
Chris@153
|
211 if (name == "Gain") return tr("Gain");
|
Chris@153
|
212 return "";
|
Chris@153
|
213 }
|
Chris@153
|
214
|
Chris@153
|
215 Layer::PropertyType
|
Chris@153
|
216 SpectrumLayer::getPropertyType(const PropertyName &name) const
|
Chris@153
|
217 {
|
Chris@153
|
218 if (name == "Gain") return RangeProperty;
|
Chris@153
|
219 if (name == "Normalize") return ToggleProperty;
|
Chris@153
|
220 return ValueProperty;
|
Chris@153
|
221 }
|
Chris@153
|
222
|
Chris@153
|
223 QString
|
Chris@153
|
224 SpectrumLayer::getPropertyGroupName(const PropertyName &name) const
|
Chris@153
|
225 {
|
Chris@153
|
226 if (name == "Window Size" ||
|
Chris@153
|
227 name == "Window Increment") return tr("Window");
|
Chris@153
|
228 if (name == "Scale" ||
|
Chris@153
|
229 name == "Normalize" ||
|
Chris@153
|
230 name == "Gain") return tr("Energy Scale");
|
Chris@153
|
231 return QString();
|
Chris@153
|
232 }
|
Chris@153
|
233
|
Chris@153
|
234 int
|
Chris@153
|
235 SpectrumLayer::getPropertyRangeAndValue(const PropertyName &name,
|
Chris@153
|
236 int *min, int *max) const
|
Chris@153
|
237 {
|
Chris@153
|
238 int deft = 0;
|
Chris@153
|
239
|
Chris@153
|
240 int garbage0, garbage1;
|
Chris@153
|
241 if (!min) min = &garbage0;
|
Chris@153
|
242 if (!max) max = &garbage1;
|
Chris@153
|
243
|
Chris@153
|
244 if (name == "Gain") {
|
Chris@153
|
245
|
Chris@153
|
246 *min = -50;
|
Chris@153
|
247 *max = 50;
|
Chris@153
|
248
|
Chris@153
|
249 deft = lrint(log10(m_gain) * 20.0);
|
Chris@153
|
250 if (deft < *min) deft = *min;
|
Chris@153
|
251 if (deft > *max) deft = *max;
|
Chris@153
|
252
|
Chris@153
|
253 } else if (name == "Normalize") {
|
Chris@153
|
254
|
Chris@153
|
255 deft = (m_normalize ? 1 : 0);
|
Chris@153
|
256
|
Chris@153
|
257 } else if (name == "Colour") {
|
Chris@153
|
258
|
Chris@153
|
259 *min = 0;
|
Chris@153
|
260 *max = 5;
|
Chris@153
|
261
|
Chris@153
|
262 if (m_colour == Qt::black) deft = 0;
|
Chris@153
|
263 else if (m_colour == Qt::darkRed) deft = 1;
|
Chris@153
|
264 else if (m_colour == Qt::darkBlue) deft = 2;
|
Chris@153
|
265 else if (m_colour == Qt::darkGreen) deft = 3;
|
Chris@153
|
266 else if (m_colour == QColor(200, 50, 255)) deft = 4;
|
Chris@153
|
267 else if (m_colour == QColor(255, 150, 50)) deft = 5;
|
Chris@153
|
268
|
Chris@153
|
269 } else if (name == "Channels") {
|
Chris@153
|
270
|
Chris@153
|
271 *min = 0;
|
Chris@153
|
272 *max = 2;
|
Chris@153
|
273 if (m_channelMode == MixChannels) deft = 1;
|
Chris@153
|
274 else if (m_channelMode == OverlayChannels) deft = 2;
|
Chris@153
|
275 else deft = 0;
|
Chris@153
|
276
|
Chris@153
|
277 } else if (name == "Scale") {
|
Chris@153
|
278
|
Chris@153
|
279 *min = 0;
|
Chris@153
|
280 *max = 2;
|
Chris@153
|
281
|
Chris@153
|
282 deft = (int)m_energyScale;
|
Chris@153
|
283
|
Chris@153
|
284 } else if (name == "Window Size") {
|
Chris@153
|
285
|
Chris@153
|
286 *min = 0;
|
Chris@153
|
287 *max = 10;
|
Chris@153
|
288
|
Chris@153
|
289 deft = 0;
|
Chris@153
|
290 int ws = m_windowSize;
|
Chris@153
|
291 while (ws > 32) { ws >>= 1; deft ++; }
|
Chris@153
|
292
|
Chris@153
|
293 } else if (name == "Window Increment") {
|
Chris@153
|
294
|
Chris@153
|
295 *min = 0;
|
Chris@153
|
296 *max = 5;
|
Chris@153
|
297
|
Chris@153
|
298 deft = m_windowHopLevel;
|
Chris@153
|
299
|
Chris@153
|
300 } else {
|
Chris@153
|
301 deft = Layer::getPropertyRangeAndValue(name, min, max);
|
Chris@153
|
302 }
|
Chris@153
|
303
|
Chris@153
|
304 return deft;
|
Chris@153
|
305 }
|
Chris@153
|
306
|
Chris@153
|
307 QString
|
Chris@153
|
308 SpectrumLayer::getPropertyValueLabel(const PropertyName &name,
|
Chris@153
|
309 int value) const
|
Chris@153
|
310 {
|
Chris@153
|
311 if (name == "Colour") {
|
Chris@153
|
312 switch (value) {
|
Chris@153
|
313 default:
|
Chris@153
|
314 case 0: return tr("Black");
|
Chris@153
|
315 case 1: return tr("Red");
|
Chris@153
|
316 case 2: return tr("Blue");
|
Chris@153
|
317 case 3: return tr("Green");
|
Chris@153
|
318 case 4: return tr("Purple");
|
Chris@153
|
319 case 5: return tr("Orange");
|
Chris@153
|
320 }
|
Chris@153
|
321 }
|
Chris@153
|
322 if (name == "Scale") {
|
Chris@153
|
323 switch (value) {
|
Chris@153
|
324 default:
|
Chris@153
|
325 case 0: return tr("Linear");
|
Chris@153
|
326 case 1: return tr("Meter");
|
Chris@153
|
327 case 2: return tr("dB");
|
Chris@153
|
328 }
|
Chris@153
|
329 }
|
Chris@153
|
330 if (name == "Channels") {
|
Chris@153
|
331 switch (value) {
|
Chris@153
|
332 default:
|
Chris@153
|
333 case 0: return tr("Separate");
|
Chris@153
|
334 case 1: return tr("Mean");
|
Chris@153
|
335 case 2: return tr("Overlay");
|
Chris@153
|
336 }
|
Chris@153
|
337 }
|
Chris@153
|
338 if (name == "Window Size") {
|
Chris@153
|
339 return QString("%1").arg(32 << value);
|
Chris@153
|
340 }
|
Chris@153
|
341 if (name == "Window Increment") {
|
Chris@153
|
342 switch (value) {
|
Chris@153
|
343 default:
|
Chris@153
|
344 case 0: return tr("None");
|
Chris@153
|
345 case 1: return tr("25 %");
|
Chris@153
|
346 case 2: return tr("50 %");
|
Chris@153
|
347 case 3: return tr("75 %");
|
Chris@153
|
348 case 4: return tr("87.5 %");
|
Chris@153
|
349 case 5: return tr("93.75 %");
|
Chris@153
|
350 }
|
Chris@153
|
351 }
|
Chris@153
|
352 return tr("<unknown>");
|
Chris@153
|
353 }
|
Chris@153
|
354
|
Chris@133
|
355 void
|
Chris@153
|
356 SpectrumLayer::setProperty(const PropertyName &name, int value)
|
Chris@133
|
357 {
|
Chris@153
|
358 if (name == "Gain") {
|
Chris@153
|
359 setGain(pow(10, float(value)/20.0));
|
Chris@153
|
360 } else if (name == "Colour") {
|
Chris@153
|
361 switch (value) {
|
Chris@153
|
362 default:
|
Chris@153
|
363 case 0: setBaseColour(Qt::black); break;
|
Chris@153
|
364 case 1: setBaseColour(Qt::darkRed); break;
|
Chris@153
|
365 case 2: setBaseColour(Qt::darkBlue); break;
|
Chris@153
|
366 case 3: setBaseColour(Qt::darkGreen); break;
|
Chris@153
|
367 case 4: setBaseColour(QColor(200, 50, 255)); break;
|
Chris@153
|
368 case 5: setBaseColour(QColor(255, 150, 50)); break;
|
Chris@153
|
369 }
|
Chris@153
|
370 } else if (name == "Channels") {
|
Chris@153
|
371 if (value == 1) setChannelMode(MixChannels);
|
Chris@153
|
372 else if (value == 2) setChannelMode(OverlayChannels);
|
Chris@153
|
373 else setChannelMode(SeparateChannels);
|
Chris@153
|
374 } else if (name == "Scale") {
|
Chris@153
|
375 switch (value) {
|
Chris@153
|
376 default:
|
Chris@153
|
377 case 0: setEnergyScale(LinearScale); break;
|
Chris@153
|
378 case 1: setEnergyScale(MeterScale); break;
|
Chris@153
|
379 case 2: setEnergyScale(dBScale); break;
|
Chris@153
|
380 }
|
Chris@153
|
381 } else if (name == "Window Size") {
|
Chris@153
|
382 setWindowSize(32 << value);
|
Chris@153
|
383 } else if (name == "Window Increment") {
|
Chris@153
|
384 setWindowHopLevel(value);
|
Chris@153
|
385 } else if (name == "Normalize") {
|
Chris@153
|
386 setNormalize(value ? true : false);
|
Chris@153
|
387 }
|
Chris@153
|
388 }
|
Chris@153
|
389
|
Chris@153
|
390 void
|
Chris@153
|
391 SpectrumLayer::setBaseColour(QColor colour)
|
Chris@153
|
392 {
|
Chris@153
|
393 if (m_colour == colour) return;
|
Chris@153
|
394 m_colour = colour;
|
Chris@153
|
395 emit layerParametersChanged();
|
Chris@153
|
396 }
|
Chris@153
|
397
|
Chris@153
|
398 void
|
Chris@153
|
399 SpectrumLayer::setChannelMode(ChannelMode channelMode)
|
Chris@153
|
400 {
|
Chris@153
|
401 if (m_channelMode == channelMode) return;
|
Chris@153
|
402 m_channelMode = channelMode;
|
Chris@153
|
403 emit layerParametersChanged();
|
Chris@153
|
404 }
|
Chris@153
|
405
|
Chris@153
|
406 void
|
Chris@153
|
407 SpectrumLayer::setEnergyScale(EnergyScale scale)
|
Chris@153
|
408 {
|
Chris@153
|
409 if (m_energyScale == scale) return;
|
Chris@153
|
410 m_energyScale = scale;
|
Chris@153
|
411 emit layerParametersChanged();
|
Chris@153
|
412 }
|
Chris@153
|
413
|
Chris@153
|
414 void
|
Chris@153
|
415 SpectrumLayer::setWindowSize(size_t ws)
|
Chris@153
|
416 {
|
Chris@153
|
417 if (m_windowSize == ws) return;
|
Chris@153
|
418 m_windowSize = ws;
|
Chris@153
|
419 setupFFTs();
|
Chris@153
|
420 emit layerParametersChanged();
|
Chris@153
|
421 }
|
Chris@153
|
422
|
Chris@153
|
423 void
|
Chris@153
|
424 SpectrumLayer::setWindowHopLevel(size_t v)
|
Chris@153
|
425 {
|
Chris@153
|
426 if (m_windowHopLevel == v) return;
|
Chris@153
|
427 m_windowHopLevel = v;
|
Chris@153
|
428 setupFFTs();
|
Chris@153
|
429 emit layerParametersChanged();
|
Chris@153
|
430 }
|
Chris@153
|
431
|
Chris@153
|
432 void
|
Chris@153
|
433 SpectrumLayer::setWindowType(WindowType w)
|
Chris@153
|
434 {
|
Chris@153
|
435 if (m_windowType == w) return;
|
Chris@153
|
436 m_windowType = w;
|
Chris@153
|
437 setupFFTs();
|
Chris@153
|
438 emit layerParametersChanged();
|
Chris@153
|
439 }
|
Chris@153
|
440
|
Chris@153
|
441 void
|
Chris@153
|
442 SpectrumLayer::setNormalize(bool n)
|
Chris@153
|
443 {
|
Chris@153
|
444 if (m_normalize == n) return;
|
Chris@153
|
445 m_normalize = n;
|
Chris@153
|
446 emit layerParametersChanged();
|
Chris@153
|
447 }
|
Chris@153
|
448
|
Chris@153
|
449 void
|
Chris@153
|
450 SpectrumLayer::setGain(float gain)
|
Chris@153
|
451 {
|
Chris@153
|
452 if (m_gain == gain) return;
|
Chris@153
|
453 m_gain = gain;
|
Chris@153
|
454 emit layerParametersChanged();
|
Chris@153
|
455 }
|
Chris@153
|
456
|
Chris@153
|
457 void
|
Chris@153
|
458 SpectrumLayer::preferenceChanged(PropertyContainer::PropertyName name)
|
Chris@153
|
459 {
|
Chris@153
|
460 if (name == "Window Type") {
|
Chris@153
|
461 setWindowType(Preferences::getInstance()->getWindowType());
|
Chris@153
|
462 return;
|
Chris@153
|
463 }
|
Chris@153
|
464 }
|
Chris@153
|
465
|
Chris@153
|
466 QString
|
Chris@153
|
467 SpectrumLayer::toXmlString(QString indent, QString extraAttributes) const
|
Chris@153
|
468 {
|
Chris@153
|
469 QString s;
|
Chris@153
|
470
|
Chris@153
|
471 s += QString("colour=\"%1\" "
|
Chris@153
|
472 "channelMode=\"%2\" "
|
Chris@153
|
473 "channel=\"%3\" "
|
Chris@153
|
474 "energyScale=\"%4\" "
|
Chris@153
|
475 "windowSize=\"%5\" "
|
Chris@153
|
476 "windowHopLevel=\"%6\" "
|
Chris@153
|
477 "gain=\"%7\" "
|
Chris@153
|
478 "normalize=\"%8\"")
|
Chris@153
|
479 .arg(encodeColour(m_colour))
|
Chris@153
|
480 .arg(m_channelMode)
|
Chris@153
|
481 .arg(m_channel)
|
Chris@153
|
482 .arg(m_energyScale)
|
Chris@153
|
483 .arg(m_windowSize)
|
Chris@153
|
484 .arg(m_windowHopLevel)
|
Chris@153
|
485 .arg(m_gain)
|
Chris@153
|
486 .arg(m_normalize ? "true" : "false");
|
Chris@153
|
487
|
Chris@153
|
488 return Layer::toXmlString(indent, extraAttributes + " " + s);
|
Chris@153
|
489 }
|
Chris@153
|
490
|
Chris@153
|
491 void
|
Chris@153
|
492 SpectrumLayer::setProperties(const QXmlAttributes &attributes)
|
Chris@153
|
493 {
|
Chris@153
|
494 bool ok = false;
|
Chris@153
|
495
|
Chris@153
|
496 QString colourSpec = attributes.value("colour");
|
Chris@153
|
497 if (colourSpec != "") {
|
Chris@153
|
498 QColor colour(colourSpec);
|
Chris@153
|
499 if (colour.isValid()) {
|
Chris@153
|
500 setBaseColour(QColor(colourSpec));
|
Chris@153
|
501 }
|
Chris@153
|
502 }
|
Chris@153
|
503
|
Chris@153
|
504 ChannelMode channelMode = (ChannelMode)
|
Chris@153
|
505 attributes.value("channelMode").toInt(&ok);
|
Chris@153
|
506 if (ok) setChannelMode(channelMode);
|
Chris@153
|
507
|
Chris@153
|
508 int channel = attributes.value("channel").toInt(&ok);
|
Chris@153
|
509 if (ok) setChannel(channel);
|
Chris@153
|
510
|
Chris@153
|
511 EnergyScale scale = (EnergyScale)
|
Chris@153
|
512 attributes.value("energyScale").toInt(&ok);
|
Chris@153
|
513 if (ok) setEnergyScale(scale);
|
Chris@153
|
514
|
Chris@153
|
515 size_t windowSize = attributes.value("windowSize").toUInt(&ok);
|
Chris@153
|
516 if (ok) setWindowSize(windowSize);
|
Chris@153
|
517
|
Chris@153
|
518 size_t windowHopLevel = attributes.value("windowHopLevel").toUInt(&ok);
|
Chris@153
|
519 if (ok) setWindowHopLevel(windowHopLevel);
|
Chris@153
|
520
|
Chris@153
|
521 float gain = attributes.value("gain").toFloat(&ok);
|
Chris@153
|
522 if (ok) setGain(gain);
|
Chris@153
|
523
|
Chris@153
|
524 bool normalize = (attributes.value("normalize").trimmed() == "true");
|
Chris@153
|
525 setNormalize(normalize);
|
Chris@133
|
526 }
|
Chris@133
|
527
|
Chris@133
|
528 bool
|
Chris@133
|
529 SpectrumLayer::getValueExtents(float &min, float &max, bool &logarithmic,
|
Chris@133
|
530 QString &units) const
|
Chris@133
|
531 {
|
Chris@133
|
532 return false;
|
Chris@133
|
533 }
|
Chris@133
|
534
|