annotate layer/PaintAssistant.cpp @ 282:d9319859a4cf tip

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