Mercurial > hg > svgui
changeset 254:a2ae3d93c645
* bit of work on harmonic cursor in spectrum
author | Chris Cannam |
---|---|
date | Mon, 11 Jun 2007 12:14:52 +0000 |
parents | 1b1e6947c124 |
children | e175ade2d6b0 |
files | layer/SliceLayer.cpp layer/SliceLayer.h layer/SpectrumLayer.cpp layer/SpectrumLayer.h |
diffstat | 4 files changed, 152 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/layer/SliceLayer.cpp Fri Jun 08 15:19:50 2007 +0000 +++ b/layer/SliceLayer.cpp Mon Jun 11 12:14:52 2007 +0000 @@ -36,7 +36,6 @@ m_plotStyle(PlotSteps), m_binScale(LinearBins), m_normalize(false), - m_bias(false), m_gain(1.0), m_currentf0(0), m_currentf1(0) @@ -229,7 +228,8 @@ void SliceLayer::paint(View *v, QPainter &paint, QRect rect) const { - if (!m_sliceableModel) return; + if (!m_sliceableModel || !m_sliceableModel->isOK() || + !m_sliceableModel->isReady()) return; paint.save(); paint.setRenderHint(QPainter::Antialiasing, false); @@ -287,10 +287,14 @@ m_currentf0 = f0; m_currentf1 = f1; + BiasCurve curve; + getBiasCurve(curve); + size_t cs = curve.size(); + 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; + if (bin < cs) value *= curve[bin]; if (m_samplingMode == SamplePeak) { if (value > m_values[bin]) m_values[bin] = value; } else {
--- a/layer/SliceLayer.h Fri Jun 08 15:19:50 2007 +0000 +++ b/layer/SliceLayer.h Mon Jun 11 12:14:52 2007 +0000 @@ -113,6 +113,12 @@ int &minbin, int &maxbin, int &range) const; + // This curve may, of course, be flat -- the spectrum uses it for + // normalizing the fft results by the fft size (with 1/(fftsize/2) + // in each bin). + typedef std::vector<float> BiasCurve; + virtual void getBiasCurve(BiasCurve &) const { return; } + const DenseThreeDimensionalModel *m_sliceableModel; QColor m_colour; int m_colourMap; @@ -121,7 +127,6 @@ PlotStyle m_plotStyle; BinScale m_binScale; bool m_normalize; - bool m_bias; float m_gain; mutable std::vector<int> m_scalePoints; mutable std::map<View *, int> m_xorigins;
--- a/layer/SpectrumLayer.cpp Fri Jun 08 15:19:50 2007 +0000 +++ b/layer/SpectrumLayer.cpp Mon Jun 11 12:14:52 2007 +0000 @@ -21,6 +21,9 @@ #include "base/AudioLevel.h" #include "base/Preferences.h" #include "base/RangeMapper.h" +#include "ColourMapper.h" + +#include <QPainter> SpectrumLayer::SpectrumLayer() : m_originModel(0), @@ -73,6 +76,11 @@ setSliceableModel(newFFT); + m_biasCurve.clear(); + for (size_t i = 0; i < m_windowSize; ++i) { + m_biasCurve.push_back(1.f / (float(m_windowSize)/2.f)); + } + newFFT->resume(); } @@ -143,7 +151,7 @@ if (name == "Window Size") { *min = 0; - *max = 10; + *max = 15; *deflt = 5; val = 0; @@ -247,6 +255,121 @@ return false; } +bool +SpectrumLayer::getCrosshairExtents(View *v, QPainter &, + QPoint cursorPos, + std::vector<QRect> &extents) const +{ + QRect vertical(cursorPos.x(), cursorPos.y(), 1, v->height() - cursorPos.y()); + extents.push_back(vertical); + + QRect horizontal(0, cursorPos.y(), v->width(), 12); + extents.push_back(horizontal); + + return true; +} + +float +SpectrumLayer::getFrequencyForX(float x, float w) const +{ + float freq = 0; + + int sampleRate = m_sliceableModel->getSampleRate(); + + float maxfreq = float(sampleRate) / 2; + + switch (m_binScale) { + + case LinearBins: + freq = ((x * maxfreq) / w); + break; + + case LogBins: + freq = powf(10.f, (x * log10f(maxfreq)) / w); + break; + + case InvertedLogBins: + freq = maxfreq - powf(10.f, ((w - x) * log10f(maxfreq)) / w); + break; + } + + return freq; +} + +float +SpectrumLayer::getXForFrequency(float freq, float w) const +{ + float x = 0; + + int sampleRate = m_sliceableModel->getSampleRate(); + + float maxfreq = float(sampleRate) / 2; + + switch (m_binScale) { + + case LinearBins: + x = (freq * w) / maxfreq; + break; + + case LogBins: + x = (log10f(freq) * w) / log10f(maxfreq); + break; + + case InvertedLogBins: + x = (w - log10f(maxfreq - freq) * w) / log10f(maxfreq); + break; + } + + return x; +} + +void +SpectrumLayer::paintCrosshairs(View *v, QPainter &paint, + QPoint cursorPos) const +{ + paint.save(); + + ColourMapper mapper(m_colourMap, 0, 1); + paint.setPen(mapper.getContrastingColour()); + + int xorigin = m_xorigins[v]; + int w = v->width() - xorigin - 1; + + paint.drawLine(xorigin, cursorPos.y(), v->width(), cursorPos.y()); + paint.drawLine(cursorPos.x(), cursorPos.y(), cursorPos.x(), v->height()); + + float fundamental = getFrequencyForX(cursorPos.x() - xorigin, w); + + int harmonic = 2; + + while (harmonic < 100) { + + float hx = lrintf(getXForFrequency(fundamental * harmonic, w)); + hx += xorigin; + + if (hx < xorigin || hx > v->width()) break; + + int len = 7; + + if (harmonic % 2 == 0) { + if (harmonic % 4 == 0) { + len = 12; + } else { + len = 10; + } + } + + paint.drawLine(int(hx), + cursorPos.y(), + int(hx), + cursorPos.y() + len); + + ++harmonic; + } + + paint.restore(); +} + QString SpectrumLayer::getFeatureDescription(View *v, QPoint &p) const { @@ -336,6 +459,11 @@ return description; } +void +SpectrumLayer::getBiasCurve(BiasCurve &curve) const +{ + curve = m_biasCurve; +} QString SpectrumLayer::toXmlString(QString indent, QString extraAttributes) const
--- a/layer/SpectrumLayer.h Fri Jun 08 15:19:50 2007 +0000 +++ b/layer/SpectrumLayer.h Mon Jun 11 12:14:52 2007 +0000 @@ -38,6 +38,10 @@ void setModel(DenseTimeValueModel *model); virtual const Model *getModel() const { return m_originModel; } + virtual bool getCrosshairExtents(View *, QPainter &, QPoint cursorPos, + std::vector<QRect> &extents) const; + virtual void paintCrosshairs(View *, QPainter &, QPoint) const; + virtual QString getFeatureDescription(View *v, QPoint &) const; virtual PropertyList getProperties() const; @@ -90,6 +94,12 @@ void setupFFT(); + virtual void getBiasCurve(BiasCurve &) const; + BiasCurve m_biasCurve; + + float getFrequencyForX(float x, float w) const; + float getXForFrequency(float freq, float w) const; + size_t getWindowIncrement() const { if (m_windowHopLevel == 0) return m_windowSize; else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4;