Mercurial > hg > svgui
diff layer/SpectrumLayer.cpp @ 280:3c402c6052f6
* Pull peak-picker out of SpectrumLayer and into FFTModel; use combined
peak-picker and frequency estimator for SpectrogramLayer (makes the
peak frequency spectrogram a bit quicker)
* Add more information to spectrum and spectrogram crosshairs
author | Chris Cannam |
---|---|
date | Wed, 04 Jul 2007 15:29:16 +0000 |
parents | a078aa2932cc |
children | 4edaff85875d |
line wrap: on
line diff
--- a/layer/SpectrumLayer.cpp Tue Jul 03 18:56:27 2007 +0000 +++ b/layer/SpectrumLayer.cpp Wed Jul 04 15:29:16 2007 +0000 @@ -1,4 +1,3 @@ - /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* @@ -294,6 +293,7 @@ SpectrumLayer::getFrequencyForX(float x, float w) const { float freq = 0; + if (!m_sliceableModel) return 0; int sampleRate = m_sliceableModel->getSampleRate(); @@ -321,6 +321,7 @@ SpectrumLayer::getXForFrequency(float freq, float w) const { float x = 0; + if (!m_sliceableModel) return x; int sampleRate = m_sliceableModel->getSampleRate(); @@ -401,14 +402,26 @@ QRect horizontal(0, cursorPos.y(), v->width(), 12); extents.push_back(horizontal); - int hoffset = 1; - if (m_binScale == LogBins) hoffset = 12; + int hoffset = 2; + if (m_binScale == LogBins) hoffset = 13; - QRect label(cursorPos.x(), - v->height() - paint.fontMetrics().height() - hoffset, - paint.fontMetrics().width("123456 Hz") + 2, + int sw = getVerticalScaleWidth(v, paint); + + QRect value(sw, cursorPos.y() - paint.fontMetrics().ascent() - 2, + paint.fontMetrics().width("0.0000001 V") + 2, paint.fontMetrics().height()); - extents.push_back(label); + extents.push_back(value); + + QRect log(sw, cursorPos.y() + 2, + paint.fontMetrics().width("-80.000 dBV") + 2, + paint.fontMetrics().height()); + extents.push_back(log); + + QRect freq(cursorPos.x(), + v->height() - paint.fontMetrics().height() - hoffset, + paint.fontMetrics().width("123456 Hz") + 2, + paint.fontMetrics().height()); + extents.push_back(freq); int w(paint.fontMetrics().width("C#10+50c") + 2); QRect pitch(cursorPos.x() - w, @@ -424,6 +437,8 @@ SpectrumLayer::paintCrosshairs(View *v, QPainter &paint, QPoint cursorPos) const { + if (!m_sliceableModel) return; + paint.save(); ColourMapper mapper(m_colourMap, 0, 1); @@ -437,8 +452,8 @@ float fundamental = getFrequencyForX(cursorPos.x() - xorigin, w); - int hoffset = 1; - if (m_binScale == LogBins) hoffset = 12; + int hoffset = 2; + if (m_binScale == LogBins) hoffset = 13; v->drawVisibleText(paint, cursorPos.x() + 2, @@ -455,6 +470,24 @@ View::OutlinedText); } + float value = getValueForY(cursorPos.y(), v); + float thresh = -80.f; + float db = thresh; + if (value > 0.f) db = 10.f * log10f(value); + if (db < thresh) db = thresh; + + v->drawVisibleText(paint, + xorigin + 2, + cursorPos.y() - 2, + QString("%1 V").arg(value), + View::OutlinedText); + + v->drawVisibleText(paint, + xorigin + 2, + cursorPos.y() + 2 + paint.fontMetrics().ascent(), + QString("%1 dBV").arg(db), + View::OutlinedText); + int harmonic = 2; while (harmonic < 100) { @@ -588,7 +621,7 @@ FFTModel *fft = dynamic_cast<FFTModel *> (const_cast<DenseThreeDimensionalModel *>(m_sliceableModel)); - float thresh = powf(10, -8) / m_gain; // -80dB + float thresh = (powf(10, -6) / m_gain) * (m_windowSize / 2.f); // -60dB adj int xorigin = getVerticalScaleWidth(v, paint) + 1; int w = v->width() - xorigin - 1; @@ -607,27 +640,38 @@ paint.setRenderHint(QPainter::Antialiasing, false); paint.setPen(QColor(160, 160, 160)); //!!! - ColourMapper mapper(m_colourMap, 0, 1); + FFTModel::PeakSet peaks = fft->getPeakFrequencies + (FFTModel::MajorPitchAdaptivePeaks, col); + + ColourMapper mapper(ColourMapper::BlackOnWhite, 0, 1); BiasCurve curve; getBiasCurve(curve); size_t cs = curve.size(); + + std::vector<float> values; for (size_t bin = 0; bin < fft->getHeight(); ++bin) { + float value = m_sliceableModel->getValueAt(col, bin); + if (bin < cs) value *= curve[bin]; + values.push_back(value); + } + + for (FFTModel::PeakSet::iterator i = peaks.begin(); + i != peaks.end(); ++i) { + + size_t bin = i->first; - if (!fft->isLocalPeak(col, bin)) continue; +// std::cerr << "bin = " << bin << ", thresh = " << thresh << ", value = " << fft->getMagnitudeAt(col, bin) << std::endl; + if (!fft->isOverThreshold(col, bin, thresh)) continue; - float freq = 0; - bool haveFreq = fft->estimateStableFrequency(col, bin, freq); - if (!haveFreq) continue; - + float freq = i->second; + int x = lrintf(getXForFrequency(freq, w)); - float value = m_sliceableModel->getValueAt(col, bin); - if (bin < cs) value *= curve[bin]; float norm = 0.f; - float y = getYForValue(value, v, norm); // don't need y, need norm + float y = getYForValue(values[bin], v, norm); // don't need y, need norm paint.setPen(mapper.map(norm)); paint.drawLine(xorigin + x, 0, xorigin + x, v->height() - pkh - 1);