# HG changeset patch # User Chris Cannam # Date 1170094280 0 # Node ID 4a3bdde1ef131b7f1ca8b738e792a3516fc8157f # Parent d13e209bfa947f87cd42a4c50aa346c79af3643e * beginnings of spectrum scales diff -r d13e209bfa94 -r 4a3bdde1ef13 layer/PaintAssistant.cpp --- /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 +#include + +void +PaintAssistant::paintVerticalLevelScale(QPainter &paint, QRect rect, + float minVal, float maxVal, + Scale scale, std::vector *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; +} diff -r d13e209bfa94 -r 4a3bdde1ef13 layer/PaintAssistant.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/PaintAssistant.h Mon Jan 29 18:11:20 2007 +0000 @@ -0,0 +1,39 @@ +/* -*- 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. +*/ + +#ifndef _PAINT_ASSISTANT_H_ +#define _PAINT_ASSISTANT_H_ + +#include +#include + +class QPainter; + +class PaintAssistant +{ +public: + enum Scale { LinearScale, MeterScale, dBScale }; + + static void paintVerticalLevelScale(QPainter &p, QRect rect, + float minVal, float maxVal, + Scale scale, + std::vector *markCoordRtns = 0); + + static int getYForValue(Scale scale, float value, + float minVal, float maxVal, + int minY, int height); +}; + +#endif diff -r d13e209bfa94 -r 4a3bdde1ef13 layer/SliceLayer.cpp --- a/layer/SliceLayer.cpp Fri Jan 26 17:20:58 2007 +0000 +++ b/layer/SliceLayer.cpp Mon Jan 29 18:11:20 2007 +0000 @@ -5,7 +5,7 @@ Sonic Visualiser An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. - This file copyright 2006 QMUL. + This file copyright 2006-2007 QMUL. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -19,6 +19,9 @@ #include "view/View.h" #include "base/AudioLevel.h" #include "base/RangeMapper.h" +#include "base/RealTime.h" + +#include "PaintAssistant.h" #include #include @@ -28,7 +31,7 @@ m_colour(Qt::darkBlue), m_energyScale(dBScale), m_samplingMode(SamplePeak), - m_plotStyle(PlotLines), + m_plotStyle(PlotSteps), m_binScale(LinearBins), m_normalize(false), m_bias(false), @@ -94,15 +97,30 @@ { if (!m_sliceableModel) return; - int w = (v->width() * 2) / 3; - int xorigin = (v->width() / 2) - (w / 2); + paint.save(); + paint.setRenderHint(QPainter::Antialiasing, false); + + if (v->getViewManager() && v->getViewManager()->shouldShowScaleGuides()) { + if (!m_scalePoints.empty()) { + paint.setPen(QColor(240, 240, 240)); //!!! and dark background? + for (size_t i = 0; i < m_scalePoints.size(); ++i) { + paint.drawLine(0, m_scalePoints[i], rect.width(), m_scalePoints[i]); + } + } + } + + paint.setPen(m_colour); + +// int w = (v->width() * 2) / 3; + int xorigin = getVerticalScaleWidth(v, paint) + 1; //!!! (v->width() / 2) - (w / 2); + int w = v->width() - xorigin - 1; - int h = (v->height() * 2) / 3; - int yorigin = (v->height() / 2) + (h / 2); + int yorigin = v->height() - 20 - paint.fontMetrics().height() - 7; + int h = yorigin - paint.fontMetrics().height() - 8; + if (h < 0) return; - paint.save(); - paint.setPen(m_colour); - paint.setRenderHint(QPainter::Antialiasing, false); +// int h = (v->height() * 3) / 4; +// int yorigin = (v->height() / 2) + (h / 2); QPainterPath path; float thresh = -80.f; @@ -118,16 +136,19 @@ size_t f0 = v->getCentreFrame(); int f0x = v->getXForFrame(f0); + f0 = v->getFrameForX(f0x); size_t f1 = v->getFrameForX(f0x + 1); + if (f1 > f0) --f1; size_t col0 = f0 / m_sliceableModel->getResolution(); size_t col1 = col0; if (m_samplingMode != NearestSample) { col1 = f1 / m_sliceableModel->getResolution(); } - if (col1 <= col0) col1 = col0 + 1; + f0 = col0 * m_sliceableModel->getResolution(); + f1 = (col1 + 1) * m_sliceableModel->getResolution() - 1; - for (size_t col = col0; col < col1; ++col) { + for (size_t col = col0; col <= col1; ++col) { for (size_t bin = 0; bin < mh; ++bin) { float value = m_sliceableModel->getValueAt(col, bin); if (m_bias) value *= bin + 1; @@ -236,6 +257,107 @@ paint.drawPath(path); paint.restore(); + if (v->getViewManager() && v->getViewManager()->shouldShowFrameCount()) { + + int sampleRate = m_sliceableModel->getSampleRate(); + + QString startText = QString("%1 / %2") + .arg(QString::fromStdString + (RealTime::frame2RealTime + (f0, sampleRate).toText(true))) + .arg(f0); + + QString endText = QString(" %1 / %2") + .arg(QString::fromStdString + (RealTime::frame2RealTime + (f1, sampleRate).toText(true))) + .arg(f1); + + QString durationText = QString("(%1 / %2) ") + .arg(QString::fromStdString + (RealTime::frame2RealTime + (f1 - f0 + 1, sampleRate).toText(true))) + .arg(f1 - f0 + 1); + + v->drawVisibleText + (paint, xorigin + 5, + paint.fontMetrics().ascent() + 5, + startText, View::OutlinedText); + + v->drawVisibleText + (paint, xorigin + 5, + paint.fontMetrics().ascent() + paint.fontMetrics().height() + 10, + endText, View::OutlinedText); + + v->drawVisibleText + (paint, xorigin + 5, + paint.fontMetrics().ascent() + 2*paint.fontMetrics().height() + 15, + durationText, View::OutlinedText); + } + +/* + + QString frameRange; + if (f1 != f0) { + frameRange = QString("%1 - %2").arg(f0).arg(f1); + } else { + frameRange = QString("%1").arg(f0); + } + + QString colRange; + if (col1 != col0) { + colRange = tr("%1 hops").arg(col1 - col0 + 1); + } else { + colRange = tr("1 hop"); + } + + if (v->getViewManager() && v->getViewManager()->shouldShowFrameCount()) { + + v->drawVisibleText + (paint, xorigin + 5, + paint.fontMetrics().ascent() + 5, + frameRange, View::OutlinedText); + + v->drawVisibleText + (paint, xorigin + 5, + paint.fontMetrics().ascent() + paint.fontMetrics().height() + 10, + colRange, View::OutlinedText); + } +*/ +} + +int +SliceLayer::getVerticalScaleWidth(View *v, QPainter &paint) const +{ + if (m_energyScale == LinearScale) { + return paint.fontMetrics().width("0.0") + 13; + } else { + return std::max(paint.fontMetrics().width(tr("0dB")), + paint.fontMetrics().width(tr("-Inf"))) + 13; + } +} + +void +SliceLayer::paintVerticalScale(View *v, QPainter &paint, QRect rect) const +{ + float thresh = 0; + if (m_energyScale != LinearScale) { + thresh = AudioLevel::dB_to_multiplier(-80); //!!! thresh + } + +// int h = (rect.height() * 3) / 4; +// int y = (rect.height() / 2) - (h / 2); + + int yorigin = v->height() - 20 - paint.fontMetrics().height() - 6; + int h = yorigin - paint.fontMetrics().height() - 8; + if (h < 0) return; + + QRect actual(rect.x(), rect.y() + yorigin - h, rect.width(), h); + + PaintAssistant::paintVerticalLevelScale + (paint, actual, thresh, 1.0 / m_gain, + PaintAssistant::Scale(m_energyScale), + const_cast *>(&m_scalePoints)); } Layer::PropertyList diff -r d13e209bfa94 -r 4a3bdde1ef13 layer/SliceLayer.h --- a/layer/SliceLayer.h Fri Jan 26 17:20:58 2007 +0000 +++ b/layer/SliceLayer.h Mon Jan 29 18:11:20 2007 +0000 @@ -41,6 +41,9 @@ virtual void paint(View *v, QPainter &paint, QRect rect) const; + virtual int getVerticalScaleWidth(View *v, QPainter &) const; + virtual void paintVerticalScale(View *v, QPainter &paint, QRect rect) const; + virtual PropertyList getProperties() const; virtual QString getPropertyLabel(const PropertyName &) const; virtual PropertyType getPropertyType(const PropertyName &) const; @@ -104,6 +107,7 @@ bool m_normalize; bool m_bias; float m_gain; + mutable std::vector m_scalePoints; }; #endif diff -r d13e209bfa94 -r 4a3bdde1ef13 layer/SpectrumLayer.cpp --- a/layer/SpectrumLayer.cpp Fri Jan 26 17:20:58 2007 +0000 +++ b/layer/SpectrumLayer.cpp Mon Jan 29 18:11:20 2007 +0000 @@ -5,7 +5,7 @@ Sonic Visualiser An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. - This file copyright 2006 QMUL. + This file copyright 2006-2007 QMUL. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -34,6 +34,8 @@ connect(prefs, SIGNAL(propertyChanged(PropertyContainer::PropertyName)), this, SLOT(preferenceChanged(PropertyContainer::PropertyName))); setWindowType(prefs->getWindowType()); + + setBinScale(LogBins); } SpectrumLayer::~SpectrumLayer() diff -r d13e209bfa94 -r 4a3bdde1ef13 layer/WaveformLayer.cpp --- a/layer/WaveformLayer.cpp Fri Jan 26 17:20:58 2007 +0000 +++ b/layer/WaveformLayer.cpp Mon Jan 29 18:11:20 2007 +0000 @@ -592,7 +592,9 @@ int n = 10; int py = -1; - if (v->hasLightBackground()) { + if (v->hasLightBackground() && + v->getViewManager() && + v->getViewManager()->shouldShowScaleGuides()) { paint->setPen(QColor(240, 240, 240)); diff -r d13e209bfa94 -r 4a3bdde1ef13 layer/layer.pro --- a/layer/layer.pro Fri Jan 26 17:20:58 2007 +0000 +++ b/layer/layer.pro Mon Jan 29 18:11:20 2007 +0000 @@ -18,6 +18,7 @@ Layer.h \ LayerFactory.h \ NoteLayer.h \ + PaintAssistant.h \ SpectrogramLayer.h \ SpectrumLayer.h \ SliceLayer.h \ @@ -31,6 +32,7 @@ Layer.cpp \ LayerFactory.cpp \ NoteLayer.cpp \ + PaintAssistant.cpp \ SpectrogramLayer.cpp \ SpectrumLayer.cpp \ SliceLayer.cpp \ diff -r d13e209bfa94 -r 4a3bdde1ef13 view/ViewManager.h --- a/view/ViewManager.h Fri Jan 26 17:20:58 2007 +0000 +++ b/view/ViewManager.h Mon Jan 29 18:11:20 2007 +0000 @@ -125,6 +125,9 @@ bool shouldShowLayerNames() const { return m_overlayMode == AllOverlays; } + bool shouldShowScaleGuides() const { + return m_overlayMode != NoOverlays; + } void setZoomWheelsEnabled(bool enable); bool getZoomWheelsEnabled() const { return m_zoomWheelsEnabled; }