Mercurial > hg > svgui
diff layer/PaintAssistant.cpp @ 195:4a3bdde1ef13
* beginnings of spectrum scales
author | Chris Cannam |
---|---|
date | Mon, 29 Jan 2007 18:11:20 +0000 |
parents | |
children | c2ed5014d4ff |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/PaintAssistant.cpp Mon Jan 29 18:11:20 2007 +0000 @@ -0,0 +1,185 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2007 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "PaintAssistant.h" + +#include "base/AudioLevel.h" + +#include <QPaintDevice> +#include <QPainter> + +void +PaintAssistant::paintVerticalLevelScale(QPainter &paint, QRect rect, + float minVal, float maxVal, + Scale scale, std::vector<int> *vy) +{ + static float meterdbs[] = { -40, -30, -20, -15, -10, + -5, -3, -2, -1, -0.5, 0 }; + + int h = rect.height(), w = rect.width(); + int textHeight = paint.fontMetrics().height(); + int toff = -textHeight/2 + paint.fontMetrics().ascent() + 1; + + int lastLabelledY = -1; + + int n = 10; + if (vy) vy->clear(); + + for (int i = 0; i <= n; ++i) { + + float val = 0.0, nval = 0.0; + QString text = ""; + + switch (scale) { + + case LinearScale: + val = minVal + ((maxVal - minVal) * i) / n; + text = QString("%1").arg(val);//float(i) / n); // ... val +/* + if (i == 0) text = "0.0"; + else { + nval = -val; + if (i == n) text = "1.0"; + } +*/ + break; + + case MeterScale: // ... min, max + val = AudioLevel::dB_to_multiplier(meterdbs[i]); + text = QString("%1").arg(meterdbs[i]); + if (i == n) text = "0dB"; + if (i == 0) { + text = "-Inf"; + val = 0.0; + } + break; + + case dBScale: // ... min, max + val = AudioLevel::dB_to_multiplier(-(10*n) + i * 10); + text = QString("%1").arg(-(10*n) + i * 10); + if (i == n) text = "0dB"; + if (i == 0) { + text = "-Inf"; + val = 0.0; + } + break; + } + + if (val < minVal || val > maxVal) continue; + + int y = getYForValue(scale, val, minVal, maxVal, rect.y(), rect.height()); + + int ny = y; + if (nval != 0.0) { + ny = getYForValue(scale, nval, minVal, maxVal, rect.y(), rect.height()); + } + + bool spaceForLabel = (i == 0 || + abs(y - lastLabelledY) >= textHeight - 1); + + if (spaceForLabel) { + + int tx = 3; + if (scale != LinearScale) { + tx = w - 10 - paint.fontMetrics().width(text); + } + + int ty = y; + if (ty < paint.fontMetrics().ascent()) { + ty = paint.fontMetrics().ascent(); + } else if (ty > h - paint.fontMetrics().descent()) { + ty = h - paint.fontMetrics().descent(); + } else { + ty += toff; + } + paint.drawText(tx, ty, text); + + lastLabelledY = ty - toff; + /* + if (ny != y) { + ty = ny; + if (ty < paint.fontMetrics().ascent()) { + ty = paint.fontMetrics().ascent(); + } else if (ty > h - paint.fontMetrics().descent()) { + ty = h - paint.fontMetrics().descent(); + } else { + ty += toff; + } + paint.drawText(tx, ty, text); + } + */ + paint.drawLine(w - 7, y, w, y); + if (vy) vy->push_back(y); + + if (ny != y) { + paint.drawLine(w - 7, ny, w, ny); + if (vy) vy->push_back(ny); + } + + } else { + + paint.drawLine(w - 4, y, w, y); + if (vy) vy->push_back(y); + + if (ny != y) { + paint.drawLine(w - 4, ny, w, ny); + if (vy) vy->push_back(ny); + } + } + } +} + +static int +dBscale(float sample, int m, float maxVal, float minVal) +{ + if (sample < 0.0) return dBscale(-sample, m, maxVal, minVal); + float dB = AudioLevel::multiplier_to_dB(sample); + float mindB = AudioLevel::multiplier_to_dB(minVal); + float maxdB = AudioLevel::multiplier_to_dB(maxVal); + if (dB < mindB) return 0; + if (dB > 0.0) return m; + return int(((dB - mindB) * m) / (maxdB - mindB) + 0.1); +} + +int +PaintAssistant::getYForValue(Scale scale, float value, + float minVal, float maxVal, + int minY, int height) +{ + int vy = 0; + +// int m = height/2; +// int my = minY + m; + + switch (scale) { + + case LinearScale: +// vy = my - int(m * value); + vy = minY + height - int(((value - minVal) / (maxVal - minVal)) * height); + break; + + case MeterScale: +// vy = my - AudioLevel::multiplier_to_preview(value, m); + vy = minY + height - AudioLevel::multiplier_to_preview + ((value - minVal) / (maxVal - minVal), height); + break; + + case dBScale: + vy = minY + height - dBscale(value, height, maxVal, minVal); + break; + } + + return vy; +}