comparison layer/SpectrogramLayer.cpp @ 1143:c53ed1a6fcbd spectrogram-minor-refactor

Fixes to phase display and colour scale for it; tidy up some debug output
author Chris Cannam
date Fri, 05 Aug 2016 14:31:16 +0100
parents 8f4634b82e36
children 6eef0330ef12
comparison
equal deleted inserted replaced
1142:8f4634b82e36 1143:c53ed1a6fcbd
49 49
50 #ifndef __GNUC__ 50 #ifndef __GNUC__
51 #include <alloca.h> 51 #include <alloca.h>
52 #endif 52 #endif
53 53
54 #define DEBUG_SPECTROGRAM 1 54 //#define DEBUG_SPECTROGRAM 1
55 #define DEBUG_SPECTROGRAM_REPAINT 1 55 //#define DEBUG_SPECTROGRAM_REPAINT 1
56 56
57 using namespace std; 57 using namespace std;
58 58
59 SpectrogramLayer::SpectrogramLayer(Configuration config) : 59 SpectrogramLayer::SpectrogramLayer(Configuration config) :
60 m_model(0), 60 m_model(0),
1505 1505
1506 } else { 1506 } else {
1507 1507
1508 result = renderer->renderTimeConstrained(v, paint, rect); 1508 result = renderer->renderTimeConstrained(v, paint, rect);
1509 1509
1510 #ifdef DEBUG_SPECTROGRAM_REPAINT
1510 cerr << "rect width from this paint: " << result.rendered.width() 1511 cerr << "rect width from this paint: " << result.rendered.width()
1511 << ", mag range in this paint: " << result.range.getMin() << " -> " 1512 << ", mag range in this paint: " << result.range.getMin() << " -> "
1512 << result.range.getMax() << endl; 1513 << result.range.getMax() << endl;
1514 #endif
1513 1515
1514 QRect uncached = renderer->getLargestUncachedRect(v); 1516 QRect uncached = renderer->getLargestUncachedRect(v);
1515 if (uncached.width() > 0) { 1517 if (uncached.width() > 0) {
1516 v->updatePaintRect(uncached); 1518 v->updatePaintRect(uncached);
1517 } 1519 }
1520 magRange.sample(result.range); 1522 magRange.sample(result.range);
1521 1523
1522 if (magRange.isSet()) { 1524 if (magRange.isSet()) {
1523 if (m_viewMags[viewId] != magRange) { 1525 if (m_viewMags[viewId] != magRange) {
1524 m_viewMags[viewId] = magRange; 1526 m_viewMags[viewId] = magRange;
1527 #ifdef DEBUG_SPECTROGRAM_REPAINT
1525 cerr << "mag range in this view has changed: " 1528 cerr << "mag range in this view has changed: "
1526 << magRange.getMin() << " -> " << magRange.getMax() << endl; 1529 << magRange.getMin() << " -> " << magRange.getMax() << endl;
1530 #endif
1527 } 1531 }
1528 } 1532 }
1529 1533
1530 if (!continuingPaint && m_normalizeVisibleArea && 1534 if (!continuingPaint && m_normalizeVisibleArea &&
1531 m_viewMags[viewId] != m_lastRenderedMags[viewId]) { 1535 m_viewMags[viewId] != m_lastRenderedMags[viewId]) {
1536 #ifdef DEBUG_SPECTROGRAM_REPAINT
1532 cerr << "mag range has changed from last rendered range: re-rendering" 1537 cerr << "mag range has changed from last rendered range: re-rendering"
1533 << endl; 1538 << endl;
1539 #endif
1534 delete m_renderers[viewId]; 1540 delete m_renderers[viewId];
1535 m_renderers.erase(viewId); 1541 m_renderers.erase(viewId);
1536 v->updatePaintRect(v->getPaintRect()); 1542 v->updatePaintRect(v->getPaintRect());
1537 } 1543 }
1538 } 1544 }
1569 QPoint localPos; 1575 QPoint localPos;
1570 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) { 1576 if (!v->shouldIlluminateLocalFeatures(this, localPos) || !m_model) {
1571 return; 1577 return;
1572 } 1578 }
1573 1579
1580 #ifdef DEBUG_SPECTROGRAM_REPAINT
1574 cerr << "SpectrogramLayer: illuminateLocalFeatures(" 1581 cerr << "SpectrogramLayer: illuminateLocalFeatures("
1575 << localPos.x() << "," << localPos.y() << ")" << endl; 1582 << localPos.x() << "," << localPos.y() << ")" << endl;
1583 #endif
1576 1584
1577 double s0, s1; 1585 double s0, s1;
1578 double f0, f1; 1586 double f0, f1;
1579 1587
1580 if (getXBinRange(v, localPos.x(), s0, s1) && 1588 if (getXBinRange(v, localPos.x(), s0, s1) &&
1587 int x1 = v->getXForFrame((s1i + 1) * getWindowIncrement()); 1595 int x1 = v->getXForFrame((s1i + 1) * getWindowIncrement());
1588 1596
1589 int y1 = int(getYForFrequency(v, f1)); 1597 int y1 = int(getYForFrequency(v, f1));
1590 int y0 = int(getYForFrequency(v, f0)); 1598 int y0 = int(getYForFrequency(v, f0));
1591 1599
1600 #ifdef DEBUG_SPECTROGRAM_REPAINT
1592 cerr << "SpectrogramLayer: illuminate " 1601 cerr << "SpectrogramLayer: illuminate "
1593 << x0 << "," << y1 << " -> " << x1 << "," << y0 << endl; 1602 << x0 << "," << y1 << " -> " << x1 << "," << y0 << endl;
1603 #endif
1594 1604
1595 paint.setPen(v->getForeground()); 1605 paint.setPen(v->getForeground());
1596 1606
1597 //!!! should we be using paintCrosshairs for this? 1607 //!!! should we be using paintCrosshairs for this?
1598 1608
2091 void 2101 void
2092 SpectrogramLayer::paintDetailedScale(LayerGeometryProvider *v, 2102 SpectrogramLayer::paintDetailedScale(LayerGeometryProvider *v,
2093 QPainter &paint, QRect rect) const 2103 QPainter &paint, QRect rect) const
2094 { 2104 {
2095 // The colour scale 2105 // The colour scale
2106
2107 if (m_colourScale == ColourScaleType::Phase) {
2108 paintDetailedScalePhase(v, paint, rect);
2109 return;
2110 }
2096 2111
2097 int h = rect.height(); 2112 int h = rect.height();
2098 int textHeight = paint.fontMetrics().height(); 2113 int textHeight = paint.fontMetrics().height();
2099 int toff = -textHeight + paint.fontMetrics().ascent() + 2; 2114 int toff = -textHeight + paint.fontMetrics().ascent() + 2;
2100 2115
2101 int cw = getColourScaleWidth(paint); 2116 int cw = getColourScaleWidth(paint);
2102 int cbw = paint.fontMetrics().width("dB"); 2117 int cbw = paint.fontMetrics().width("dB");
2103 2118
2104 int topLines = 2; 2119 int topLines = 2;
2105 if (m_colourScale == ColourScaleType::Phase) topLines = 1;
2106 2120
2107 int ch = h - textHeight * (topLines + 1) - 8; 2121 int ch = h - textHeight * (topLines + 1) - 8;
2108 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1); 2122 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1);
2109 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1); 2123 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1);
2110 2124
2133 #ifdef DEBUG_SPECTROGRAM_REPAINT 2147 #ifdef DEBUG_SPECTROGRAM_REPAINT
2134 cerr << "adjusted dB range to min = " << dBmin << ", max = " << dBmax 2148 cerr << "adjusted dB range to min = " << dBmin << ", max = " << dBmax
2135 << endl; 2149 << endl;
2136 #endif 2150 #endif
2137 2151
2138 //!!! & phase etc 2152 paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2,
2139 2153 2 + textHeight + toff, "dBFS");
2140 if (m_colourScale != ColourScaleType::Phase) {
2141 paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2,
2142 2 + textHeight + toff, "dBFS");
2143 }
2144 2154
2145 // paint.drawText((cw + 6 - paint.fontMetrics().width(top)) / 2, 2155 // paint.drawText((cw + 6 - paint.fontMetrics().width(top)) / 2,
2146 paint.drawText(3 + cw - cbw - paint.fontMetrics().width(top), 2156 paint.drawText(3 + cw - cbw - paint.fontMetrics().width(top),
2147 2 + textHeight * topLines + toff + textHeight/2, top); 2157 2 + textHeight * topLines + toff + textHeight/2, top);
2148 2158
2183 paint.setPen(v->getForeground()); 2193 paint.setPen(v->getForeground());
2184 paint.drawLine(5 + cw - cbw, y, 8 + cw - cbw, y); 2194 paint.drawLine(5 + cw - cbw, y, 8 + cw - cbw, y);
2185 lasty = y; 2195 lasty = y;
2186 lastdb = idb; 2196 lastdb = idb;
2187 } 2197 }
2198 }
2199 paint.restore();
2200 }
2201
2202 void
2203 SpectrogramLayer::paintDetailedScalePhase(LayerGeometryProvider *v,
2204 QPainter &paint, QRect rect) const
2205 {
2206 // The colour scale in phase mode
2207
2208 int h = rect.height();
2209 int textHeight = paint.fontMetrics().height();
2210 int toff = -textHeight + paint.fontMetrics().ascent() + 2;
2211
2212 int cw = getColourScaleWidth(paint);
2213
2214 // Phase is not measured in dB of course, but this places the
2215 // scale at the same position as in the magnitude spectrogram
2216 int cbw = paint.fontMetrics().width("dB");
2217
2218 int topLines = 1;
2219
2220 int ch = h - textHeight * (topLines + 1) - 8;
2221 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1);
2222
2223 QString top, bottom, middle;
2224 top = QString("%1").arg(QChar(0x3c0)); // pi
2225 bottom = "-" + top;
2226 middle = "0";
2227
2228 double min = -M_PI;
2229 double max = M_PI;
2230
2231 paint.drawText(3 + cw - cbw - paint.fontMetrics().width(top),
2232 2 + textHeight * topLines + toff + textHeight/2, top);
2233
2234 paint.drawText(3 + cw - cbw - paint.fontMetrics().width(middle),
2235 2 + textHeight * topLines + ch/2 + toff + textHeight/2, middle);
2236
2237 paint.drawText(3 + cw - cbw - paint.fontMetrics().width(bottom),
2238 h + toff - 3 - textHeight/2, bottom);
2239
2240 paint.save();
2241 paint.setBrush(Qt::NoBrush);
2242
2243 for (int i = 0; i < ch; ++i) {
2244 double val = min + (((max - min) * i) / (ch - 1));
2245 paint.setPen(getRenderer(v)->getColour(val));
2246 int y = textHeight * topLines + 4 + ch - i;
2247 paint.drawLine(5 + cw - cbw, y, cw + 2, y);
2188 } 2248 }
2189 paint.restore(); 2249 paint.restore();
2190 } 2250 }
2191 2251
2192 class SpectrogramRangeMapper : public RangeMapper 2252 class SpectrogramRangeMapper : public RangeMapper