comparison layer/SpectrogramLayer.cpp @ 120:8dfa20f1c70a

* some work on scaling and zooming for spectrogram
author Chris Cannam
date Wed, 19 Jul 2006 16:55:29 +0000
parents 508276c923ba
children 7363cacf7de0
comparison
equal deleted inserted replaced
119:508276c923ba 120:8dfa20f1c70a
54 m_colourScale(dBColourScale), 54 m_colourScale(dBColourScale),
55 m_colourScheme(DefaultColours), 55 m_colourScheme(DefaultColours),
56 m_frequencyScale(LinearFrequencyScale), 56 m_frequencyScale(LinearFrequencyScale),
57 m_binDisplay(AllBins), 57 m_binDisplay(AllBins),
58 m_normalizeColumns(false), 58 m_normalizeColumns(false),
59 m_normalizeVisibleArea(false),
59 m_updateTimer(0), 60 m_updateTimer(0),
60 m_candidateFillStartFrame(0), 61 m_candidateFillStartFrame(0),
61 m_exiting(false) 62 m_exiting(false)
62 { 63 {
63 if (config == MelodicRange) { 64 if (config == MelodicRange) {
123 list.push_back("Colour Scale"); 124 list.push_back("Colour Scale");
124 // list.push_back("Window Type"); 125 // list.push_back("Window Type");
125 list.push_back("Window Size"); 126 list.push_back("Window Size");
126 list.push_back("Window Increment"); 127 list.push_back("Window Increment");
127 list.push_back("Normalize Columns"); 128 list.push_back("Normalize Columns");
129 list.push_back("Normalize Visible Area");
128 list.push_back("Bin Display"); 130 list.push_back("Bin Display");
129 list.push_back("Threshold"); 131 list.push_back("Threshold");
130 list.push_back("Gain"); 132 list.push_back("Gain");
131 list.push_back("Colour Rotation"); 133 list.push_back("Colour Rotation");
132 list.push_back("Min Frequency"); 134 list.push_back("Min Frequency");
143 if (name == "Colour Scale") return tr("Colour Scale"); 145 if (name == "Colour Scale") return tr("Colour Scale");
144 if (name == "Window Type") return tr("Window Type"); 146 if (name == "Window Type") return tr("Window Type");
145 if (name == "Window Size") return tr("Window Size"); 147 if (name == "Window Size") return tr("Window Size");
146 if (name == "Window Increment") return tr("Window Overlap"); 148 if (name == "Window Increment") return tr("Window Overlap");
147 if (name == "Normalize Columns") return tr("Normalize Columns"); 149 if (name == "Normalize Columns") return tr("Normalize Columns");
150 if (name == "Normalize Visible Area") return tr("Normalize Visible Area");
148 if (name == "Bin Display") return tr("Bin Display"); 151 if (name == "Bin Display") return tr("Bin Display");
149 if (name == "Threshold") return tr("Threshold"); 152 if (name == "Threshold") return tr("Threshold");
150 if (name == "Gain") return tr("Gain"); 153 if (name == "Gain") return tr("Gain");
151 if (name == "Colour Rotation") return tr("Colour Rotation"); 154 if (name == "Colour Rotation") return tr("Colour Rotation");
152 if (name == "Min Frequency") return tr("Min Frequency"); 155 if (name == "Min Frequency") return tr("Min Frequency");
160 SpectrogramLayer::getPropertyType(const PropertyName &name) const 163 SpectrogramLayer::getPropertyType(const PropertyName &name) const
161 { 164 {
162 if (name == "Gain") return RangeProperty; 165 if (name == "Gain") return RangeProperty;
163 if (name == "Colour Rotation") return RangeProperty; 166 if (name == "Colour Rotation") return RangeProperty;
164 if (name == "Normalize Columns") return ToggleProperty; 167 if (name == "Normalize Columns") return ToggleProperty;
168 if (name == "Normalize Visible Area") return ToggleProperty;
165 if (name == "Threshold") return RangeProperty; 169 if (name == "Threshold") return RangeProperty;
166 if (name == "Zero Padding") return ToggleProperty; 170 if (name == "Zero Padding") return ToggleProperty;
167 return ValueProperty; 171 return ValueProperty;
168 } 172 }
169 173
177 if (name == "Colour" || 181 if (name == "Colour" ||
178 name == "Gain" || 182 name == "Gain" ||
179 name == "Threshold" || 183 name == "Threshold" ||
180 name == "Colour Rotation") return tr("Colour"); 184 name == "Colour Rotation") return tr("Colour");
181 if (name == "Normalize Columns" || 185 if (name == "Normalize Columns" ||
186 name == "Normalize Visible Area" ||
182 name == "Bin Display" || 187 name == "Bin Display" ||
183 name == "Colour Scale") return tr("Scale"); 188 name == "Colour Scale") return tr("Scale");
184 if (name == "Max Frequency" || 189 if (name == "Max Frequency" ||
185 name == "Min Frequency" || 190 name == "Min Frequency" ||
186 name == "Frequency Scale" || 191 name == "Frequency Scale" ||
316 deft = (int)m_binDisplay; 321 deft = (int)m_binDisplay;
317 322
318 } else if (name == "Normalize Columns") { 323 } else if (name == "Normalize Columns") {
319 324
320 deft = (m_normalizeColumns ? 1 : 0); 325 deft = (m_normalizeColumns ? 1 : 0);
326
327 } else if (name == "Normalize Visible Area") {
328
329 deft = (m_normalizeVisibleArea ? 1 : 0);
321 330
322 } else { 331 } else {
323 deft = Layer::getPropertyRangeAndValue(name, min, max); 332 deft = Layer::getPropertyRangeAndValue(name, min, max);
324 } 333 }
325 334
509 case 1: setBinDisplay(PeakBins); break; 518 case 1: setBinDisplay(PeakBins); break;
510 case 2: setBinDisplay(PeakFrequencies); break; 519 case 2: setBinDisplay(PeakFrequencies); break;
511 } 520 }
512 } else if (name == "Normalize Columns") { 521 } else if (name == "Normalize Columns") {
513 setNormalizeColumns(value ? true : false); 522 setNormalizeColumns(value ? true : false);
523 } else if (name == "Normalize Visible Area") {
524 setNormalizeVisibleArea(value ? true : false);
514 } 525 }
515 } 526 }
516 527
517 void 528 void
518 SpectrogramLayer::invalidatePixmapCaches() 529 SpectrogramLayer::invalidatePixmapCaches()
818 829
819 bool 830 bool
820 SpectrogramLayer::getNormalizeColumns() const 831 SpectrogramLayer::getNormalizeColumns() const
821 { 832 {
822 return m_normalizeColumns; 833 return m_normalizeColumns;
834 }
835
836 void
837 SpectrogramLayer::setNormalizeVisibleArea(bool n)
838 {
839 if (m_normalizeVisibleArea == n) return;
840
841 invalidatePixmapCaches();
842 invalidateMagnitudes();
843 m_normalizeVisibleArea = n;
844
845 emit layerParametersChanged();
846 }
847
848 bool
849 SpectrogramLayer::getNormalizeVisibleArea() const
850 {
851 return m_normalizeVisibleArea;
823 } 852 }
824 853
825 void 854 void
826 SpectrogramLayer::setLayerDormant(const View *v, bool dormant) 855 SpectrogramLayer::setLayerDormant(const View *v, bool dormant)
827 { 856 {
1064 unsigned char 1093 unsigned char
1065 SpectrogramLayer::getDisplayValue(View *v, float input) const 1094 SpectrogramLayer::getDisplayValue(View *v, float input) const
1066 { 1095 {
1067 int value; 1096 int value;
1068 1097
1069 //!!! for the moment we're always normalizing visible area 1098 float min = 0.f;
1070 float min = m_viewMags[v].getMin(); 1099 float max = 1.f;
1071 float max = m_viewMags[v].getMax(); 1100
1101 if (m_normalizeVisibleArea) {
1102 min = m_viewMags[v].getMin();
1103 max = m_viewMags[v].getMax();
1104 } else if (!m_normalizeColumns) {
1105 if (m_colourScale == LinearColourScale ||
1106 m_colourScale == MeterColourScale) {
1107 max = 0.1f;
1108 }
1109 }
1110
1072 float thresh = -80.f; 1111 float thresh = -80.f;
1073 1112
1074 if (max == 0.f) max = 1.f; 1113 if (max == 0.f) max = 1.f;
1075 if (max == min) min = max - 0.0001f; 1114 if (max == min) min = max - 0.0001f;
1076 1115
1142 SpectrogramLayer::getInputForDisplayValue(unsigned char uc) const 1181 SpectrogramLayer::getInputForDisplayValue(unsigned char uc) const
1143 { 1182 {
1144 int value = uc; 1183 int value = uc;
1145 float input; 1184 float input;
1146 1185
1186 //!!! incorrect for normalizing visible area (and also out of date)
1187
1147 switch (m_colourScale) { 1188 switch (m_colourScale) {
1148 1189
1149 default: 1190 default:
1150 case LinearColourScale: 1191 case LinearColourScale:
1151 input = float(value - 1) / 255.0 / (m_normalizeColumns ? 1 : 50); 1192 input = float(value - 1) / 255.0 / (m_normalizeColumns ? 1 : 50);
1994 2035
1995 QPainter cachePainter(&cache.pixmap); 2036 QPainter cachePainter(&cache.pixmap);
1996 cachePainter.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h); 2037 cachePainter.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h);
1997 cachePainter.end(); 2038 cachePainter.end();
1998 2039
1999 if (!overallMagChanged) { 2040 if (!m_normalizeVisibleArea || !overallMagChanged) {
2000 2041
2001 cache.startFrame = startFrame; 2042 cache.startFrame = startFrame;
2002 cache.zoomLevel = zoomLevel; 2043 cache.zoomLevel = zoomLevel;
2003 2044
2004 if (cache.validArea.x() > 0) { 2045 if (cache.validArea.x() > 0) {
2028 // overallMagChanged 2069 // overallMagChanged
2029 cache.validArea = QRect(); 2070 cache.validArea = QRect();
2030 v->update(); 2071 v->update();
2031 } 2072 }
2032 2073
2074 QPoint localPos;
2075
2076 if (v->shouldIlluminateLocalFeatures(this, localPos)) {
2077
2078 std::cerr << "SpectrogramLayer: shouldIlluminateLocalFeatures("
2079 << localPos.x() << "," << localPos.y() << ")" << std::endl;
2080
2081 float s0, s1;
2082 float q0, q1;
2083
2084 if (getXBinRange(v, localPos.x(), s0, s1) &&
2085 getYBinRange(v, localPos.y(), q0, q1)) {
2086
2087 int s0i = int(s0 + 0.001);
2088 int s1i = int(s1);
2089
2090 int q0i = int(q0 + 0.001);
2091 int q1i = int(q1);
2092
2093 int x0 = v->getXForFrame(s0i * getWindowIncrement());
2094 int x1 = v->getXForFrame(s1i * getWindowIncrement() + 1);
2095 int y1 = yval[q0i];
2096 int y0 = yval[q1i + 1];
2097
2098 std::cerr << "SpectrogramLayer::paint: illuminate "
2099 << x0 << "," << y1 << " -> " << x1 << "," << y0 << std::endl;
2100
2101 paint.setPen(Qt::white);
2102 paint.drawRect(x0, y1, x1 - x0 + 1, y0 - y1 + 1);
2103 }
2104 }
2105
2033 #ifdef DEBUG_SPECTROGRAM_REPAINT 2106 #ifdef DEBUG_SPECTROGRAM_REPAINT
2034 std::cerr << "SpectrogramLayer::paint() returning" << std::endl; 2107 std::cerr << "SpectrogramLayer::paint() returning" << std::endl;
2035 #endif 2108 #endif
2036 } 2109 }
2037 2110
2080 { 2153 {
2081 min = getEffectiveMinFrequency(); 2154 min = getEffectiveMinFrequency();
2082 max = getEffectiveMaxFrequency(); 2155 max = getEffectiveMaxFrequency();
2083 return true; 2156 return true;
2084 } 2157 }
2158
2159 bool
2160 SpectrogramLayer::setDisplayExtents(float min, float max)
2161 {
2162 if (!m_model) return false;
2163 if (min < 0) min = 0;
2164 if (max > m_model->getSampleRate()/2) max = m_model->getSampleRate()/2;
2165
2166 size_t minf = lrintf(min);
2167 size_t maxf = lrintf(max);
2168
2169 if (m_minFrequency == minf && m_maxFrequency == maxf) return true;
2170
2171 invalidatePixmapCaches();
2172 invalidateMagnitudes();
2173
2174 m_minFrequency = minf;
2175 m_maxFrequency = maxf;
2176
2177 emit layerParametersChanged();
2178
2179 return true;
2180 }
2085 2181
2086 bool 2182 bool
2087 SpectrogramLayer::snapToFeatureFrame(View *v, int &frame, 2183 SpectrogramLayer::snapToFeatureFrame(View *v, int &frame,
2088 size_t &resolution, 2184 size_t &resolution,
2089 SnapType snap) const 2185 SnapType snap) const
2327 { 2423 {
2328 if (!m_model || !m_model->isOK()) { 2424 if (!m_model || !m_model->isOK()) {
2329 return; 2425 return;
2330 } 2426 }
2331 2427
2428 //!!! cache this?
2429
2332 int h = rect.height(), w = rect.width(); 2430 int h = rect.height(), w = rect.width();
2333 2431
2334 int tickw = (m_frequencyScale == LogFrequencyScale ? 10 : 4); 2432 int tickw = (m_frequencyScale == LogFrequencyScale ? 10 : 4);
2335 int pkw = (m_frequencyScale == LogFrequencyScale ? 10 : 0); 2433 int pkw = (m_frequencyScale == LogFrequencyScale ? 10 : 0);
2336 2434
2391 float max = m_viewMags[v].getMax(); 2489 float max = m_viewMags[v].getMax();
2392 2490
2393 float dBmin = AudioLevel::multiplier_to_dB(min); 2491 float dBmin = AudioLevel::multiplier_to_dB(min);
2394 float dBmax = AudioLevel::multiplier_to_dB(max); 2492 float dBmax = AudioLevel::multiplier_to_dB(max);
2395 2493
2396 if (dBmin < -80.f) dBmin = -80.f; 2494 if (dBmax < -60.f) dBmax = -60.f;
2495 else top = QString("%1").arg(lrintf(dBmax));
2496
2497 if (dBmin < dBmax - 60.f) dBmin = dBmax - 60.f;
2397 bottom = QString("%1").arg(lrintf(dBmin)); 2498 bottom = QString("%1").arg(lrintf(dBmin));
2398
2399 if (dBmax < -80.f) dBmax = -80.f;
2400 else top = QString("%1").arg(lrintf(dBmax));
2401 2499
2402 //!!! & phase etc 2500 //!!! & phase etc
2403 2501
2404 if (m_colourScale != PhaseColourScale) { 2502 if (m_colourScale != PhaseColourScale) {
2405 paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2, 2503 paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2,
2446 2544
2447 if (i == 0) { 2545 if (i == 0) {
2448 lasty = y; 2546 lasty = y;
2449 lastdb = idb; 2547 lastdb = idb;
2450 } else if (i < ch - paint.fontMetrics().ascent() && 2548 } else if (i < ch - paint.fontMetrics().ascent() &&
2549 idb != lastdb &&
2451 ((abs(y - lasty) > textHeight && 2550 ((abs(y - lasty) > textHeight &&
2452 idb % 10 == 0) || 2551 idb % 10 == 0) ||
2453 (abs(y - lasty) > paint.fontMetrics().ascent() && 2552 (abs(y - lasty) > paint.fontMetrics().ascent() &&
2454 idb % 5 == 0))) { 2553 idb % 5 == 0))) {
2455 paint.setPen(Qt::black); 2554 paint.setPen(Qt::black);