comparison layer/SpectrogramLayer.cpp @ 114:991de8783cf5

* Add fuzzy-adapter class to pick out subset data from FFT data server, instead of having separate methods in data server class. Update spectrogram to use it. * Give spectrogram layer one fft adapter per view, in case the views need different zero-padding levels. * Reduce ridiculous memory consumption of MatrixFile for tall matrices. Still very much work in progress here.
author Chris Cannam
date Fri, 30 Jun 2006 11:26:10 +0000
parents 7a23edd831cb
children 47cb32bb35ab
comparison
equal deleted inserted replaced
113:7a23edd831cb 114:991de8783cf5
53 m_colourScale(dBColourScale), 53 m_colourScale(dBColourScale),
54 m_colourScheme(DefaultColours), 54 m_colourScheme(DefaultColours),
55 m_frequencyScale(LinearFrequencyScale), 55 m_frequencyScale(LinearFrequencyScale),
56 m_binDisplay(AllBins), 56 m_binDisplay(AllBins),
57 m_normalizeColumns(false), 57 m_normalizeColumns(false),
58 m_fftServer(0),
59 m_updateTimer(0), 58 m_updateTimer(0),
60 m_candidateFillStartFrame(0), 59 m_candidateFillStartFrame(0),
61 m_lastFillExtent(0), 60 m_lastFillExtent(0),
62 m_exiting(false) 61 m_exiting(false)
63 { 62 {
85 SpectrogramLayer::~SpectrogramLayer() 84 SpectrogramLayer::~SpectrogramLayer()
86 { 85 {
87 delete m_updateTimer; 86 delete m_updateTimer;
88 m_updateTimer = 0; 87 m_updateTimer = 0;
89 88
90 if (m_fftServer) { 89 invalidateFFTAdapters();
91 FFTDataServer::releaseInstance(m_fftServer);
92 m_fftServer = 0;
93 }
94 } 90 }
95 91
96 void 92 void
97 SpectrogramLayer::setModel(const DenseTimeValueModel *model) 93 SpectrogramLayer::setModel(const DenseTimeValueModel *model)
98 { 94 {
99 // std::cerr << "SpectrogramLayer(" << this << "): setModel(" << model << ")" << std::endl; 95 // std::cerr << "SpectrogramLayer(" << this << "): setModel(" << model << ")" << std::endl;
100 96
101 if (model == m_model) return; 97 if (model == m_model) return;
102 98
103 m_model = model; 99 m_model = model;
104 getFFTServer(); 100 invalidateFFTAdapters();
105 101
106 if (!m_model || !m_model->isOK()) return; 102 if (!m_model || !m_model->isOK()) return;
107 103
108 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged())); 104 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged()));
109 connect(m_model, SIGNAL(modelChanged(size_t, size_t)), 105 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
116 connect(m_model, SIGNAL(modelChanged(size_t, size_t)), 112 connect(m_model, SIGNAL(modelChanged(size_t, size_t)),
117 this, SLOT(cacheInvalid(size_t, size_t))); 113 this, SLOT(cacheInvalid(size_t, size_t)));
118 114
119 emit modelReplaced(); 115 emit modelReplaced();
120 } 116 }
121 117 /*!!!
122 void 118 void
123 SpectrogramLayer::getFFTServer() 119 SpectrogramLayer::invalidateFFTAdapters()
124 { 120 {
125 if (m_fftServer) { 121 // if (m_fftServer) {
126 FFTDataServer::releaseInstance(m_fftServer); 122 // FFTDataServer::releaseInstance(m_fftServer);
127 m_fftServer = 0; 123 // m_fftServer = 0;
128 } 124 // }
125
126 delete m_fftServer;
127 m_fftServer = 0;
129 128
130 if (m_model) { 129 if (m_model) {
131 m_fftServer = FFTDataServer::getFuzzyInstance(m_model, 130 // m_fftServer = FFTDataServer::getFuzzyInstance(m_model,
131 m_fftServer = new FFTFuzzyAdapter(m_model,
132 m_channel, 132 m_channel,
133 m_windowType, 133 m_windowType,
134 m_windowSize, 134 m_windowSize,
135 getWindowIncrement(), 135 getWindowIncrement(),
136 m_fftSize, 136 m_fftSize,
143 m_updateTimer = new QTimer(this); 143 m_updateTimer = new QTimer(this);
144 connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(fillTimerTimedOut())); 144 connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(fillTimerTimedOut()));
145 m_updateTimer->start(200); 145 m_updateTimer->start(200);
146 } 146 }
147 } 147 }
148 148 */
149 Layer::PropertyList 149 Layer::PropertyList
150 SpectrogramLayer::getProperties() const 150 SpectrogramLayer::getProperties() const
151 { 151 {
152 PropertyList list; 152 PropertyList list;
153 list.push_back("Colour"); 153 list.push_back("Colour");
571 { 571 {
572 if (m_channel == ch) return; 572 if (m_channel == ch) return;
573 573
574 invalidatePixmapCaches(); 574 invalidatePixmapCaches();
575 m_channel = ch; 575 m_channel = ch;
576 getFFTServer(); 576 invalidateFFTAdapters();
577 577
578 emit layerParametersChanged(); 578 emit layerParametersChanged();
579 } 579 }
580 580
581 int 581 int
592 invalidatePixmapCaches(); 592 invalidatePixmapCaches();
593 593
594 m_windowSize = ws; 594 m_windowSize = ws;
595 m_fftSize = ws * (m_zeroPadLevel + 1); 595 m_fftSize = ws * (m_zeroPadLevel + 1);
596 596
597 getFFTServer(); 597 invalidateFFTAdapters();
598 598
599 emit layerParametersChanged(); 599 emit layerParametersChanged();
600 } 600 }
601 601
602 size_t 602 size_t
612 612
613 invalidatePixmapCaches(); 613 invalidatePixmapCaches();
614 614
615 m_windowHopLevel = v; 615 m_windowHopLevel = v;
616 616
617 getFFTServer(); 617 invalidateFFTAdapters();
618 618
619 emit layerParametersChanged(); 619 emit layerParametersChanged();
620 620
621 // fillCache(); 621 // fillCache();
622 } 622 }
635 invalidatePixmapCaches(); 635 invalidatePixmapCaches();
636 636
637 m_zeroPadLevel = v; 637 m_zeroPadLevel = v;
638 m_fftSize = m_windowSize * (v + 1); 638 m_fftSize = m_windowSize * (v + 1);
639 639
640 getFFTServer(); 640 invalidateFFTAdapters();
641 641
642 emit layerParametersChanged(); 642 emit layerParametersChanged();
643 } 643 }
644 644
645 size_t 645 size_t
655 655
656 invalidatePixmapCaches(); 656 invalidatePixmapCaches();
657 657
658 m_windowType = w; 658 m_windowType = w;
659 659
660 getFFTServer(); 660 invalidateFFTAdapters();
661 661
662 emit layerParametersChanged(); 662 emit layerParametersChanged();
663 } 663 }
664 664
665 WindowType 665 WindowType
857 857
858 m_dormancy[v] = true; 858 m_dormancy[v] = true;
859 859
860 invalidatePixmapCaches(); 860 invalidatePixmapCaches();
861 m_pixmapCaches.erase(v); 861 m_pixmapCaches.erase(v);
862
863 if (m_fftAdapters.find(v) != m_fftAdapters.end()) {
864 delete m_fftAdapters[v];
865 m_fftAdapters.erase(v);
866 }
862 867
863 } else { 868 } else {
864 869
865 m_dormancy[v] = false; 870 m_dormancy[v] = false;
866 } 871 }
880 } 885 }
881 886
882 void 887 void
883 SpectrogramLayer::fillTimerTimedOut() 888 SpectrogramLayer::fillTimerTimedOut()
884 { 889 {
890 /*!!!
885 if (m_fftServer && m_model) { 891 if (m_fftServer && m_model) {
886 892
887 size_t fillExtent = m_fftServer->getFillExtent(); 893 size_t fillExtent = m_fftServer->getFillExtent();
888 #ifdef DEBUG_SPECTROGRAM_REPAINT 894 #ifdef DEBUG_SPECTROGRAM_REPAINT
889 std::cerr << "SpectrogramLayer::fillTimerTimedOut: extent " << fillExtent << ", last " << m_lastFillExtent << ", total " << m_model->getEndFrame() << std::endl; 895 std::cerr << "SpectrogramLayer::fillTimerTimedOut: extent " << fillExtent << ", last " << m_lastFillExtent << ", total " << m_model->getEndFrame() << std::endl;
915 invalidatePixmapCaches(); 921 invalidatePixmapCaches();
916 emit modelChanged(m_model->getStartFrame(), m_model->getEndFrame()); 922 emit modelChanged(m_model->getStartFrame(), m_model->getEndFrame());
917 m_lastFillExtent = fillExtent; 923 m_lastFillExtent = fillExtent;
918 } 924 }
919 } 925 }
926 */
920 } 927 }
921 928
922 void 929 void
923 SpectrogramLayer::setColourmap() 930 SpectrogramLayer::setColourmap()
924 { 931 {
996 } 1003 }
997 1004
998 void 1005 void
999 SpectrogramLayer::rotateColourmap(int distance) 1006 SpectrogramLayer::rotateColourmap(int distance)
1000 { 1007 {
1001 if (!m_fftServer) return;
1002
1003 QColor newPixels[256]; 1008 QColor newPixels[256];
1004 1009
1005 newPixels[NO_VALUE] = m_colourMap.getColour(NO_VALUE); 1010 newPixels[NO_VALUE] = m_colourMap.getColour(NO_VALUE);
1006 1011
1007 for (int pixel = 1; pixel < 256; ++pixel) { 1012 for (int pixel = 1; pixel < 256; ++pixel) {
1167 float minf = getEffectiveMinFrequency(); 1172 float minf = getEffectiveMinFrequency();
1168 float maxf = getEffectiveMaxFrequency(); 1173 float maxf = getEffectiveMaxFrequency();
1169 1174
1170 bool logarithmic = (m_frequencyScale == LogFrequencyScale); 1175 bool logarithmic = (m_frequencyScale == LogFrequencyScale);
1171 1176
1177 //!!! wrong for smoothing -- wrong fft size for fft adapter
1178
1172 q0 = v->getFrequencyForY(y, minf, maxf, logarithmic); 1179 q0 = v->getFrequencyForY(y, minf, maxf, logarithmic);
1173 q1 = v->getFrequencyForY(y - 1, minf, maxf, logarithmic); 1180 q1 = v->getFrequencyForY(y - 1, minf, maxf, logarithmic);
1174 1181
1175 // Now map these on to actual bins 1182 // Now map these on to actual bins
1176 1183
1239 1246
1240 int q0i = int(q0 + 0.001); 1247 int q0i = int(q0 + 0.001);
1241 int q1i = int(q1); 1248 int q1i = int(q1);
1242 1249
1243 int sr = m_model->getSampleRate(); 1250 int sr = m_model->getSampleRate();
1251
1252 //!!! wrong for smoothing -- wrong fft size for fft adapter
1244 1253
1245 for (int q = q0i; q <= q1i; ++q) { 1254 for (int q = q0i; q <= q1i; ++q) {
1246 int binfreq = (sr * q) / m_fftSize; 1255 int binfreq = (sr * q) / m_fftSize;
1247 if (q == q0i) freqMin = binfreq; 1256 if (q == q0i) freqMin = binfreq;
1248 if (q == q1i) freqMax = binfreq; 1257 if (q == q1i) freqMax = binfreq;
1254 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y, 1263 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y,
1255 float &freqMin, float &freqMax, 1264 float &freqMin, float &freqMax,
1256 float &adjFreqMin, float &adjFreqMax) 1265 float &adjFreqMin, float &adjFreqMax)
1257 const 1266 const
1258 { 1267 {
1259 if (!m_fftServer) return false; 1268 FFTFuzzyAdapter *fft = getFFTAdapter(v);
1269 if (!fft) return false;
1260 1270
1261 float s0 = 0, s1 = 0; 1271 float s0 = 0, s1 = 0;
1262 if (!getXBinRange(v, x, s0, s1)) return false; 1272 if (!getXBinRange(v, x, s0, s1)) return false;
1263 1273
1264 float q0 = 0, q1 = 0; 1274 float q0 = 0, q1 = 0;
1286 1296
1287 float binfreq = (sr * q) / m_windowSize; 1297 float binfreq = (sr * q) / m_windowSize;
1288 if (q == q0i) freqMin = binfreq; 1298 if (q == q0i) freqMin = binfreq;
1289 if (q == q1i) freqMax = binfreq; 1299 if (q == q1i) freqMax = binfreq;
1290 1300
1291 if (peaksOnly && !isFFTLocalPeak(s, q)) continue; 1301 if (peaksOnly && !fft->isLocalPeak(s, q)) continue;
1292 1302
1293 if (!isFFTOverThreshold(s, q, m_threshold)) continue; 1303 if (!fft->isOverThreshold(s, q, m_threshold)) continue;
1294 1304
1295 float freq = binfreq; 1305 float freq = binfreq;
1296 bool steady = false; 1306 bool steady = false;
1297 1307
1298 if (s < int(getFFTWidth()) - 1) { 1308 if (s < int(fft->getWidth()) - 1) {
1299 1309
1300 freq = calculateFrequency(q, 1310 freq = calculateFrequency(q,
1301 windowSize, 1311 windowSize,
1302 windowIncrement, 1312 windowIncrement,
1303 sr, 1313 sr,
1304 getFFTPhaseAt(s, q), 1314 fft->getPhaseAt(s, q),
1305 getFFTPhaseAt(s+1, q), 1315 fft->getPhaseAt(s+1, q),
1306 steady); 1316 steady);
1307 1317
1308 if (!haveAdj || freq < adjFreqMin) adjFreqMin = freq; 1318 if (!haveAdj || freq < adjFreqMin) adjFreqMin = freq;
1309 if (!haveAdj || freq > adjFreqMax) adjFreqMax = freq; 1319 if (!haveAdj || freq > adjFreqMax) adjFreqMax = freq;
1310 1320
1337 int s0i = int(s0 + 0.001); 1347 int s0i = int(s0 + 0.001);
1338 int s1i = int(s1); 1348 int s1i = int(s1);
1339 1349
1340 bool rv = false; 1350 bool rv = false;
1341 1351
1342 if (m_fftServer) { 1352 FFTFuzzyAdapter *fft = getFFTAdapter(v);
1343 1353
1344 int cw = getFFTWidth(); 1354 if (fft) {
1345 int ch = getFFTHeight(); 1355
1356 int cw = fft->getWidth();
1357 int ch = fft->getHeight();
1346 1358
1347 min = 0.0; 1359 min = 0.0;
1348 max = 0.0; 1360 max = 0.0;
1349 phaseMin = 0.0; 1361 phaseMin = 0.0;
1350 phaseMax = 0.0; 1362 phaseMax = 0.0;
1354 for (int s = s0i; s <= s1i; ++s) { 1366 for (int s = s0i; s <= s1i; ++s) {
1355 if (s >= 0 && q >= 0 && s < cw && q < ch) { 1367 if (s >= 0 && q >= 0 && s < cw && q < ch) {
1356 1368
1357 float value; 1369 float value;
1358 1370
1359 value = getFFTPhaseAt(s, q); 1371 value = fft->getPhaseAt(s, q);
1360 if (!have || value < phaseMin) { phaseMin = value; } 1372 if (!have || value < phaseMin) { phaseMin = value; }
1361 if (!have || value > phaseMax) { phaseMax = value; } 1373 if (!have || value > phaseMax) { phaseMax = value; }
1362 1374
1363 value = getFFTMagnitudeAt(s, q); 1375 value = fft->getMagnitudeAt(s, q);
1364 if (!have || value < min) { min = value; } 1376 if (!have || value < min) { min = value; }
1365 if (!have || value > max) { max = value; } 1377 if (!have || value > max) { max = value; }
1366 1378
1367 have = true; 1379 have = true;
1368 } 1380 }
1375 } 1387 }
1376 1388
1377 return rv; 1389 return rv;
1378 } 1390 }
1379 1391
1392 size_t
1393 SpectrogramLayer::getZeroPadLevel(const View *v) const
1394 {
1395 //!!! tidy all this stuff
1396
1397 if (m_binDisplay != AllBins) return 0;
1398 if (m_frequencyScale == LogFrequencyScale) return 3;
1399
1400 int sr = m_model->getSampleRate();
1401
1402 size_t bins = m_fftSize / 2;
1403 if (m_maxFrequency > 0) {
1404 bins = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1);
1405 if (bins > m_fftSize / 2) bins = m_fftSize / 2;
1406 }
1407
1408 size_t minbin = 1;
1409 if (m_minFrequency > 0) {
1410 minbin = int((double(m_minFrequency) * m_fftSize) / sr + 0.1);
1411 if (minbin < 1) minbin = 1;
1412 if (minbin >= bins) minbin = bins - 1;
1413 }
1414
1415 if (v->height() / 1.5 > (bins - minbin) / (m_zeroPadLevel + 1)) {
1416 return 3;
1417 } else {
1418 return 0;
1419 }
1420 }
1421
1422 size_t
1423 SpectrogramLayer::getFFTSize(const View *v) const
1424 {
1425 return m_fftSize * (getZeroPadLevel(v) + 1);
1426 }
1427
1428 FFTFuzzyAdapter *
1429 SpectrogramLayer::getFFTAdapter(const View *v) const
1430 {
1431 if (!m_model) return 0;
1432
1433 size_t fftSize = getFFTSize(v);
1434
1435 if (m_fftAdapters.find(v) != m_fftAdapters.end()) {
1436 if (m_fftAdapters[v]->getHeight() != fftSize / 2) {
1437 delete m_fftAdapters[v];
1438 m_fftAdapters.erase(v);
1439 }
1440 }
1441
1442 if (m_fftAdapters.find(v) == m_fftAdapters.end()) {
1443 m_fftAdapters[v] = new FFTFuzzyAdapter(m_model,
1444 m_channel,
1445 m_windowType,
1446 m_windowSize,
1447 getWindowIncrement(),
1448 getFFTSize(v),
1449 true,
1450 m_candidateFillStartFrame);
1451 m_lastFillExtent = 0;
1452
1453 delete m_updateTimer;
1454 m_updateTimer = new QTimer((SpectrogramLayer *)this);
1455 connect(m_updateTimer, SIGNAL(timeout()),
1456 this, SLOT(fillTimerTimedOut()));
1457 m_updateTimer->start(200);
1458 }
1459
1460 return m_fftAdapters[v];
1461 }
1462
1463 void
1464 SpectrogramLayer::invalidateFFTAdapters()
1465 {
1466 for (ViewFFTMap::iterator i = m_fftAdapters.begin();
1467 i != m_fftAdapters.end(); ++i) {
1468 delete i->second;
1469 }
1470
1471 m_fftAdapters.clear();
1472 }
1473
1380 void 1474 void
1381 SpectrogramLayer::paint(View *v, QPainter &paint, QRect rect) const 1475 SpectrogramLayer::paint(View *v, QPainter &paint, QRect rect) const
1382 { 1476 {
1383 if (m_colourScheme == BlackOnWhite) { 1477 if (m_colourScheme == BlackOnWhite) {
1384 v->setLightBackground(true); 1478 v->setLightBackground(true);
1409 // is not in the dormancy map at all -- we need it to be present 1503 // is not in the dormancy map at all -- we need it to be present
1410 // and accountable for when determining whether we need the cache 1504 // and accountable for when determining whether we need the cache
1411 // in the cache-fill thread above. 1505 // in the cache-fill thread above.
1412 m_dormancy[v] = false; 1506 m_dormancy[v] = false;
1413 1507
1414 if (!m_fftServer) { // lock the mutex before checking this 1508 size_t fftSize = getFFTSize(v);
1415 #ifdef DEBUG_SPECTROGRAM_REPAINT 1509 FFTFuzzyAdapter *fft = getFFTAdapter(v);
1416 std::cerr << "SpectrogramLayer::paint(): No FFT server, returning" << std::endl; 1510 if (!fft) {
1417 #endif 1511 std::cerr << "ERROR: SpectrogramLayer::paint(): No FFT adapter, returning" << std::endl;
1418 return; 1512 return;
1419 } 1513 }
1420 1514
1421 PixmapCache &cache = m_pixmapCaches[v]; 1515 PixmapCache &cache = m_pixmapCaches[v];
1422 1516
1621 1715
1622 m_drawBuffer.fill(m_colourMap.getColour(0).rgb()); 1716 m_drawBuffer.fill(m_colourMap.getColour(0).rgb());
1623 1717
1624 int sr = m_model->getSampleRate(); 1718 int sr = m_model->getSampleRate();
1625 1719
1626 size_t bins = m_fftSize / 2; 1720 size_t bins = fftSize / 2;
1627 if (m_maxFrequency > 0) { 1721 if (m_maxFrequency > 0) {
1628 bins = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1); 1722 bins = int((double(m_maxFrequency) * fftSize) / sr + 0.1);
1629 if (bins > m_fftSize / 2) bins = m_fftSize / 2; 1723 if (bins > fftSize / 2) bins = fftSize / 2;
1630 } 1724 }
1631 1725
1632 size_t minbin = 1; 1726 size_t minbin = 1;
1633 if (m_minFrequency > 0) { 1727 if (m_minFrequency > 0) {
1634 minbin = int((double(m_minFrequency) * m_fftSize) / sr + 0.1); 1728 minbin = int((double(m_minFrequency) * fftSize) / sr + 0.1);
1635 if (minbin < 1) minbin = 1; 1729 if (minbin < 1) minbin = 1;
1636 if (minbin >= bins) minbin = bins - 1; 1730 if (minbin >= bins) minbin = bins - 1;
1637 } 1731 }
1638 1732
1639 //!!! quite wrong and won't work for layers that may be in more than one view 1733 float minFreq = (float(minbin) * sr) / fftSize;
1640 if (v->height() / 1.5 > (bins - minbin) / (m_zeroPadLevel + 1)) { 1734 float maxFreq = (float(bins) * sr) / fftSize;
1641 if (m_zeroPadLevel != 3) {
1642 std::cerr << v->height()/1.5 << " > " << ((bins - minbin) / (m_zeroPadLevel + 1)) << ": switching to smoothed display" << std::endl;
1643 ((SpectrogramLayer *)this)->setZeroPadLevel(3);
1644 return;
1645 }
1646 } else {
1647 if (m_zeroPadLevel != 0) {
1648 ((SpectrogramLayer *)this)->setZeroPadLevel(0);
1649 return;
1650 }
1651 }
1652
1653 float minFreq = (float(minbin) * sr) / m_fftSize;
1654 float maxFreq = (float(bins) * sr) / m_fftSize;
1655 1735
1656 float ymag[h]; 1736 float ymag[h];
1657 float ydiv[h]; 1737 float ydiv[h];
1658 float yval[bins + 1]; 1738 float yval[bins + 1];
1659 1739
1660 size_t increment = getWindowIncrement(); 1740 size_t increment = getWindowIncrement();
1661 1741
1662 bool logarithmic = (m_frequencyScale == LogFrequencyScale); 1742 bool logarithmic = (m_frequencyScale == LogFrequencyScale);
1663 1743
1664 for (size_t q = minbin; q <= bins; ++q) { 1744 for (size_t q = minbin; q <= bins; ++q) {
1665 float f0 = (float(q) * sr) / m_fftSize; 1745 float f0 = (float(q) * sr) / fftSize;
1666 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic); 1746 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic);
1667 } 1747 }
1668 1748
1669 for (int x = 0; x < w; ++x) { 1749 for (int x = 0; x < w; ++x) {
1670 1750
1681 } 1761 }
1682 1762
1683 int s0i = int(s0 + 0.001); 1763 int s0i = int(s0 + 0.001);
1684 int s1i = int(s1); 1764 int s1i = int(s1);
1685 1765
1686 if (s1i >= getFFTWidth()) { 1766 if (s1i >= fft->getWidth()) {
1687 if (s0i >= getFFTWidth()) { 1767 if (s0i >= fft->getWidth()) {
1688 continue; 1768 continue;
1689 } else { 1769 } else {
1690 s1i = s0i; 1770 s1i = s0i;
1691 } 1771 }
1692 } 1772 }
1693 1773
1694 for (int s = s0i; s <= s1i; ++s) { 1774 for (int s = s0i; s <= s1i; ++s) {
1695 1775
1696 if (!isFFTColumnReady(s)) continue; 1776 if (!fft->isColumnReady(s)) continue;
1697 1777
1698 for (size_t q = minbin; q < bins; ++q) { 1778 for (size_t q = minbin; q < bins; ++q) {
1699 1779
1700 float y0 = yval[q + 1]; 1780 float y0 = yval[q + 1];
1701 float y1 = yval[q]; 1781 float y1 = yval[q];
1702 1782
1703 if (m_binDisplay == PeakBins || 1783 if (m_binDisplay == PeakBins ||
1704 m_binDisplay == PeakFrequencies) { 1784 m_binDisplay == PeakFrequencies) {
1705 if (!isFFTLocalPeak(s, q)) continue; 1785 if (!fft->isLocalPeak(s, q)) continue;
1706 } 1786 }
1707 1787
1708 if (!isFFTOverThreshold(s, q, m_threshold)) continue; 1788 if (m_threshold != 0.f &&
1789 !fft->isOverThreshold(s, q, m_threshold)) {
1790 continue;
1791 }
1709 1792
1710 float sprop = 1.0; 1793 float sprop = 1.0;
1711 if (s == s0i) sprop *= (s + 1) - s0; 1794 if (s == s0i) sprop *= (s + 1) - s0;
1712 if (s == s1i) sprop *= s1 - s; 1795 if (s == s1i) sprop *= s1 - s;
1713 1796
1714 if (m_binDisplay == PeakFrequencies && 1797 if (m_binDisplay == PeakFrequencies &&
1715 s < int(getFFTWidth()) - 1) { 1798 s < int(fft->getWidth()) - 1) {
1716 1799
1717 bool steady = false; 1800 bool steady = false;
1718 float f = calculateFrequency(q, 1801 float f = calculateFrequency(q,
1719 m_windowSize, 1802 m_windowSize,
1720 increment, 1803 increment,
1721 sr, 1804 sr,
1722 getFFTPhaseAt(s, q), 1805 fft->getPhaseAt(s, q),
1723 getFFTPhaseAt(s+1, q), 1806 fft->getPhaseAt(s+1, q),
1724 steady); 1807 steady);
1725 1808
1726 y0 = y1 = v->getYForFrequency 1809 y0 = y1 = v->getYForFrequency
1727 (f, minFreq, maxFreq, logarithmic); 1810 (f, minFreq, maxFreq, logarithmic);
1728 } 1811 }
1731 int y1i = int(y1); 1814 int y1i = int(y1);
1732 1815
1733 float value; 1816 float value;
1734 1817
1735 if (m_colourScale == PhaseColourScale) { 1818 if (m_colourScale == PhaseColourScale) {
1736 value = getFFTPhaseAt(s, q); 1819 value = fft->getPhaseAt(s, q);
1737 } else if (m_normalizeColumns) { 1820 } else if (m_normalizeColumns) {
1738 value = getFFTNormalizedMagnitudeAt(s, q) * m_gain; 1821 value = fft->getNormalizedMagnitudeAt(s, q) * m_gain;
1739 } else { 1822 } else {
1740 value = getFFTMagnitudeAt(s, q) * m_gain; 1823 value = fft->getMagnitudeAt(s, q) * m_gain;
1741 } 1824 }
1742 1825
1743 for (int y = y0i; y <= y1i; ++y) { 1826 for (int y = y0i; y <= y1i; ++y) {
1744 1827
1745 if (y < 0 || y >= h) continue; 1828 if (y < 0 || y >= h) continue;
1831 } 1914 }
1832 1915
1833 int 1916 int
1834 SpectrogramLayer::getCompletion() const 1917 SpectrogramLayer::getCompletion() const
1835 { 1918 {
1919 /*!!!
1836 if (m_updateTimer == 0 || !m_fftServer) return 100; 1920 if (m_updateTimer == 0 || !m_fftServer) return 100;
1837 size_t completion = m_fftServer->getFillCompletion(); 1921 size_t completion = m_fftServer->getFillCompletion();
1838 // std::cerr << "SpectrogramLayer::getCompletion: completion = " << completion << std::endl; 1922 // std::cerr << "SpectrogramLayer::getCompletion: completion = " << completion << std::endl;
1839 return completion; 1923 return completion;
1924 */
1925 return 100;
1840 } 1926 }
1841 1927
1842 bool 1928 bool
1843 SpectrogramLayer::getValueExtents(float &min, float &max, 1929 SpectrogramLayer::getValueExtents(float &min, float &max,
1844 bool &logarithmic, QString &unit) const 1930 bool &logarithmic, QString &unit) const
2115 2201
2116 int py = -1; 2202 int py = -1;
2117 int textHeight = paint.fontMetrics().height(); 2203 int textHeight = paint.fontMetrics().height();
2118 int toff = -textHeight + paint.fontMetrics().ascent() + 2; 2204 int toff = -textHeight + paint.fontMetrics().ascent() + 2;
2119 2205
2120 if (m_fftServer && h > textHeight * 2 + 10) { 2206 if (h > textHeight * 2 + 10) {
2121 2207
2122 int ch = h - textHeight * 2 - 8; 2208 int ch = h - textHeight * 2 - 8;
2123 paint.drawRect(4, textHeight + 4, cw - 1, ch + 1); 2209 paint.drawRect(4, textHeight + 4, cw - 1, ch + 1);
2124 2210
2125 QString top, bottom; 2211 QString top, bottom;