comparison layer/SpectrogramLayer.cpp @ 107:bf196d6e8998

* Separate out window and FFT size variables. Not necessarily correct for frequency estimation code.
author Chris Cannam
date Mon, 19 Jun 2006 16:14:16 +0000
parents 1348818e7be7
children 12340cb6e6cb
comparison
equal deleted inserted replaced
106:551d7ae05526 107:bf196d6e8998
66 m_model(0), 66 m_model(0),
67 m_channel(0), 67 m_channel(0),
68 m_windowSize(1024), 68 m_windowSize(1024),
69 m_windowType(HanningWindow), 69 m_windowType(HanningWindow),
70 m_windowHopLevel(2), 70 m_windowHopLevel(2),
71 m_fftSize(1024),
71 m_gain(1.0), 72 m_gain(1.0),
72 m_threshold(0.0), 73 m_threshold(0.0),
73 m_colourRotation(0), 74 m_colourRotation(0),
74 m_minFrequency(0), 75 m_minFrequency(0),
75 m_maxFrequency(8000), 76 m_maxFrequency(8000),
582 m_mutex.lock(); 583 m_mutex.lock();
583 m_cacheInvalid = true; 584 m_cacheInvalid = true;
584 invalidatePixmapCaches(); 585 invalidatePixmapCaches();
585 586
586 m_windowSize = ws; 587 m_windowSize = ws;
588 m_fftSize = ws;
587 589
588 m_mutex.unlock(); 590 m_mutex.unlock();
589 591
590 emit layerParametersChanged(); 592 emit layerParametersChanged();
591 593
1111 steadyState = false; 1113 steadyState = false;
1112 return frequency; 1114 return frequency;
1113 } 1115 }
1114 1116
1115 void 1117 void
1116 SpectrogramLayer::fillCacheColumn(int column, fftsample *input, 1118 SpectrogramLayer::fillCacheColumn(int column,
1119 fftsample *input,
1117 fftwf_complex *output, 1120 fftwf_complex *output,
1118 fftwf_plan plan, 1121 fftwf_plan plan,
1119 size_t windowSize, 1122 size_t windowSize,
1123 size_t fftSize,
1120 size_t increment, 1124 size_t increment,
1121 float *workbuffer, 1125 float *workbuffer,
1122 const Window<fftsample> &windower) const 1126 const Window<fftsample> &windower) const
1123 { 1127 {
1124 //!!! we _do_ need a lock for these references to the model 1128 //!!! we _do_ need a lock for these references to the model
1129 1133
1130 startFrame -= int(windowSize - increment) / 2; 1134 startFrame -= int(windowSize - increment) / 2;
1131 endFrame -= int(windowSize - increment) / 2; 1135 endFrame -= int(windowSize - increment) / 2;
1132 size_t pfx = 0; 1136 size_t pfx = 0;
1133 1137
1138 size_t off = (m_fftSize - m_windowSize) / 2;
1139
1140 for (size_t i = 0; i < off; ++i) {
1141 input[i] = 0.0;
1142 input[m_fftSize - i - 1] = 0.0;
1143 }
1144
1134 if (startFrame < 0) { 1145 if (startFrame < 0) {
1135 pfx = size_t(-startFrame); 1146 pfx = size_t(-startFrame);
1136 for (size_t i = 0; i < pfx; ++i) { 1147 for (size_t i = 0; i < pfx; ++i) {
1137 input[i] = 0.0; 1148 input[off + i] = 0.0;
1138 } 1149 }
1139 } 1150 }
1140 1151
1141 size_t got = m_model->getValues(m_channel, startFrame + pfx, 1152 size_t got = m_model->getValues(m_channel, startFrame + pfx,
1142 endFrame, input + pfx); 1153 endFrame, input + pfx);
1143 while (got + pfx < windowSize) { 1154 while (got + pfx < windowSize) {
1144 input[got + pfx] = 0.0; 1155 input[off + got + pfx] = 0.0;
1145 ++got; 1156 ++got;
1146 } 1157 }
1147 1158
1148 if (m_channel == -1) { 1159 if (m_channel == -1) {
1149 int channels = m_model->getChannelCount(); 1160 int channels = m_model->getChannelCount();
1150 if (channels > 1) { 1161 if (channels > 1) {
1151 for (size_t i = 0; i < windowSize; ++i) { 1162 for (size_t i = 0; i < windowSize; ++i) {
1152 input[i] /= channels; 1163 input[off + i] /= channels;
1153 } 1164 }
1154 } 1165 }
1155 } 1166 }
1156 1167
1157 windower.cut(input); 1168 windower.cut(input);
1158 1169
1159 for (size_t i = 0; i < windowSize/2; ++i) { 1170 for (size_t i = 0; i < windowSize/2; ++i) {
1160 fftsample temp = input[i]; 1171 fftsample temp = input[off + i];
1161 input[i] = input[i + windowSize/2]; 1172 input[off + i] = input[off + i + windowSize/2];
1162 input[i + windowSize/2] = temp; 1173 input[off + i + windowSize/2] = temp;
1163 } 1174 }
1164 1175
1165 fftwf_execute(plan); 1176 fftwf_execute(plan);
1166 1177
1167 fftsample factor = 0.0; 1178 fftsample factor = 0.0;
1168 1179
1169 for (size_t i = 0; i < windowSize/2; ++i) { 1180 for (size_t i = 0; i < fftSize/2; ++i) {
1170 1181
1171 fftsample mag = sqrtf(output[i][0] * output[i][0] + 1182 fftsample mag = sqrtf(output[i][0] * output[i][0] +
1172 output[i][1] * output[i][1]); 1183 output[i][1] * output[i][1]);
1173 mag /= windowSize / 2; 1184 mag /= fftSize / 2;
1174 1185
1175 if (mag > factor) factor = mag; 1186 if (mag > factor) factor = mag;
1176 1187
1177 fftsample phase = atan2f(output[i][1], output[i][0]); 1188 fftsample phase = atan2f(output[i][1], output[i][0]);
1178 phase = princargf(phase); 1189 phase = princargf(phase);
1179 1190
1180 workbuffer[i] = mag; 1191 workbuffer[i] = mag;
1181 workbuffer[i + windowSize/2] = phase; 1192 workbuffer[i + fftSize/2] = phase;
1182 } 1193 }
1183 1194
1184 m_writeCache->setColumnAt(column, workbuffer, 1195 m_writeCache->setColumnAt(column, workbuffer,
1185 workbuffer + windowSize/2, factor); 1196 workbuffer + fftSize/2, factor);
1186 } 1197 }
1187 1198
1188 unsigned char 1199 unsigned char
1189 SpectrogramLayer::getDisplayValue(float input) const 1200 SpectrogramLayer::getDisplayValue(float input) const
1190 { 1201 {
1312 // std::cerr << "start = " << start << ", end = " << end << std::endl; 1323 // std::cerr << "start = " << start << ", end = " << end << std::endl;
1313 1324
1314 WindowType windowType = m_layer.m_windowType; 1325 WindowType windowType = m_layer.m_windowType;
1315 size_t windowSize = m_layer.m_windowSize; 1326 size_t windowSize = m_layer.m_windowSize;
1316 size_t windowIncrement = m_layer.getWindowIncrement(); 1327 size_t windowIncrement = m_layer.getWindowIncrement();
1328 size_t fftSize = m_layer.m_fftSize;
1317 1329
1318 // std::cerr << "\nWINDOW INCREMENT: " << windowIncrement << " (for hop level " << m_layer.m_windowHopLevel << ")\n" << std::endl; 1330 // std::cerr << "\nWINDOW INCREMENT: " << windowIncrement << " (for hop level " << m_layer.m_windowHopLevel << ")\n" << std::endl;
1319 1331
1320 size_t visibleStart = m_layer.m_candidateFillStartFrame; 1332 size_t visibleStart = m_layer.m_candidateFillStartFrame;
1321 visibleStart = (visibleStart / windowIncrement) * windowIncrement; 1333 visibleStart = (visibleStart / windowIncrement) * windowIncrement;
1322 1334
1323 size_t width = (end - start) / windowIncrement + 1; 1335 size_t width = (end - start) / windowIncrement + 1;
1324 size_t height = windowSize / 2; 1336 size_t height = fftSize / 2;
1325 1337
1326 //!!! if (!m_layer.m_cache) { 1338 //!!! if (!m_layer.m_cache) {
1327 // m_layer.m_cache = new FFTMemoryCache; 1339 // m_layer.m_cache = new FFTMemoryCache;
1328 // } 1340 // }
1329 if (!m_layer.m_writeCache) { 1341 if (!m_layer.m_writeCache) {
1339 1351
1340 m_layer.setColourmap(); 1352 m_layer.setColourmap();
1341 //!!! m_layer.m_writeCache->reset(); 1353 //!!! m_layer.m_writeCache->reset();
1342 1354
1343 fftsample *input = (fftsample *) 1355 fftsample *input = (fftsample *)
1344 fftwf_malloc(windowSize * sizeof(fftsample)); 1356 fftwf_malloc(fftSize * sizeof(fftsample));
1345 1357
1346 fftwf_complex *output = (fftwf_complex *) 1358 fftwf_complex *output = (fftwf_complex *)
1347 fftwf_malloc(windowSize * sizeof(fftwf_complex)); 1359 fftwf_malloc(fftSize * sizeof(fftwf_complex));
1348 1360
1349 float *workbuffer = (float *) 1361 float *workbuffer = (float *)
1350 fftwf_malloc(windowSize * sizeof(float)); 1362 fftwf_malloc(fftSize * sizeof(float));
1351 1363
1352 fftwf_plan plan = fftwf_plan_dft_r2c_1d(windowSize, input, 1364 fftwf_plan plan = fftwf_plan_dft_r2c_1d(fftSize, input,
1353 output, FFTW_ESTIMATE); 1365 output, FFTW_ESTIMATE);
1354 1366
1355 if (!plan) { 1367 if (!plan) {
1356 std::cerr << "WARNING: fftwf_plan_dft_r2c_1d(" << windowSize << ") failed!" << std::endl; 1368 std::cerr << "WARNING: fftwf_plan_dft_r2c_1d(" << windowSize << ") failed!" << std::endl;
1357 fftwf_free(input); 1369 fftwf_free(input);
1383 1395
1384 for (size_t f = visibleStart; f < end; f += windowIncrement) { 1396 for (size_t f = visibleStart; f < end; f += windowIncrement) {
1385 1397
1386 m_layer.fillCacheColumn(int((f - start) / windowIncrement), 1398 m_layer.fillCacheColumn(int((f - start) / windowIncrement),
1387 input, output, plan, 1399 input, output, plan,
1388 windowSize, windowIncrement, 1400 windowSize, fftSize,
1401 windowIncrement,
1389 workbuffer, windower); 1402 workbuffer, windower);
1390 1403
1391 if (m_layer.m_cacheInvalid || m_layer.m_exiting) { 1404 if (m_layer.m_cacheInvalid || m_layer.m_exiting) {
1392 interrupted = true; 1405 interrupted = true;
1393 m_fillExtent = 0; 1406 m_fillExtent = 0;
1415 1428
1416 for (size_t f = start; f < remainingEnd; f += windowIncrement) { 1429 for (size_t f = start; f < remainingEnd; f += windowIncrement) {
1417 1430
1418 m_layer.fillCacheColumn(int((f - start) / windowIncrement), 1431 m_layer.fillCacheColumn(int((f - start) / windowIncrement),
1419 input, output, plan, 1432 input, output, plan,
1420 windowSize, windowIncrement, 1433 windowSize, fftSize,
1434 windowIncrement,
1421 workbuffer, windower); 1435 workbuffer, windower);
1422 1436
1423 if (m_layer.m_cacheInvalid || m_layer.m_exiting) { 1437 if (m_layer.m_cacheInvalid || m_layer.m_exiting) {
1424 interrupted = true; 1438 interrupted = true;
1425 m_fillExtent = 0; 1439 m_fillExtent = 0;
1455 1469
1456 float 1470 float
1457 SpectrogramLayer::getEffectiveMinFrequency() const 1471 SpectrogramLayer::getEffectiveMinFrequency() const
1458 { 1472 {
1459 int sr = m_model->getSampleRate(); 1473 int sr = m_model->getSampleRate();
1460 float minf = float(sr) / m_windowSize; 1474 float minf = float(sr) / m_fftSize;
1461 1475
1462 if (m_minFrequency > 0.0) { 1476 if (m_minFrequency > 0.0) {
1463 size_t minbin = size_t((double(m_minFrequency) * m_windowSize) / sr + 0.01); 1477 size_t minbin = size_t((double(m_minFrequency) * m_fftSize) / sr + 0.01);
1464 if (minbin < 1) minbin = 1; 1478 if (minbin < 1) minbin = 1;
1465 minf = minbin * sr / m_windowSize; 1479 minf = minbin * sr / m_fftSize;
1466 } 1480 }
1467 1481
1468 return minf; 1482 return minf;
1469 } 1483 }
1470 1484
1473 { 1487 {
1474 int sr = m_model->getSampleRate(); 1488 int sr = m_model->getSampleRate();
1475 float maxf = float(sr) / 2; 1489 float maxf = float(sr) / 2;
1476 1490
1477 if (m_maxFrequency > 0.0) { 1491 if (m_maxFrequency > 0.0) {
1478 size_t maxbin = size_t((double(m_maxFrequency) * m_windowSize) / sr + 0.1); 1492 size_t maxbin = size_t((double(m_maxFrequency) * m_fftSize) / sr + 0.1);
1479 if (maxbin > m_windowSize / 2) maxbin = m_windowSize / 2; 1493 if (maxbin > m_fftSize / 2) maxbin = m_fftSize / 2;
1480 maxf = maxbin * sr / m_windowSize; 1494 maxf = maxbin * sr / m_fftSize;
1481 } 1495 }
1482 1496
1483 return maxf; 1497 return maxf;
1484 } 1498 }
1485 1499
1498 q0 = v->getFrequencyForY(y, minf, maxf, logarithmic); 1512 q0 = v->getFrequencyForY(y, minf, maxf, logarithmic);
1499 q1 = v->getFrequencyForY(y - 1, minf, maxf, logarithmic); 1513 q1 = v->getFrequencyForY(y - 1, minf, maxf, logarithmic);
1500 1514
1501 // Now map these on to actual bins 1515 // Now map these on to actual bins
1502 1516
1503 int b0 = int((q0 * m_windowSize) / sr); 1517 int b0 = int((q0 * m_fftSize) / sr);
1504 int b1 = int((q1 * m_windowSize) / sr); 1518 int b1 = int((q1 * m_fftSize) / sr);
1505 1519
1506 //!!! this is supposed to return fractions-of-bins, as it were, hence the floats 1520 //!!! this is supposed to return fractions-of-bins, as it were, hence the floats
1507 q0 = b0; 1521 q0 = b0;
1508 q1 = b1; 1522 q1 = b1;
1509 1523
1510 // q0 = (b0 * sr) / m_windowSize; 1524 // q0 = (b0 * sr) / m_fftSize;
1511 // q1 = (b1 * sr) / m_windowSize; 1525 // q1 = (b1 * sr) / m_fftSize;
1512 1526
1513 return true; 1527 return true;
1514 } 1528 }
1515 1529
1516 bool 1530 bool
1567 int q1i = int(q1); 1581 int q1i = int(q1);
1568 1582
1569 int sr = m_model->getSampleRate(); 1583 int sr = m_model->getSampleRate();
1570 1584
1571 for (int q = q0i; q <= q1i; ++q) { 1585 for (int q = q0i; q <= q1i; ++q) {
1572 int binfreq = (sr * q) / m_windowSize; 1586 int binfreq = (sr * q) / m_fftSize;
1573 if (q == q0i) freqMin = binfreq; 1587 if (q == q0i) freqMin = binfreq;
1574 if (q == q1i) freqMax = binfreq; 1588 if (q == q1i) freqMax = binfreq;
1575 } 1589 }
1576 return true; 1590 return true;
1577 } 1591 }
1965 1979
1966 m_drawBuffer.fill(m_colourMap.getColour(0).rgb()); 1980 m_drawBuffer.fill(m_colourMap.getColour(0).rgb());
1967 1981
1968 int sr = m_model->getSampleRate(); 1982 int sr = m_model->getSampleRate();
1969 1983
1970 size_t bins = m_windowSize / 2; 1984 size_t bins = m_fftSize / 2;
1971 if (m_maxFrequency > 0) { 1985 if (m_maxFrequency > 0) {
1972 bins = int((double(m_maxFrequency) * m_windowSize) / sr + 0.1); 1986 bins = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1);
1973 if (bins > m_windowSize / 2) bins = m_windowSize / 2; 1987 if (bins > m_fftSize / 2) bins = m_fftSize / 2;
1974 } 1988 }
1975 1989
1976 size_t minbin = 1; 1990 size_t minbin = 1;
1977 if (m_minFrequency > 0) { 1991 if (m_minFrequency > 0) {
1978 minbin = int((double(m_minFrequency) * m_windowSize) / sr + 0.1); 1992 minbin = int((double(m_minFrequency) * m_fftSize) / sr + 0.1);
1979 if (minbin < 1) minbin = 1; 1993 if (minbin < 1) minbin = 1;
1980 if (minbin >= bins) minbin = bins - 1; 1994 if (minbin >= bins) minbin = bins - 1;
1981 } 1995 }
1982 1996
1983 float minFreq = (float(minbin) * sr) / m_windowSize; 1997 float minFreq = (float(minbin) * sr) / m_fftSize;
1984 float maxFreq = (float(bins) * sr) / m_windowSize; 1998 float maxFreq = (float(bins) * sr) / m_fftSize;
1985 1999
1986 float ymag[h]; 2000 float ymag[h];
1987 float ydiv[h]; 2001 float ydiv[h];
1988 float yval[bins + 1]; 2002 float yval[bins + 1];
1989 2003
1992 bool logarithmic = (m_frequencyScale == LogFrequencyScale); 2006 bool logarithmic = (m_frequencyScale == LogFrequencyScale);
1993 2007
1994 m_mutex.unlock(); 2008 m_mutex.unlock();
1995 2009
1996 for (size_t q = minbin; q <= bins; ++q) { 2010 for (size_t q = minbin; q <= bins; ++q) {
1997 float f0 = (float(q) * sr) / m_windowSize; 2011 float f0 = (float(q) * sr) / m_fftSize;
1998 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic); 2012 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic);
1999 } 2013 }
2000 2014
2001 m_mutex.lock(); 2015 m_mutex.lock();
2002 2016
2446 int h = rect.height(), w = rect.width(); 2460 int h = rect.height(), w = rect.width();
2447 2461
2448 int tickw = (m_frequencyScale == LogFrequencyScale ? 10 : 4); 2462 int tickw = (m_frequencyScale == LogFrequencyScale ? 10 : 4);
2449 int pkw = (m_frequencyScale == LogFrequencyScale ? 10 : 0); 2463 int pkw = (m_frequencyScale == LogFrequencyScale ? 10 : 0);
2450 2464
2451 size_t bins = m_windowSize / 2; 2465 size_t bins = m_fftSize / 2;
2452 int sr = m_model->getSampleRate(); 2466 int sr = m_model->getSampleRate();
2453 2467
2454 if (m_maxFrequency > 0) { 2468 if (m_maxFrequency > 0) {
2455 bins = int((double(m_maxFrequency) * m_windowSize) / sr + 0.1); 2469 bins = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1);
2456 if (bins > m_windowSize / 2) bins = m_windowSize / 2; 2470 if (bins > m_fftSize / 2) bins = m_fftSize / 2;
2457 } 2471 }
2458 2472
2459 int cw = getColourScaleWidth(paint); 2473 int cw = getColourScaleWidth(paint);
2460 2474
2461 int py = -1; 2475 int py = -1;
2528 bin = int(q0); 2542 bin = int(q0);
2529 } else { 2543 } else {
2530 continue; 2544 continue;
2531 } 2545 }
2532 2546
2533 int freq = (sr * bin) / m_windowSize; 2547 int freq = (sr * bin) / m_fftSize;
2534 2548
2535 if (py >= 0 && (vy - py) < textHeight - 1) { 2549 if (py >= 0 && (vy - py) < textHeight - 1) {
2536 if (m_frequencyScale == LinearFrequencyScale) { 2550 if (m_frequencyScale == LinearFrequencyScale) {
2537 paint.drawLine(w - tickw, h - vy, w, h - vy); 2551 paint.drawLine(w - tickw, h - vy, w, h - vy);
2538 } 2552 }