Mercurial > hg > svgui
diff layer/SpectrumLayer.cpp @ 278:a078aa2932cc
* Fix piano keyboard in spectrum, add pitch labels to frequency displays in
measurement rect (clunkily done) and harmonic cursor in spectrum
author | Chris Cannam |
---|---|
date | Tue, 03 Jul 2007 18:47:39 +0000 |
parents | 8acd30ed735c |
children | 3c402c6052f6 |
line wrap: on
line diff
--- 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) {