comparison layer/PaintAssistant.cpp @ 195:4a3bdde1ef13

* beginnings of spectrum scales
author Chris Cannam
date Mon, 29 Jan 2007 18:11:20 +0000
parents
children c2ed5014d4ff
comparison
equal deleted inserted replaced
194:d13e209bfa94 195:4a3bdde1ef13
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 #include "PaintAssistant.h"
17
18 #include "base/AudioLevel.h"
19
20 #include <QPaintDevice>
21 #include <QPainter>
22
23 void
24 PaintAssistant::paintVerticalLevelScale(QPainter &paint, QRect rect,
25 float minVal, float maxVal,
26 Scale scale, std::vector<int> *vy)
27 {
28 static float meterdbs[] = { -40, -30, -20, -15, -10,
29 -5, -3, -2, -1, -0.5, 0 };
30
31 int h = rect.height(), w = rect.width();
32 int textHeight = paint.fontMetrics().height();
33 int toff = -textHeight/2 + paint.fontMetrics().ascent() + 1;
34
35 int lastLabelledY = -1;
36
37 int n = 10;
38 if (vy) vy->clear();
39
40 for (int i = 0; i <= n; ++i) {
41
42 float val = 0.0, nval = 0.0;
43 QString text = "";
44
45 switch (scale) {
46
47 case LinearScale:
48 val = minVal + ((maxVal - minVal) * i) / n;
49 text = QString("%1").arg(val);//float(i) / n); // ... val
50 /*
51 if (i == 0) text = "0.0";
52 else {
53 nval = -val;
54 if (i == n) text = "1.0";
55 }
56 */
57 break;
58
59 case MeterScale: // ... min, max
60 val = AudioLevel::dB_to_multiplier(meterdbs[i]);
61 text = QString("%1").arg(meterdbs[i]);
62 if (i == n) text = "0dB";
63 if (i == 0) {
64 text = "-Inf";
65 val = 0.0;
66 }
67 break;
68
69 case dBScale: // ... min, max
70 val = AudioLevel::dB_to_multiplier(-(10*n) + i * 10);
71 text = QString("%1").arg(-(10*n) + i * 10);
72 if (i == n) text = "0dB";
73 if (i == 0) {
74 text = "-Inf";
75 val = 0.0;
76 }
77 break;
78 }
79
80 if (val < minVal || val > maxVal) continue;
81
82 int y = getYForValue(scale, val, minVal, maxVal, rect.y(), rect.height());
83
84 int ny = y;
85 if (nval != 0.0) {
86 ny = getYForValue(scale, nval, minVal, maxVal, rect.y(), rect.height());
87 }
88
89 bool spaceForLabel = (i == 0 ||
90 abs(y - lastLabelledY) >= textHeight - 1);
91
92 if (spaceForLabel) {
93
94 int tx = 3;
95 if (scale != LinearScale) {
96 tx = w - 10 - paint.fontMetrics().width(text);
97 }
98
99 int ty = y;
100 if (ty < paint.fontMetrics().ascent()) {
101 ty = paint.fontMetrics().ascent();
102 } else if (ty > h - paint.fontMetrics().descent()) {
103 ty = h - paint.fontMetrics().descent();
104 } else {
105 ty += toff;
106 }
107 paint.drawText(tx, ty, text);
108
109 lastLabelledY = ty - toff;
110 /*
111 if (ny != y) {
112 ty = ny;
113 if (ty < paint.fontMetrics().ascent()) {
114 ty = paint.fontMetrics().ascent();
115 } else if (ty > h - paint.fontMetrics().descent()) {
116 ty = h - paint.fontMetrics().descent();
117 } else {
118 ty += toff;
119 }
120 paint.drawText(tx, ty, text);
121 }
122 */
123 paint.drawLine(w - 7, y, w, y);
124 if (vy) vy->push_back(y);
125
126 if (ny != y) {
127 paint.drawLine(w - 7, ny, w, ny);
128 if (vy) vy->push_back(ny);
129 }
130
131 } else {
132
133 paint.drawLine(w - 4, y, w, y);
134 if (vy) vy->push_back(y);
135
136 if (ny != y) {
137 paint.drawLine(w - 4, ny, w, ny);
138 if (vy) vy->push_back(ny);
139 }
140 }
141 }
142 }
143
144 static int
145 dBscale(float sample, int m, float maxVal, float minVal)
146 {
147 if (sample < 0.0) return dBscale(-sample, m, maxVal, minVal);
148 float dB = AudioLevel::multiplier_to_dB(sample);
149 float mindB = AudioLevel::multiplier_to_dB(minVal);
150 float maxdB = AudioLevel::multiplier_to_dB(maxVal);
151 if (dB < mindB) return 0;
152 if (dB > 0.0) return m;
153 return int(((dB - mindB) * m) / (maxdB - mindB) + 0.1);
154 }
155
156 int
157 PaintAssistant::getYForValue(Scale scale, float value,
158 float minVal, float maxVal,
159 int minY, int height)
160 {
161 int vy = 0;
162
163 // int m = height/2;
164 // int my = minY + m;
165
166 switch (scale) {
167
168 case LinearScale:
169 // vy = my - int(m * value);
170 vy = minY + height - int(((value - minVal) / (maxVal - minVal)) * height);
171 break;
172
173 case MeterScale:
174 // vy = my - AudioLevel::multiplier_to_preview(value, m);
175 vy = minY + height - AudioLevel::multiplier_to_preview
176 ((value - minVal) / (maxVal - minVal), height);
177 break;
178
179 case dBScale:
180 vy = minY + height - dBscale(value, height, maxVal, minVal);
181 break;
182 }
183
184 return vy;
185 }