Chris@195
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@195
|
2
|
Chris@195
|
3 /*
|
Chris@195
|
4 Sonic Visualiser
|
Chris@195
|
5 An audio file viewer and annotation editor.
|
Chris@195
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@195
|
7 This file copyright 2006-2007 Chris Cannam and QMUL.
|
Chris@195
|
8
|
Chris@195
|
9 This program is free software; you can redistribute it and/or
|
Chris@195
|
10 modify it under the terms of the GNU General Public License as
|
Chris@195
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@195
|
12 License, or (at your option) any later version. See the file
|
Chris@195
|
13 COPYING included with this distribution for more information.
|
Chris@195
|
14 */
|
Chris@195
|
15
|
Chris@195
|
16 #include "PaintAssistant.h"
|
Chris@195
|
17
|
Chris@195
|
18 #include "base/AudioLevel.h"
|
Chris@195
|
19
|
Chris@195
|
20 #include <QPaintDevice>
|
Chris@195
|
21 #include <QPainter>
|
Chris@195
|
22
|
Chris@198
|
23 #include <iostream>
|
Chris@198
|
24
|
Chris@195
|
25 void
|
Chris@195
|
26 PaintAssistant::paintVerticalLevelScale(QPainter &paint, QRect rect,
|
Chris@195
|
27 float minVal, float maxVal,
|
Chris@195
|
28 Scale scale, std::vector<int> *vy)
|
Chris@195
|
29 {
|
Chris@195
|
30 static float meterdbs[] = { -40, -30, -20, -15, -10,
|
Chris@195
|
31 -5, -3, -2, -1, -0.5, 0 };
|
Chris@195
|
32
|
Chris@195
|
33 int h = rect.height(), w = rect.width();
|
Chris@195
|
34 int textHeight = paint.fontMetrics().height();
|
Chris@195
|
35 int toff = -textHeight/2 + paint.fontMetrics().ascent() + 1;
|
Chris@195
|
36
|
Chris@195
|
37 int lastLabelledY = -1;
|
Chris@195
|
38
|
Chris@195
|
39 int n = 10;
|
Chris@195
|
40 if (vy) vy->clear();
|
Chris@195
|
41
|
Chris@195
|
42 for (int i = 0; i <= n; ++i) {
|
Chris@195
|
43
|
Chris@195
|
44 float val = 0.0, nval = 0.0;
|
Chris@195
|
45 QString text = "";
|
Chris@195
|
46
|
Chris@195
|
47 switch (scale) {
|
Chris@195
|
48
|
Chris@195
|
49 case LinearScale:
|
Chris@195
|
50 val = minVal + ((maxVal - minVal) * i) / n;
|
Chris@195
|
51 text = QString("%1").arg(val);//float(i) / n); // ... val
|
Chris@195
|
52 /*
|
Chris@195
|
53 if (i == 0) text = "0.0";
|
Chris@195
|
54 else {
|
Chris@195
|
55 nval = -val;
|
Chris@195
|
56 if (i == n) text = "1.0";
|
Chris@195
|
57 }
|
Chris@195
|
58 */
|
Chris@195
|
59 break;
|
Chris@195
|
60
|
Chris@195
|
61 case MeterScale: // ... min, max
|
Chris@195
|
62 val = AudioLevel::dB_to_multiplier(meterdbs[i]);
|
Chris@195
|
63 text = QString("%1").arg(meterdbs[i]);
|
Chris@195
|
64 if (i == n) text = "0dB";
|
Chris@195
|
65 if (i == 0) {
|
Chris@195
|
66 text = "-Inf";
|
Chris@195
|
67 val = 0.0;
|
Chris@195
|
68 }
|
Chris@195
|
69 break;
|
Chris@195
|
70
|
Chris@195
|
71 case dBScale: // ... min, max
|
Chris@195
|
72 val = AudioLevel::dB_to_multiplier(-(10*n) + i * 10);
|
Chris@195
|
73 text = QString("%1").arg(-(10*n) + i * 10);
|
Chris@195
|
74 if (i == n) text = "0dB";
|
Chris@195
|
75 if (i == 0) {
|
Chris@195
|
76 text = "-Inf";
|
Chris@195
|
77 val = 0.0;
|
Chris@195
|
78 }
|
Chris@195
|
79 break;
|
Chris@195
|
80 }
|
Chris@195
|
81
|
Chris@195
|
82 if (val < minVal || val > maxVal) continue;
|
Chris@195
|
83
|
Chris@198
|
84 int y = getYForValue(scale, val, minVal, maxVal, rect.y(), h);
|
Chris@195
|
85
|
Chris@195
|
86 int ny = y;
|
Chris@195
|
87 if (nval != 0.0) {
|
Chris@198
|
88 ny = getYForValue(scale, nval, minVal, maxVal, rect.y(), h);
|
Chris@195
|
89 }
|
Chris@195
|
90
|
Chris@198
|
91 // std::cerr << "PaintAssistant::paintVerticalLevelScale: val = "
|
Chris@198
|
92 // << val << ", y = " << y << ", h = " << h << std::endl;
|
Chris@198
|
93
|
Chris@195
|
94 bool spaceForLabel = (i == 0 ||
|
Chris@195
|
95 abs(y - lastLabelledY) >= textHeight - 1);
|
Chris@195
|
96
|
Chris@195
|
97 if (spaceForLabel) {
|
Chris@195
|
98
|
Chris@195
|
99 int tx = 3;
|
Chris@195
|
100 if (scale != LinearScale) {
|
Chris@195
|
101 tx = w - 10 - paint.fontMetrics().width(text);
|
Chris@195
|
102 }
|
Chris@195
|
103
|
Chris@195
|
104 int ty = y;
|
Chris@198
|
105
|
Chris@195
|
106 if (ty < paint.fontMetrics().ascent()) {
|
Chris@195
|
107 ty = paint.fontMetrics().ascent();
|
Chris@198
|
108 // } else if (ty > rect.y() + h - paint.fontMetrics().descent()) {
|
Chris@198
|
109 // ty = rect.y() + h - paint.fontMetrics().descent();
|
Chris@195
|
110 } else {
|
Chris@195
|
111 ty += toff;
|
Chris@195
|
112 }
|
Chris@198
|
113
|
Chris@195
|
114 paint.drawText(tx, ty, text);
|
Chris@195
|
115
|
Chris@195
|
116 lastLabelledY = ty - toff;
|
Chris@195
|
117 /*
|
Chris@195
|
118 if (ny != y) {
|
Chris@195
|
119 ty = ny;
|
Chris@195
|
120 if (ty < paint.fontMetrics().ascent()) {
|
Chris@195
|
121 ty = paint.fontMetrics().ascent();
|
Chris@195
|
122 } else if (ty > h - paint.fontMetrics().descent()) {
|
Chris@195
|
123 ty = h - paint.fontMetrics().descent();
|
Chris@195
|
124 } else {
|
Chris@195
|
125 ty += toff;
|
Chris@195
|
126 }
|
Chris@195
|
127 paint.drawText(tx, ty, text);
|
Chris@195
|
128 }
|
Chris@195
|
129 */
|
Chris@195
|
130 paint.drawLine(w - 7, y, w, y);
|
Chris@195
|
131 if (vy) vy->push_back(y);
|
Chris@195
|
132
|
Chris@195
|
133 if (ny != y) {
|
Chris@195
|
134 paint.drawLine(w - 7, ny, w, ny);
|
Chris@195
|
135 if (vy) vy->push_back(ny);
|
Chris@195
|
136 }
|
Chris@195
|
137
|
Chris@195
|
138 } else {
|
Chris@195
|
139
|
Chris@195
|
140 paint.drawLine(w - 4, y, w, y);
|
Chris@195
|
141 if (vy) vy->push_back(y);
|
Chris@195
|
142
|
Chris@195
|
143 if (ny != y) {
|
Chris@195
|
144 paint.drawLine(w - 4, ny, w, ny);
|
Chris@195
|
145 if (vy) vy->push_back(ny);
|
Chris@195
|
146 }
|
Chris@195
|
147 }
|
Chris@195
|
148 }
|
Chris@195
|
149 }
|
Chris@195
|
150
|
Chris@195
|
151 static int
|
Chris@195
|
152 dBscale(float sample, int m, float maxVal, float minVal)
|
Chris@195
|
153 {
|
Chris@195
|
154 if (sample < 0.0) return dBscale(-sample, m, maxVal, minVal);
|
Chris@195
|
155 float dB = AudioLevel::multiplier_to_dB(sample);
|
Chris@195
|
156 float mindB = AudioLevel::multiplier_to_dB(minVal);
|
Chris@195
|
157 float maxdB = AudioLevel::multiplier_to_dB(maxVal);
|
Chris@195
|
158 if (dB < mindB) return 0;
|
Chris@195
|
159 if (dB > 0.0) return m;
|
Chris@195
|
160 return int(((dB - mindB) * m) / (maxdB - mindB) + 0.1);
|
Chris@195
|
161 }
|
Chris@195
|
162
|
Chris@195
|
163 int
|
Chris@195
|
164 PaintAssistant::getYForValue(Scale scale, float value,
|
Chris@195
|
165 float minVal, float maxVal,
|
Chris@195
|
166 int minY, int height)
|
Chris@195
|
167 {
|
Chris@195
|
168 int vy = 0;
|
Chris@195
|
169
|
Chris@195
|
170 // int m = height/2;
|
Chris@195
|
171 // int my = minY + m;
|
Chris@195
|
172
|
Chris@195
|
173 switch (scale) {
|
Chris@195
|
174
|
Chris@195
|
175 case LinearScale:
|
Chris@195
|
176 // vy = my - int(m * value);
|
Chris@195
|
177 vy = minY + height - int(((value - minVal) / (maxVal - minVal)) * height);
|
Chris@195
|
178 break;
|
Chris@195
|
179
|
Chris@195
|
180 case MeterScale:
|
Chris@195
|
181 // vy = my - AudioLevel::multiplier_to_preview(value, m);
|
Chris@195
|
182 vy = minY + height - AudioLevel::multiplier_to_preview
|
Chris@195
|
183 ((value - minVal) / (maxVal - minVal), height);
|
Chris@195
|
184 break;
|
Chris@195
|
185
|
Chris@195
|
186 case dBScale:
|
Chris@195
|
187 vy = minY + height - dBscale(value, height, maxVal, minVal);
|
Chris@195
|
188 break;
|
Chris@195
|
189 }
|
Chris@195
|
190
|
Chris@195
|
191 return vy;
|
Chris@195
|
192 }
|