comparison layer/SpectrogramLayer.cpp @ 905:b66fb15de477 cxx11

Working through the float/double and int/sv_frame_t fixes
author Chris Cannam
date Mon, 09 Mar 2015 14:35:21 +0000
parents 0fe1f4407261
children 12ab113ca2b1
comparison
equal deleted inserted replaced
904:e0f08e108064 905:b66fb15de477
1261 if (value > UCHAR_MAX) value = UCHAR_MAX; 1261 if (value > UCHAR_MAX) value = UCHAR_MAX;
1262 if (value < 0) value = 0; 1262 if (value < 0) value = 0;
1263 return value; 1263 return value;
1264 } 1264 }
1265 1265
1266 float 1266 double
1267 SpectrogramLayer::getEffectiveMinFrequency() const 1267 SpectrogramLayer::getEffectiveMinFrequency() const
1268 { 1268 {
1269 int sr = m_model->getSampleRate(); 1269 int sr = m_model->getSampleRate();
1270 float minf = float(sr) / m_fftSize; 1270 double minf = double(sr) / m_fftSize;
1271 1271
1272 if (m_minFrequency > 0.0) { 1272 if (m_minFrequency > 0.0) {
1273 int minbin = int((double(m_minFrequency) * m_fftSize) / sr + 0.01); 1273 int minbin = int((double(m_minFrequency) * m_fftSize) / sr + 0.01);
1274 if (minbin < 1) minbin = 1; 1274 if (minbin < 1) minbin = 1;
1275 minf = minbin * sr / m_fftSize; 1275 minf = minbin * sr / m_fftSize;
1276 } 1276 }
1277 1277
1278 return minf; 1278 return minf;
1279 } 1279 }
1280 1280
1281 float 1281 double
1282 SpectrogramLayer::getEffectiveMaxFrequency() const 1282 SpectrogramLayer::getEffectiveMaxFrequency() const
1283 { 1283 {
1284 int sr = m_model->getSampleRate(); 1284 int sr = m_model->getSampleRate();
1285 float maxf = float(sr) / 2; 1285 double maxf = double(sr) / 2;
1286 1286
1287 if (m_maxFrequency > 0.0) { 1287 if (m_maxFrequency > 0.0) {
1288 int maxbin = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1); 1288 int maxbin = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1);
1289 if (maxbin > m_fftSize / 2) maxbin = m_fftSize / 2; 1289 if (maxbin > m_fftSize / 2) maxbin = m_fftSize / 2;
1290 maxf = maxbin * sr / m_fftSize; 1290 maxf = maxbin * sr / m_fftSize;
1292 1292
1293 return maxf; 1293 return maxf;
1294 } 1294 }
1295 1295
1296 bool 1296 bool
1297 SpectrogramLayer::getYBinRange(View *v, int y, float &q0, float &q1) const 1297 SpectrogramLayer::getYBinRange(View *v, int y, double &q0, double &q1) const
1298 { 1298 {
1299 Profiler profiler("SpectrogramLayer::getYBinRange"); 1299 Profiler profiler("SpectrogramLayer::getYBinRange");
1300 1300
1301 int h = v->height(); 1301 int h = v->height();
1302 if (y < 0 || y >= h) return false; 1302 if (y < 0 || y >= h) return false;
1303 1303
1304 int sr = m_model->getSampleRate(); 1304 int sr = m_model->getSampleRate();
1305 float minf = getEffectiveMinFrequency(); 1305 double minf = getEffectiveMinFrequency();
1306 float maxf = getEffectiveMaxFrequency(); 1306 double maxf = getEffectiveMaxFrequency();
1307 1307
1308 bool logarithmic = (m_frequencyScale == LogFrequencyScale); 1308 bool logarithmic = (m_frequencyScale == LogFrequencyScale);
1309 1309
1310 q0 = v->getFrequencyForY(y, minf, maxf, logarithmic); 1310 q0 = v->getFrequencyForY(y, minf, maxf, logarithmic);
1311 q1 = v->getFrequencyForY(y - 1, minf, maxf, logarithmic); 1311 q1 = v->getFrequencyForY(y - 1, minf, maxf, logarithmic);
1318 1318
1319 return true; 1319 return true;
1320 } 1320 }
1321 1321
1322 bool 1322 bool
1323 SpectrogramLayer::getSmoothedYBinRange(View *v, int y, float &q0, float &q1) const 1323 SpectrogramLayer::getSmoothedYBinRange(View *v, int y, double &q0, double &q1) const
1324 { 1324 {
1325 Profiler profiler("SpectrogramLayer::getSmoothedYBinRange"); 1325 Profiler profiler("SpectrogramLayer::getSmoothedYBinRange");
1326 1326
1327 int h = v->height(); 1327 int h = v->height();
1328 if (y < 0 || y >= h) return false; 1328 if (y < 0 || y >= h) return false;
1329 1329
1330 int sr = m_model->getSampleRate(); 1330 int sr = m_model->getSampleRate();
1331 float minf = getEffectiveMinFrequency(); 1331 double minf = getEffectiveMinFrequency();
1332 float maxf = getEffectiveMaxFrequency(); 1332 double maxf = getEffectiveMaxFrequency();
1333 1333
1334 bool logarithmic = (m_frequencyScale == LogFrequencyScale); 1334 bool logarithmic = (m_frequencyScale == LogFrequencyScale);
1335 1335
1336 q0 = v->getFrequencyForY(y, minf, maxf, logarithmic); 1336 q0 = v->getFrequencyForY(y, minf, maxf, logarithmic);
1337 q1 = v->getFrequencyForY(y - 1, minf, maxf, logarithmic); 1337 q1 = v->getFrequencyForY(y - 1, minf, maxf, logarithmic);
1344 1344
1345 return true; 1345 return true;
1346 } 1346 }
1347 1347
1348 bool 1348 bool
1349 SpectrogramLayer::getXBinRange(View *v, int x, float &s0, float &s1) const 1349 SpectrogramLayer::getXBinRange(View *v, int x, double &s0, double &s1) const
1350 { 1350 {
1351 int modelStart = m_model->getStartFrame(); 1351 int modelStart = m_model->getStartFrame();
1352 int modelEnd = m_model->getEndFrame(); 1352 int modelEnd = m_model->getEndFrame();
1353 1353
1354 // Each pixel column covers an exact range of sample frames: 1354 // Each pixel column covers an exact range of sample frames:
1361 1361
1362 // And that range may be drawn from a possibly non-integral 1362 // And that range may be drawn from a possibly non-integral
1363 // range of spectrogram windows: 1363 // range of spectrogram windows:
1364 1364
1365 int windowIncrement = getWindowIncrement(); 1365 int windowIncrement = getWindowIncrement();
1366 s0 = float(f0) / windowIncrement; 1366 s0 = double(f0) / windowIncrement;
1367 s1 = float(f1) / windowIncrement; 1367 s1 = double(f1) / windowIncrement;
1368 1368
1369 return true; 1369 return true;
1370 } 1370 }
1371 1371
1372 bool 1372 bool
1373 SpectrogramLayer::getXBinSourceRange(View *v, int x, RealTime &min, RealTime &max) const 1373 SpectrogramLayer::getXBinSourceRange(View *v, int x, RealTime &min, RealTime &max) const
1374 { 1374 {
1375 float s0 = 0, s1 = 0; 1375 double s0 = 0, s1 = 0;
1376 if (!getXBinRange(v, x, s0, s1)) return false; 1376 if (!getXBinRange(v, x, s0, s1)) return false;
1377 1377
1378 int s0i = int(s0 + 0.001); 1378 int s0i = int(s0 + 0.001);
1379 int s1i = int(s1); 1379 int s1i = int(s1);
1380 1380
1387 max = RealTime::frame2RealTime(w1, m_model->getSampleRate()); 1387 max = RealTime::frame2RealTime(w1, m_model->getSampleRate());
1388 return true; 1388 return true;
1389 } 1389 }
1390 1390
1391 bool 1391 bool
1392 SpectrogramLayer::getYBinSourceRange(View *v, int y, float &freqMin, float &freqMax) 1392 SpectrogramLayer::getYBinSourceRange(View *v, int y, double &freqMin, double &freqMax)
1393 const 1393 const
1394 { 1394 {
1395 float q0 = 0, q1 = 0; 1395 double q0 = 0, q1 = 0;
1396 if (!getYBinRange(v, y, q0, q1)) return false; 1396 if (!getYBinRange(v, y, q0, q1)) return false;
1397 1397
1398 int q0i = int(q0 + 0.001); 1398 int q0i = int(q0 + 0.001);
1399 int q1i = int(q1); 1399 int q1i = int(q1);
1400 1400
1407 return true; 1407 return true;
1408 } 1408 }
1409 1409
1410 bool 1410 bool
1411 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y, 1411 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y,
1412 float &freqMin, float &freqMax, 1412 double &freqMin, double &freqMax,
1413 float &adjFreqMin, float &adjFreqMax) 1413 double &adjFreqMin, double &adjFreqMax)
1414 const 1414 const
1415 { 1415 {
1416 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1416 if (!m_model || !m_model->isOK() || !m_model->isReady()) {
1417 return false; 1417 return false;
1418 } 1418 }
1419 1419
1420 FFTModel *fft = getFFTModel(v); 1420 FFTModel *fft = getFFTModel(v);
1421 if (!fft) return false; 1421 if (!fft) return false;
1422 1422
1423 float s0 = 0, s1 = 0; 1423 double s0 = 0, s1 = 0;
1424 if (!getXBinRange(v, x, s0, s1)) return false; 1424 if (!getXBinRange(v, x, s0, s1)) return false;
1425 1425
1426 float q0 = 0, q1 = 0; 1426 double q0 = 0, q1 = 0;
1427 if (!getYBinRange(v, y, q0, q1)) return false; 1427 if (!getYBinRange(v, y, q0, q1)) return false;
1428 1428
1429 int s0i = int(s0 + 0.001); 1429 int s0i = int(s0 + 0.001);
1430 int s1i = int(s1); 1430 int s1i = int(s1);
1431 1431
1443 1443
1444 for (int s = s0i; s <= s1i; ++s) { 1444 for (int s = s0i; s <= s1i; ++s) {
1445 1445
1446 if (!fft->isColumnAvailable(s)) continue; 1446 if (!fft->isColumnAvailable(s)) continue;
1447 1447
1448 float binfreq = (float(sr) * q) / m_windowSize; 1448 double binfreq = (double(sr) * q) / m_windowSize;
1449 if (q == q0i) freqMin = binfreq; 1449 if (q == q0i) freqMin = binfreq;
1450 if (q == q1i) freqMax = binfreq; 1450 if (q == q1i) freqMax = binfreq;
1451 1451
1452 if (peaksOnly && !fft->isLocalPeak(s, q)) continue; 1452 if (peaksOnly && !fft->isLocalPeak(s, q)) continue;
1453 1453
1454 if (!fft->isOverThreshold(s, q, m_threshold * (m_fftSize/2))) continue; 1454 if (!fft->isOverThreshold(s, q, m_threshold * (m_fftSize/2))) continue;
1455 1455
1456 float freq = binfreq; 1456 double freq = binfreq;
1457 1457
1458 if (s < int(fft->getWidth()) - 1) { 1458 if (s < int(fft->getWidth()) - 1) {
1459 1459
1460 fft->estimateStableFrequency(s, q, freq); 1460 fft->estimateStableFrequency(s, q, freq);
1461 1461
1474 return haveAdj; 1474 return haveAdj;
1475 } 1475 }
1476 1476
1477 bool 1477 bool
1478 SpectrogramLayer::getXYBinSourceRange(View *v, int x, int y, 1478 SpectrogramLayer::getXYBinSourceRange(View *v, int x, int y,
1479 float &min, float &max, 1479 double &min, double &max,
1480 float &phaseMin, float &phaseMax) const 1480 double &phaseMin, double &phaseMax) const
1481 { 1481 {
1482 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1482 if (!m_model || !m_model->isOK() || !m_model->isReady()) {
1483 return false; 1483 return false;
1484 } 1484 }
1485 1485
1486 float q0 = 0, q1 = 0; 1486 double q0 = 0, q1 = 0;
1487 if (!getYBinRange(v, y, q0, q1)) return false; 1487 if (!getYBinRange(v, y, q0, q1)) return false;
1488 1488
1489 float s0 = 0, s1 = 0; 1489 double s0 = 0, s1 = 0;
1490 if (!getXBinRange(v, x, s0, s1)) return false; 1490 if (!getXBinRange(v, x, s0, s1)) return false;
1491 1491
1492 int q0i = int(q0 + 0.001); 1492 int q0i = int(q0 + 0.001);
1493 int q1i = int(q1); 1493 int q1i = int(q1);
1494 1494
1518 for (int s = s0i; s <= s1i; ++s) { 1518 for (int s = s0i; s <= s1i; ++s) {
1519 if (s >= 0 && q >= 0 && s < cw && q < ch) { 1519 if (s >= 0 && q >= 0 && s < cw && q < ch) {
1520 1520
1521 if (!fft->isColumnAvailable(s)) continue; 1521 if (!fft->isColumnAvailable(s)) continue;
1522 1522
1523 float value; 1523 double value;
1524 1524
1525 value = fft->getPhaseAt(s, q); 1525 value = fft->getPhaseAt(s, q);
1526 if (!have || value < phaseMin) { phaseMin = value; } 1526 if (!have || value < phaseMin) { phaseMin = value; }
1527 if (!have || value > phaseMax) { phaseMax = value; } 1527 if (!have || value > phaseMax) { phaseMax = value; }
1528 1528
1571 minbin = int((double(m_minFrequency) * m_fftSize) / sr + 0.1); 1571 minbin = int((double(m_minFrequency) * m_fftSize) / sr + 0.1);
1572 if (minbin < 1) minbin = 1; 1572 if (minbin < 1) minbin = 1;
1573 if (minbin >= maxbin) minbin = maxbin - 1; 1573 if (minbin >= maxbin) minbin = maxbin - 1;
1574 } 1574 }
1575 1575
1576 float perPixel = 1576 double perPixel =
1577 float(v->height()) / 1577 double(v->height()) /
1578 float((maxbin - minbin) / (m_zeroPadLevel + 1)); 1578 double((maxbin - minbin) / (m_zeroPadLevel + 1));
1579 1579
1580 if (perPixel > 2.8) { 1580 if (perPixel > 2.8) {
1581 return 3; // 4x oversampling 1581 return 3; // 4x oversampling
1582 } else if (perPixel > 1.5) { 1582 } else if (perPixel > 1.5) {
1583 return 1; // 2x 1583 return 1; // 2x
1722 SpectrogramLayer::updateViewMagnitudes(View *v) const 1722 SpectrogramLayer::updateViewMagnitudes(View *v) const
1723 { 1723 {
1724 MagnitudeRange mag; 1724 MagnitudeRange mag;
1725 1725
1726 int x0 = 0, x1 = v->width(); 1726 int x0 = 0, x1 = v->width();
1727 float s00 = 0, s01 = 0, s10 = 0, s11 = 0; 1727 double s00 = 0, s01 = 0, s10 = 0, s11 = 0;
1728 1728
1729 if (!getXBinRange(v, x0, s00, s01)) { 1729 if (!getXBinRange(v, x0, s00, s01)) {
1730 s00 = s01 = m_model->getStartFrame() / getWindowIncrement(); 1730 s00 = s01 = m_model->getStartFrame() / getWindowIncrement();
1731 } 1731 }
1732 1732
1828 bool recreateWholeImageCache = true; 1828 bool recreateWholeImageCache = true;
1829 1829
1830 x0 = rect.left(); 1830 x0 = rect.left();
1831 x1 = rect.right() + 1; 1831 x1 = rect.right() + 1;
1832 /* 1832 /*
1833 float xPixelRatio = float(fft->getResolution()) / float(zoomLevel); 1833 double xPixelRatio = double(fft->getResolution()) / double(zoomLevel);
1834 cerr << "xPixelRatio = " << xPixelRatio << endl; 1834 cerr << "xPixelRatio = " << xPixelRatio << endl;
1835 if (xPixelRatio < 1.f) xPixelRatio = 1.f; 1835 if (xPixelRatio < 1.f) xPixelRatio = 1.f;
1836 */ 1836 */
1837 if (cache.validArea.width() > 0) { 1837 if (cache.validArea.width() > 0) {
1838 1838
2135 2135
2136 int zpl = getZeroPadLevel(v) + 1; 2136 int zpl = getZeroPadLevel(v) + 1;
2137 minbin = minbin * zpl; 2137 minbin = minbin * zpl;
2138 maxbin = (maxbin + 1) * zpl - 1; 2138 maxbin = (maxbin + 1) * zpl - 1;
2139 2139
2140 float minFreq = (float(minbin) * sr) / fftSize; 2140 double minFreq = (double(minbin) * sr) / fftSize;
2141 float maxFreq = (float(maxbin) * sr) / fftSize; 2141 double maxFreq = (double(maxbin) * sr) / fftSize;
2142 2142
2143 float displayMinFreq = minFreq; 2143 double displayMinFreq = minFreq;
2144 float displayMaxFreq = maxFreq; 2144 double displayMaxFreq = maxFreq;
2145 2145
2146 if (fftSize != m_fftSize) { 2146 if (fftSize != m_fftSize) {
2147 displayMinFreq = getEffectiveMinFrequency(); 2147 displayMinFreq = getEffectiveMinFrequency();
2148 displayMaxFreq = getEffectiveMaxFrequency(); 2148 displayMaxFreq = getEffectiveMaxFrequency();
2149 } 2149 }
2152 2152
2153 int increment = getWindowIncrement(); 2153 int increment = getWindowIncrement();
2154 2154
2155 bool logarithmic = (m_frequencyScale == LogFrequencyScale); 2155 bool logarithmic = (m_frequencyScale == LogFrequencyScale);
2156 /* 2156 /*
2157 float yforbin[maxbin - minbin + 1]; 2157 double yforbin[maxbin - minbin + 1];
2158 2158
2159 for (int q = minbin; q <= maxbin; ++q) { 2159 for (int q = minbin; q <= maxbin; ++q) {
2160 float f0 = (float(q) * sr) / fftSize; 2160 double f0 = (double(q) * sr) / fftSize;
2161 yforbin[q - minbin] = 2161 yforbin[q - minbin] =
2162 v->getYForFrequency(f0, displayMinFreq, displayMaxFreq, 2162 v->getYForFrequency(f0, displayMinFreq, displayMaxFreq,
2163 logarithmic); 2163 logarithmic);
2164 } 2164 }
2165 */ 2165 */
2166 MagnitudeRange overallMag = m_viewMags[v]; 2166 MagnitudeRange overallMag = m_viewMags[v];
2167 bool overallMagChanged = false; 2167 bool overallMagChanged = false;
2168 2168
2169 #ifdef DEBUG_SPECTROGRAM_REPAINT 2169 #ifdef DEBUG_SPECTROGRAM_REPAINT
2170 cerr << ((float(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << endl; 2170 cerr << ((double(v->getFrameForX(1) - v->getFrameForX(0))) / increment) << " bin(s) per pixel" << endl;
2171 #endif 2171 #endif
2172 2172
2173 if (w == 0) { 2173 if (w == 0) {
2174 SVDEBUG << "*** NOTE: w == 0" << endl; 2174 SVDEBUG << "*** NOTE: w == 0" << endl;
2175 } 2175 }
2229 bufwid = w; 2229 bufwid = w;
2230 } 2230 }
2231 2231
2232 #ifdef __GNUC__ 2232 #ifdef __GNUC__
2233 int binforx[bufwid]; 2233 int binforx[bufwid];
2234 float binfory[h]; 2234 double binfory[h];
2235 #else 2235 #else
2236 int *binforx = (int *)alloca(bufwid * sizeof(int)); 2236 int *binforx = (int *)alloca(bufwid * sizeof(int));
2237 float *binfory = (float *)alloca(h * sizeof(float)); 2237 double *binfory = (double *)alloca(h * sizeof(double));
2238 #endif 2238 #endif
2239 2239
2240 bool usePeaksCache = false; 2240 bool usePeaksCache = false;
2241 2241
2242 if (bufferBinResolution) { 2242 if (bufferBinResolution) {
2245 // cerr << "binforx[" << x << "] = " << binforx[x] << endl; 2245 // cerr << "binforx[" << x << "] = " << binforx[x] << endl;
2246 } 2246 }
2247 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8); 2247 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8);
2248 } else { 2248 } else {
2249 for (int x = 0; x < bufwid; ++x) { 2249 for (int x = 0; x < bufwid; ++x) {
2250 float s0 = 0, s1 = 0; 2250 double s0 = 0, s1 = 0;
2251 if (getXBinRange(v, x + x0, s0, s1)) { 2251 if (getXBinRange(v, x + x0, s0, s1)) {
2252 binforx[x] = int(s0 + 0.0001); 2252 binforx[x] = int(s0 + 0.0001);
2253 } else { 2253 } else {
2254 binforx[x] = -1; //??? 2254 binforx[x] = -1; //???
2255 } 2255 }
2269 m_drawBuffer.fill(0); 2269 m_drawBuffer.fill(0);
2270 2270
2271 if (m_binDisplay != PeakFrequencies) { 2271 if (m_binDisplay != PeakFrequencies) {
2272 2272
2273 for (int y = 0; y < h; ++y) { 2273 for (int y = 0; y < h; ++y) {
2274 float q0 = 0, q1 = 0; 2274 double q0 = 0, q1 = 0;
2275 if (!getSmoothedYBinRange(v, h-y-1, q0, q1)) { 2275 if (!getSmoothedYBinRange(v, h-y-1, q0, q1)) {
2276 binfory[y] = -1; 2276 binfory[y] = -1;
2277 } else { 2277 } else {
2278 binfory[y] = q0; 2278 binfory[y] = q0;
2279 // cerr << "binfory[" << y << "] = " << binfory[y] << endl; 2279 // cerr << "binfory[" << y << "] = " << binfory[y] << endl;
2458 int w, 2458 int w,
2459 int h, 2459 int h,
2460 int *binforx, 2460 int *binforx,
2461 int minbin, 2461 int minbin,
2462 int maxbin, 2462 int maxbin,
2463 float displayMinFreq, 2463 double displayMinFreq,
2464 float displayMaxFreq, 2464 double displayMaxFreq,
2465 bool logarithmic, 2465 bool logarithmic,
2466 MagnitudeRange &overallMag, 2466 MagnitudeRange &overallMag,
2467 bool &overallMagChanged) const 2467 bool &overallMagChanged) const
2468 { 2468 {
2469 Profiler profiler("SpectrogramLayer::paintDrawBufferPeakFrequencies"); 2469 Profiler profiler("SpectrogramLayer::paintDrawBufferPeakFrequencies");
2520 fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1); 2520 fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1);
2521 } else if (m_normalizeColumns) { 2521 } else if (m_normalizeColumns) {
2522 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); 2522 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
2523 } else if (m_normalizeHybrid) { 2523 } else if (m_normalizeHybrid) {
2524 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); 2524 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
2525 float max = fft->getMaximumMagnitudeAt(sx); 2525 double max = fft->getMaximumMagnitudeAt(sx);
2526 if (max > 0.f) { 2526 if (max > 0.f) {
2527 for (int i = minbin; i <= maxbin; ++i) { 2527 for (int i = minbin; i <= maxbin; ++i) {
2528 values[i - minbin] *= log10(max); 2528 values[i - minbin] *= log10(max);
2529 } 2529 }
2530 } 2530 }
2551 } 2551 }
2552 mag.sample(value); 2552 mag.sample(value);
2553 value *= m_gain; 2553 value *= m_gain;
2554 } 2554 }
2555 2555
2556 float y = v->getYForFrequency 2556 double y = v->getYForFrequency
2557 (freq, displayMinFreq, displayMaxFreq, logarithmic); 2557 (freq, displayMinFreq, displayMaxFreq, logarithmic);
2558 2558
2559 int iy = int(y + 0.5); 2559 int iy = int(y + 0.5);
2560 if (iy < 0 || iy >= h) continue; 2560 if (iy < 0 || iy >= h) continue;
2561 2561
2584 bool 2584 bool
2585 SpectrogramLayer::paintDrawBuffer(View *v, 2585 SpectrogramLayer::paintDrawBuffer(View *v,
2586 int w, 2586 int w,
2587 int h, 2587 int h,
2588 int *binforx, 2588 int *binforx,
2589 float *binfory, 2589 double *binfory,
2590 bool usePeaksCache, 2590 bool usePeaksCache,
2591 MagnitudeRange &overallMag, 2591 MagnitudeRange &overallMag,
2592 bool &overallMagChanged) const 2592 bool &overallMagChanged) const
2593 { 2593 {
2594 Profiler profiler("SpectrogramLayer::paintDrawBuffer"); 2594 Profiler profiler("SpectrogramLayer::paintDrawBuffer");
2687 fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1); 2687 fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1);
2688 } else if (m_normalizeColumns) { 2688 } else if (m_normalizeColumns) {
2689 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); 2689 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1);
2690 } else if (m_normalizeHybrid) { 2690 } else if (m_normalizeHybrid) {
2691 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); 2691 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1);
2692 float max = fft->getMaximumMagnitudeAt(sx); 2692 double max = fft->getMaximumMagnitudeAt(sx);
2693 for (int i = minbin; i <= maxbin; ++i) { 2693 for (int i = minbin; i <= maxbin; ++i) {
2694 if (max > 0.f) { 2694 if (max > 0.f) {
2695 autoarray[i - minbin] *= log10(max); 2695 autoarray[i - minbin] *= log10(max);
2696 } 2696 }
2697 } 2697 }
2713 psx = sx; 2713 psx = sx;
2714 } 2714 }
2715 2715
2716 for (int y = 0; y < h; ++y) { 2716 for (int y = 0; y < h; ++y) {
2717 2717
2718 float sy0 = binfory[y]; 2718 double sy0 = binfory[y];
2719 float sy1 = sy0 + 1; 2719 double sy1 = sy0 + 1;
2720 if (y+1 < h) sy1 = binfory[y+1]; 2720 if (y+1 < h) sy1 = binfory[y+1];
2721 2721
2722 float value = 0.f; 2722 double value = 0.f;
2723 2723
2724 if (interpolate && fabsf(sy1 - sy0) < 1.f) { 2724 if (interpolate && fabsf(sy1 - sy0) < 1.f) {
2725 2725
2726 float centre = (sy0 + sy1) / 2; 2726 double centre = (sy0 + sy1) / 2;
2727 float dist = (centre - 0.5) - lrintf(centre - 0.5); 2727 double dist = (centre - 0.5) - lrintf(centre - 0.5);
2728 int bin = int(centre); 2728 int bin = int(centre);
2729 int other = (dist < 0 ? (bin-1) : (bin+1)); 2729 int other = (dist < 0 ? (bin-1) : (bin+1));
2730 if (bin < minbin) bin = minbin; 2730 if (bin < minbin) bin = minbin;
2731 if (bin > maxbin) bin = maxbin; 2731 if (bin > maxbin) bin = maxbin;
2732 if (other < minbin || other > maxbin) other = bin; 2732 if (other < minbin || other > maxbin) other = bin;
2733 float prop = 1.f - fabsf(dist); 2733 double prop = 1.f - fabsf(dist);
2734 2734
2735 float v0 = values[bin - minbin]; 2735 double v0 = values[bin - minbin];
2736 float v1 = values[other - minbin]; 2736 double v1 = values[other - minbin];
2737 if (m_binDisplay == PeakBins) { 2737 if (m_binDisplay == PeakBins) {
2738 if (bin == minbin || bin == maxbin || 2738 if (bin == minbin || bin == maxbin ||
2739 v0 < values[bin-minbin-1] || 2739 v0 < values[bin-minbin-1] ||
2740 v0 < values[bin-minbin+1]) v0 = 0.f; 2740 v0 < values[bin-minbin+1]) v0 = 0.f;
2741 if (other == minbin || other == maxbin || 2741 if (other == minbin || other == maxbin ||
2798 } 2798 }
2799 } 2799 }
2800 2800
2801 for (int y = 0; y < h; ++y) { 2801 for (int y = 0; y < h; ++y) {
2802 2802
2803 float peak = peaks[y]; 2803 double peak = peaks[y];
2804 2804
2805 if (m_colourScale != PhaseColourScale && 2805 if (m_colourScale != PhaseColourScale &&
2806 (m_normalizeColumns || m_normalizeHybrid) && 2806 (m_normalizeColumns || m_normalizeHybrid) &&
2807 columnMax > 0.f) { 2807 columnMax > 0.f) {
2808 peak /= columnMax; 2808 peak /= columnMax;
2831 } 2831 }
2832 2832
2833 // cerr << "SpectrogramLayer: illuminateLocalFeatures(" 2833 // cerr << "SpectrogramLayer: illuminateLocalFeatures("
2834 // << localPos.x() << "," << localPos.y() << ")" << endl; 2834 // << localPos.x() << "," << localPos.y() << ")" << endl;
2835 2835
2836 float s0, s1; 2836 double s0, s1;
2837 float f0, f1; 2837 double f0, f1;
2838 2838
2839 if (getXBinRange(v, localPos.x(), s0, s1) && 2839 if (getXBinRange(v, localPos.x(), s0, s1) &&
2840 getYBinSourceRange(v, localPos.y(), f0, f1)) { 2840 getYBinSourceRange(v, localPos.y(), f0, f1)) {
2841 2841
2842 int s0i = int(s0 + 0.001); 2842 int s0i = int(s0 + 0.001);
2857 2857
2858 paint.drawRect(x0, y1, x1 - x0 + 1, y0 - y1 + 1); 2858 paint.drawRect(x0, y1, x1 - x0 + 1, y0 - y1 + 1);
2859 } 2859 }
2860 } 2860 }
2861 2861
2862 float 2862 double
2863 SpectrogramLayer::getYForFrequency(const View *v, float frequency) const 2863 SpectrogramLayer::getYForFrequency(const View *v, double frequency) const
2864 { 2864 {
2865 return v->getYForFrequency(frequency, 2865 return v->getYForFrequency(frequency,
2866 getEffectiveMinFrequency(), 2866 getEffectiveMinFrequency(),
2867 getEffectiveMaxFrequency(), 2867 getEffectiveMaxFrequency(),
2868 m_frequencyScale == LogFrequencyScale); 2868 m_frequencyScale == LogFrequencyScale);
2869 } 2869 }
2870 2870
2871 float 2871 double
2872 SpectrogramLayer::getFrequencyForY(const View *v, int y) const 2872 SpectrogramLayer::getFrequencyForY(const View *v, int y) const
2873 { 2873 {
2874 return v->getFrequencyForY(y, 2874 return v->getFrequencyForY(y,
2875 getEffectiveMinFrequency(), 2875 getEffectiveMinFrequency(),
2876 getEffectiveMaxFrequency(), 2876 getEffectiveMaxFrequency(),
2896 if (m_fftModels.find(v) == m_fftModels.end()) return ""; 2896 if (m_fftModels.find(v) == m_fftModels.end()) return "";
2897 return m_fftModels[v].first->getError(); 2897 return m_fftModels[v].first->getError();
2898 } 2898 }
2899 2899
2900 bool 2900 bool
2901 SpectrogramLayer::getValueExtents(float &min, float &max, 2901 SpectrogramLayer::getValueExtents(double &min, double &max,
2902 bool &logarithmic, QString &unit) const 2902 bool &logarithmic, QString &unit) const
2903 { 2903 {
2904 if (!m_model) return false; 2904 if (!m_model) return false;
2905 2905
2906 int sr = m_model->getSampleRate(); 2906 int sr = m_model->getSampleRate();
2907 min = float(sr) / m_fftSize; 2907 min = double(sr) / m_fftSize;
2908 max = float(sr) / 2; 2908 max = double(sr) / 2;
2909 2909
2910 logarithmic = (m_frequencyScale == LogFrequencyScale); 2910 logarithmic = (m_frequencyScale == LogFrequencyScale);
2911 unit = "Hz"; 2911 unit = "Hz";
2912 return true; 2912 return true;
2913 } 2913 }
2914 2914
2915 bool 2915 bool
2916 SpectrogramLayer::getDisplayExtents(float &min, float &max) const 2916 SpectrogramLayer::getDisplayExtents(double &min, double &max) const
2917 { 2917 {
2918 min = getEffectiveMinFrequency(); 2918 min = getEffectiveMinFrequency();
2919 max = getEffectiveMaxFrequency(); 2919 max = getEffectiveMaxFrequency();
2920 2920
2921 // SVDEBUG << "SpectrogramLayer::getDisplayExtents: " << min << "->" << max << endl; 2921 // SVDEBUG << "SpectrogramLayer::getDisplayExtents: " << min << "->" << max << endl;
2922 return true; 2922 return true;
2923 } 2923 }
2924 2924
2925 bool 2925 bool
2926 SpectrogramLayer::setDisplayExtents(float min, float max) 2926 SpectrogramLayer::setDisplayExtents(double min, double max)
2927 { 2927 {
2928 if (!m_model) return false; 2928 if (!m_model) return false;
2929 2929
2930 // SVDEBUG << "SpectrogramLayer::setDisplayExtents: " << min << "->" << max << endl; 2930 // SVDEBUG << "SpectrogramLayer::setDisplayExtents: " << min << "->" << max << endl;
2931 2931
2954 return true; 2954 return true;
2955 } 2955 }
2956 2956
2957 bool 2957 bool
2958 SpectrogramLayer::getYScaleValue(const View *v, int y, 2958 SpectrogramLayer::getYScaleValue(const View *v, int y,
2959 float &value, QString &unit) const 2959 double &value, QString &unit) const
2960 { 2960 {
2961 value = getFrequencyForY(v, y); 2961 value = getFrequencyForY(v, y);
2962 unit = "Hz"; 2962 unit = "Hz";
2963 return true; 2963 return true;
2964 } 2964 }
3060 paint.setPen(m_crosshairColour); 3060 paint.setPen(m_crosshairColour);
3061 3061
3062 paint.drawLine(0, cursorPos.y(), cursorPos.x() - 1, cursorPos.y()); 3062 paint.drawLine(0, cursorPos.y(), cursorPos.x() - 1, cursorPos.y());
3063 paint.drawLine(cursorPos.x(), 0, cursorPos.x(), v->height()); 3063 paint.drawLine(cursorPos.x(), 0, cursorPos.x(), v->height());
3064 3064
3065 float fundamental = getFrequencyForY(v, cursorPos.y()); 3065 double fundamental = getFrequencyForY(v, cursorPos.y());
3066 3066
3067 v->drawVisibleText(paint, 3067 v->drawVisibleText(paint,
3068 sw + 2, 3068 sw + 2,
3069 cursorPos.y() - 2, 3069 cursorPos.y() - 2,
3070 QString("%1 Hz").arg(fundamental), 3070 QString("%1 Hz").arg(fundamental),
3096 3096
3097 int harmonic = 2; 3097 int harmonic = 2;
3098 3098
3099 while (harmonic < 100) { 3099 while (harmonic < 100) {
3100 3100
3101 float hy = lrintf(getYForFrequency(v, fundamental * harmonic)); 3101 double hy = lrintf(getYForFrequency(v, fundamental * harmonic));
3102 if (hy < 0 || hy > v->height()) break; 3102 if (hy < 0 || hy > v->height()) break;
3103 3103
3104 int len = 7; 3104 int len = 7;
3105 3105
3106 if (harmonic % 2 == 0) { 3106 if (harmonic % 2 == 0) {
3128 int x = pos.x(); 3128 int x = pos.x();
3129 int y = pos.y(); 3129 int y = pos.y();
3130 3130
3131 if (!m_model || !m_model->isOK()) return ""; 3131 if (!m_model || !m_model->isOK()) return "";
3132 3132
3133 float magMin = 0, magMax = 0; 3133 double magMin = 0, magMax = 0;
3134 float phaseMin = 0, phaseMax = 0; 3134 double phaseMin = 0, phaseMax = 0;
3135 float freqMin = 0, freqMax = 0; 3135 double freqMin = 0, freqMax = 0;
3136 float adjFreqMin = 0, adjFreqMax = 0; 3136 double adjFreqMin = 0, adjFreqMax = 0;
3137 QString pitchMin, pitchMax; 3137 QString pitchMin, pitchMax;
3138 RealTime rtMin, rtMax; 3138 RealTime rtMin, rtMax;
3139 3139
3140 bool haveValues = false; 3140 bool haveValues = false;
3141 3141
3203 .arg(adjPitchText) 3203 .arg(adjPitchText)
3204 .arg(Pitch::getPitchLabelForFrequency(freqMin)); 3204 .arg(Pitch::getPitchLabelForFrequency(freqMin));
3205 } 3205 }
3206 3206
3207 if (haveValues) { 3207 if (haveValues) {
3208 float dbMin = AudioLevel::multiplier_to_dB(magMin); 3208 double dbMin = AudioLevel::multiplier_to_dB(magMin);
3209 float dbMax = AudioLevel::multiplier_to_dB(magMax); 3209 double dbMax = AudioLevel::multiplier_to_dB(magMax);
3210 QString dbMinString; 3210 QString dbMinString;
3211 QString dbMaxString; 3211 QString dbMaxString;
3212 if (dbMin == AudioLevel::DB_FLOOR) { 3212 if (dbMin == AudioLevel::DB_FLOOR) {
3213 dbMinString = tr("-Inf"); 3213 dbMinString = tr("-Inf");
3214 } else { 3214 } else {
3306 int ch = h - textHeight * (topLines + 1) - 8; 3306 int ch = h - textHeight * (topLines + 1) - 8;
3307 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1); 3307 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1);
3308 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1); 3308 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1);
3309 3309
3310 QString top, bottom; 3310 QString top, bottom;
3311 float min = m_viewMags[v].getMin(); 3311 double min = m_viewMags[v].getMin();
3312 float max = m_viewMags[v].getMax(); 3312 double max = m_viewMags[v].getMax();
3313 3313
3314 float dBmin = AudioLevel::multiplier_to_dB(min); 3314 double dBmin = AudioLevel::multiplier_to_dB(min);
3315 float dBmax = AudioLevel::multiplier_to_dB(max); 3315 double dBmax = AudioLevel::multiplier_to_dB(max);
3316 3316
3317 if (dBmax < -60.f) dBmax = -60.f; 3317 if (dBmax < -60.f) dBmax = -60.f;
3318 else top = QString("%1").arg(lrintf(dBmax)); 3318 else top = QString("%1").arg(lrintf(dBmax));
3319 3319
3320 if (dBmin < dBmax - 60.f) dBmin = dBmax - 60.f; 3320 if (dBmin < dBmax - 60.f) dBmin = dBmax - 60.f;
3340 int lasty = 0; 3340 int lasty = 0;
3341 int lastdb = 0; 3341 int lastdb = 0;
3342 3342
3343 for (int i = 0; i < ch; ++i) { 3343 for (int i = 0; i < ch; ++i) {
3344 3344
3345 float dBval = dBmin + (((dBmax - dBmin) * i) / (ch - 1)); 3345 double dBval = dBmin + (((dBmax - dBmin) * i) / (ch - 1));
3346 int idb = int(dBval); 3346 int idb = int(dBval);
3347 3347
3348 float value = AudioLevel::dB_to_multiplier(dBval); 3348 double value = AudioLevel::dB_to_multiplier(dBval);
3349 int colour = getDisplayValue(v, value * m_gain); 3349 int colour = getDisplayValue(v, value * m_gain);
3350 3350
3351 paint.setPen(m_palette.getColour(colour)); 3351 paint.setPen(m_palette.getColour(colour));
3352 3352
3353 int y = textHeight * topLines + 4 + ch - i; 3353 int y = textHeight * topLines + 4 + ch - i;
3380 3380
3381 int bin = -1; 3381 int bin = -1;
3382 3382
3383 for (int y = 0; y < v->height(); ++y) { 3383 for (int y = 0; y < v->height(); ++y) {
3384 3384
3385 float q0, q1; 3385 double q0, q1;
3386 if (!getYBinRange(v, v->height() - y, q0, q1)) continue; 3386 if (!getYBinRange(v, v->height() - y, q0, q1)) continue;
3387 3387
3388 int vy; 3388 int vy;
3389 3389
3390 if (int(q0) > bin) { 3390 if (int(q0) > bin) {
3491 3491
3492 int sr = m_model->getSampleRate(); 3492 int sr = m_model->getSampleRate();
3493 3493
3494 SpectrogramRangeMapper mapper(sr, m_fftSize); 3494 SpectrogramRangeMapper mapper(sr, m_fftSize);
3495 3495
3496 // int maxStep = mapper.getPositionForValue((float(sr) / m_fftSize) + 0.001); 3496 // int maxStep = mapper.getPositionForValue((double(sr) / m_fftSize) + 0.001);
3497 int maxStep = mapper.getPositionForValue(0); 3497 int maxStep = mapper.getPositionForValue(0);
3498 int minStep = mapper.getPositionForValue(float(sr) / 2); 3498 int minStep = mapper.getPositionForValue(double(sr) / 2);
3499 3499
3500 int initialMax = m_initialMaxFrequency; 3500 int initialMax = m_initialMaxFrequency;
3501 if (initialMax == 0) initialMax = sr / 2; 3501 if (initialMax == 0) initialMax = sr / 2;
3502 3502
3503 defaultStep = mapper.getPositionForValue(initialMax) - minStep; 3503 defaultStep = mapper.getPositionForValue(initialMax) - minStep;
3510 int 3510 int
3511 SpectrogramLayer::getCurrentVerticalZoomStep() const 3511 SpectrogramLayer::getCurrentVerticalZoomStep() const
3512 { 3512 {
3513 if (!m_model) return 0; 3513 if (!m_model) return 0;
3514 3514
3515 float dmin, dmax; 3515 double dmin, dmax;
3516 getDisplayExtents(dmin, dmax); 3516 getDisplayExtents(dmin, dmax);
3517 3517
3518 SpectrogramRangeMapper mapper(m_model->getSampleRate(), m_fftSize); 3518 SpectrogramRangeMapper mapper(m_model->getSampleRate(), m_fftSize);
3519 int n = mapper.getPositionForValue(dmax - dmin); 3519 int n = mapper.getPositionForValue(dmax - dmin);
3520 // SVDEBUG << "SpectrogramLayer::getCurrentVerticalZoomStep: " << n << endl; 3520 // SVDEBUG << "SpectrogramLayer::getCurrentVerticalZoomStep: " << n << endl;
3524 void 3524 void
3525 SpectrogramLayer::setVerticalZoomStep(int step) 3525 SpectrogramLayer::setVerticalZoomStep(int step)
3526 { 3526 {
3527 if (!m_model) return; 3527 if (!m_model) return;
3528 3528
3529 float dmin = m_minFrequency, dmax = m_maxFrequency; 3529 double dmin = m_minFrequency, dmax = m_maxFrequency;
3530 // getDisplayExtents(dmin, dmax); 3530 // getDisplayExtents(dmin, dmax);
3531 3531
3532 // cerr << "current range " << dmin << " -> " << dmax << ", range " << dmax-dmin << ", mid " << (dmax + dmin)/2 << endl; 3532 // cerr << "current range " << dmin << " -> " << dmax << ", range " << dmax-dmin << ", mid " << (dmax + dmin)/2 << endl;
3533 3533
3534 int sr = m_model->getSampleRate(); 3534 int sr = m_model->getSampleRate();
3535 SpectrogramRangeMapper mapper(sr, m_fftSize); 3535 SpectrogramRangeMapper mapper(sr, m_fftSize);
3536 float newdist = mapper.getValueForPosition(step); 3536 double newdist = mapper.getValueForPosition(step);
3537 3537
3538 float newmin, newmax; 3538 double newmin, newmax;
3539 3539
3540 if (m_frequencyScale == LogFrequencyScale) { 3540 if (m_frequencyScale == LogFrequencyScale) {
3541 3541
3542 // need to pick newmin and newmax such that 3542 // need to pick newmin and newmax such that
3543 // 3543 //
3564 newmin = newmax - newdist; 3564 newmin = newmax - newdist;
3565 3565
3566 // cerr << "newmin = " << newmin << ", newmax = " << newmax << endl; 3566 // cerr << "newmin = " << newmin << ", newmax = " << newmax << endl;
3567 3567
3568 } else { 3568 } else {
3569 float dmid = (dmax + dmin) / 2; 3569 double dmid = (dmax + dmin) / 2;
3570 newmin = dmid - newdist / 2; 3570 newmin = dmid - newdist / 2;
3571 newmax = dmid + newdist / 2; 3571 newmax = dmid + newdist / 2;
3572 } 3572 }
3573 3573
3574 float mmin, mmax; 3574 double mmin, mmax;
3575 mmin = 0; 3575 mmin = 0;
3576 mmax = float(sr) / 2; 3576 mmax = double(sr) / 2;
3577 3577
3578 if (newmin < mmin) { 3578 if (newmin < mmin) {
3579 newmax += (mmin - newmin); 3579 newmax += (mmin - newmin);
3580 newmin = mmin; 3580 newmin = mmin;
3581 } 3581 }