Mercurial > hg > svgui
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 } |