# HG changeset patch # User Chris Cannam # Date 1183488459 0 # Node ID a078aa2932cc99a76d26931d129e513bf2e15a1d # Parent 8acd30ed735c0143a0fdcafc8072d17166c168c6 * Fix piano keyboard in spectrum, add pitch labels to frequency displays in measurement rect (clunkily done) and harmonic cursor in spectrum diff -r 8acd30ed735c -r a078aa2932cc layer/SpectrogramLayer.cpp --- a/layer/SpectrogramLayer.cpp Tue Jul 03 12:46:18 2007 +0000 +++ b/layer/SpectrogramLayer.cpp Tue Jul 03 18:47:39 2007 +0000 @@ -2487,7 +2487,13 @@ float fundamental = getFrequencyForY(v, cursorPos.y()); int sw = getVerticalScaleWidth(v, paint); - paint.drawText(sw + 2, cursorPos.y() - 2, QString("%1 Hz").arg(fundamental)); + v->drawVisibleText(paint, + sw + 2, + cursorPos.y() - 2, + QString("%1 Hz").arg(fundamental), + View::OutlinedText); + + //!!! and pitch label int harmonic = 2; diff -r 8acd30ed735c -r a078aa2932cc layer/SpectrumLayer.cpp --- a/layer/SpectrumLayer.cpp Tue Jul 03 12:46:18 2007 +0000 +++ b/layer/SpectrumLayer.cpp Tue Jul 03 18:47:39 2007 +0000 @@ -401,11 +401,22 @@ QRect horizontal(0, cursorPos.y(), v->width(), 12); extents.push_back(horizontal); - QRect label(cursorPos.x(), v->height() - paint.fontMetrics().height(), + int hoffset = 1; + if (m_binScale == LogBins) hoffset = 12; + + QRect label(cursorPos.x(), + v->height() - paint.fontMetrics().height() - hoffset, paint.fontMetrics().width("123456 Hz") + 2, paint.fontMetrics().height()); extents.push_back(label); + int w(paint.fontMetrics().width("C#10+50c") + 2); + QRect pitch(cursorPos.x() - w, + v->height() - paint.fontMetrics().height() - hoffset, + w, + paint.fontMetrics().height()); + extents.push_back(pitch); + return true; } @@ -426,8 +437,23 @@ float fundamental = getFrequencyForX(cursorPos.x() - xorigin, w); - paint.drawText(cursorPos.x() + 2, v->height() - 2, - QString("%1 Hz").arg(fundamental)); + int hoffset = 1; + if (m_binScale == LogBins) hoffset = 12; + + v->drawVisibleText(paint, + cursorPos.x() + 2, + v->height() - 2 - hoffset, + QString("%1 Hz").arg(fundamental), + View::OutlinedText); + + if (Pitch::isFrequencyInMidiRange(fundamental)) { + QString pitchLabel = Pitch::getPitchLabelForFrequency(fundamental); + v->drawVisibleText(paint, + cursorPos.x() - paint.fontMetrics().width(pitchLabel) - 2, + v->height() - 2 - hoffset, + pitchLabel, + View::OutlinedText); + } int harmonic = 2; @@ -567,6 +593,9 @@ int xorigin = getVerticalScaleWidth(v, paint) + 1; int w = v->width() - xorigin - 1; + int pkh = 0; + if (m_binScale == LogBins) pkh = 10; + if (fft) { // draw peak lines @@ -601,7 +630,7 @@ float y = getYForValue(value, v, norm); // don't need y, need norm paint.setPen(mapper.map(norm)); - paint.drawLine(xorigin + x, 0, xorigin + x, v->height()); + paint.drawLine(xorigin + x, 0, xorigin + x, v->height() - pkh - 1); } paint.restore(); @@ -609,6 +638,15 @@ SliceLayer::paint(v, paint, rect); + //!!! All of this stuff relating to depicting frequencies + //(keyboard, crosshairs etc) should be applicable to any slice + //layer whose model has a vertical scale unit of Hz. However, the + //dense 3d model at the moment doesn't record its vertical scale + //unit -- we need to fix that and hoist this code as appropriate. + //Same really goes for any code in SpectrogramLayer that could be + //relevant to Colour3DPlotLayer with unit Hz, but that's a bigger + //proposition. + if (m_binScale == LogBins) { int pkh = 10; @@ -616,32 +654,45 @@ // piano keyboard //!!! should be in a new paintHorizontalScale()? + // nice to have a piano keyboard class, of course - paint.drawLine(xorigin, h - pkh - 1, w, h - pkh - 1); + paint.drawLine(xorigin, h - pkh - 1, w + xorigin, h - pkh - 1); int px = xorigin, ppx = xorigin; -// paint.setBrush(paint.pen().color()); + paint.setBrush(paint.pen().color()); for (int i = 0; i < 128; ++i) { float f = Pitch::getFrequencyForPitch(i); int x = lrintf(getXForFrequency(f, w)); + + x += xorigin; - if (x < 0) break; - if (x + xorigin > w) { + if (i == 0) { + px = ppx = x; + } + if (i == 1) { + ppx = px - (x - px); + } + + if (x < xorigin) { + ppx = px; + px = x; continue; } - - x += xorigin; + + if (x > w) { + break; + } int n = (i % 12); if (n == 1) { // C# -- fill the C from here if (x - ppx > 2) { - paint.fillRect(x, + paint.fillRect((px + ppx) / 2 + 1, h - pkh, - x - (px + ppx) / 2, + x - (px + ppx) / 2 - 1, pkh, Qt::gray); } @@ -650,9 +701,9 @@ if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) { // black notes paint.drawLine(x, h - pkh, x, h); - int rw = ((px - x) / 4) * 2; + int rw = lrintf(float(x - px) / 4) * 2; if (rw < 2) rw = 2; - paint.drawRect(x - (px-x)/4, h - pkh, rw, pkh/2); + paint.drawRect(x - rw/2, h - pkh, rw, pkh/2); } else if (n == 0 || n == 5) { // C, F if (px < w) { diff -r 8acd30ed735c -r a078aa2932cc view/View.cpp --- a/view/View.cpp Tue Jul 03 12:46:18 2007 +0000 +++ b/view/View.cpp Tue Jul 03 18:47:39 2007 +0000 @@ -18,6 +18,7 @@ #include "data/model/Model.h" #include "base/ZoomConstraint.h" #include "base/Profiler.h" +#include "base/Pitch.h" #include "layer/TimeRulerLayer.h" //!!! damn, shouldn't be including that here #include "data/model/PowerOfSqrtTwoZoomConstraint.h" //!!! likewise @@ -1679,6 +1680,13 @@ if (!focus) return; + paint.save(); + QFont fn = paint.font(); + if (fn.pointSize() > 8) { + fn.setPointSize(fn.pointSize() - 1); + paint.setFont(fn); + } + int fontHeight = paint.fontMetrics().height(); int fontAscent = paint.fontMetrics().ascent(); @@ -1695,6 +1703,10 @@ if ((b0 = topLayer->getXScaleValue(this, r.x(), v0, u0))) { axs = QString("%1 %2").arg(v0).arg(u0); + if (u0 == "Hz" && Pitch::isFrequencyInMidiRange(v0)) { + axs = QString("%1 (%2)").arg(axs) + .arg(Pitch::getPitchLabelForFrequency(v0)); + } aw = paint.fontMetrics().width(axs); ++labelCount; } @@ -1702,6 +1714,10 @@ if (r.width() > 0) { if ((b1 = topLayer->getXScaleValue(this, r.x() + r.width(), v1, u1))) { bxs = QString("%1 %2").arg(v1).arg(u1); + if (u1 == "Hz" && Pitch::isFrequencyInMidiRange(v1)) { + bxs = QString("%1 (%2)").arg(bxs) + .arg(Pitch::getPitchLabelForFrequency(v1)); + } bw = paint.fontMetrics().width(bxs); } } @@ -1716,6 +1732,10 @@ if ((b0 = topLayer->getYScaleValue(this, r.y(), v0, u0))) { ays = QString("%1 %2").arg(v0).arg(u0); + if (u0 == "Hz" && Pitch::isFrequencyInMidiRange(v0)) { + ays = QString("%1 (%2)").arg(ays) + .arg(Pitch::getPitchLabelForFrequency(v0)); + } aw = std::max(aw, paint.fontMetrics().width(ays)); ++labelCount; } @@ -1723,6 +1743,10 @@ if (r.height() > 0) { if ((b1 = topLayer->getYScaleValue(this, r.y() + r.height(), v1, u1))) { bys = QString("%1 %2").arg(v1).arg(u1); + if (u1 == "Hz" && Pitch::isFrequencyInMidiRange(v1)) { + bys = QString("%1 (%2)").arg(bys) + .arg(Pitch::getPitchLabelForFrequency(v1)); + } bw = std::max(bw, paint.fontMetrics().width(bys)); } } @@ -1827,6 +1851,8 @@ drawVisibleText(paint, dxx, dxy, dys, OutlinedText); dxy += fontHeight; } + + paint.restore(); } bool