comparison layer/SpectrogramLayer.cpp @ 104:1348818e7be7

* Switch from fftw3 to fftw3f. I think the efficiency improvement is probably worth the lower precision, although I ought to do a few more tests.
author Chris Cannam
date Thu, 15 Jun 2006 12:28:47 +0000
parents 8ce53683d0d7
children bf196d6e8998
comparison
equal deleted inserted replaced
103:5064eeb1c76f 104:1348818e7be7
41 double a = floor(x / y); 41 double a = floor(x / y);
42 double b = x - (y * a); 42 double b = x - (y * a);
43 return b; 43 return b;
44 } 44 }
45 45
46 static float modf(float x, float y)
47 {
48 float a = floorf(x / y);
49 float b = x - (y * a);
50 return b;
51 }
52
46 static double princarg(double ang) 53 static double princarg(double ang)
47 { 54 {
48 return mod(ang + M_PI, -2 * M_PI) + M_PI; 55 return mod(ang + M_PI, -2 * M_PI) + M_PI;
56 }
57
58 static float princargf(float ang)
59 {
60 return modf(ang + M_PI, -2 * M_PI) + M_PI;
49 } 61 }
50 62
51 63
52 SpectrogramLayer::SpectrogramLayer(Configuration config) : 64 SpectrogramLayer::SpectrogramLayer(Configuration config) :
53 Layer(), 65 Layer(),
1079 float frequency = (float(bin) * sampleRate) / windowSize; 1091 float frequency = (float(bin) * sampleRate) / windowSize;
1080 1092
1081 float expectedPhase = 1093 float expectedPhase =
1082 oldPhase + (2.0 * M_PI * bin * windowIncrement) / windowSize; 1094 oldPhase + (2.0 * M_PI * bin * windowIncrement) / windowSize;
1083 1095
1084 float phaseError = princarg(newPhase - expectedPhase); 1096 float phaseError = princargf(newPhase - expectedPhase);
1085 1097
1086 if (fabs(phaseError) < (1.1 * (windowIncrement * M_PI) / windowSize)) { 1098 if (fabs(phaseError) < (1.1 * (windowIncrement * M_PI) / windowSize)) {
1087 1099
1088 // The new frequency estimate based on the phase error 1100 // The new frequency estimate based on the phase error
1089 // resulting from assuming the "native" frequency of this bin 1101 // resulting from assuming the "native" frequency of this bin
1099 steadyState = false; 1111 steadyState = false;
1100 return frequency; 1112 return frequency;
1101 } 1113 }
1102 1114
1103 void 1115 void
1104 SpectrogramLayer::fillCacheColumn(int column, double *input, 1116 SpectrogramLayer::fillCacheColumn(int column, fftsample *input,
1105 fftw_complex *output, 1117 fftwf_complex *output,
1106 fftw_plan plan, 1118 fftwf_plan plan,
1107 size_t windowSize, 1119 size_t windowSize,
1108 size_t increment, 1120 size_t increment,
1109 float *workbuffer, 1121 float *workbuffer,
1110 const Window<double> &windower) const 1122 const Window<fftsample> &windower) const
1111 { 1123 {
1112 //!!! we _do_ need a lock for these references to the model 1124 //!!! we _do_ need a lock for these references to the model
1113 // though, don't we? 1125 // though, don't we?
1114 1126
1115 int startFrame = increment * column; 1127 int startFrame = increment * column;
1143 } 1155 }
1144 1156
1145 windower.cut(input); 1157 windower.cut(input);
1146 1158
1147 for (size_t i = 0; i < windowSize/2; ++i) { 1159 for (size_t i = 0; i < windowSize/2; ++i) {
1148 double temp = input[i]; 1160 fftsample temp = input[i];
1149 input[i] = input[i + windowSize/2]; 1161 input[i] = input[i + windowSize/2];
1150 input[i + windowSize/2] = temp; 1162 input[i + windowSize/2] = temp;
1151 } 1163 }
1152 1164
1153 fftw_execute(plan); 1165 fftwf_execute(plan);
1154 1166
1155 double factor = 0.0; 1167 fftsample factor = 0.0;
1156 1168
1157 for (size_t i = 0; i < windowSize/2; ++i) { 1169 for (size_t i = 0; i < windowSize/2; ++i) {
1158 1170
1159 double mag = sqrt(output[i][0] * output[i][0] + 1171 fftsample mag = sqrtf(output[i][0] * output[i][0] +
1160 output[i][1] * output[i][1]); 1172 output[i][1] * output[i][1]);
1161 mag /= windowSize / 2; 1173 mag /= windowSize / 2;
1162 1174
1163 if (mag > factor) factor = mag; 1175 if (mag > factor) factor = mag;
1164 1176
1165 double phase = atan2(output[i][1], output[i][0]); 1177 fftsample phase = atan2f(output[i][1], output[i][0]);
1166 phase = princarg(phase); 1178 phase = princargf(phase);
1167 1179
1168 workbuffer[i] = mag; 1180 workbuffer[i] = mag;
1169 workbuffer[i + windowSize/2] = phase; 1181 workbuffer[i + windowSize/2] = phase;
1170 } 1182 }
1171 1183
1326 MatrixFile::ReadOnly); 1338 MatrixFile::ReadOnly);
1327 1339
1328 m_layer.setColourmap(); 1340 m_layer.setColourmap();
1329 //!!! m_layer.m_writeCache->reset(); 1341 //!!! m_layer.m_writeCache->reset();
1330 1342
1331 double *input = (double *) 1343 fftsample *input = (fftsample *)
1332 fftw_malloc(windowSize * sizeof(double)); 1344 fftwf_malloc(windowSize * sizeof(fftsample));
1333 1345
1334 fftw_complex *output = (fftw_complex *) 1346 fftwf_complex *output = (fftwf_complex *)
1335 fftw_malloc(windowSize * sizeof(fftw_complex)); 1347 fftwf_malloc(windowSize * sizeof(fftwf_complex));
1336 1348
1337 float *workbuffer = (float *) 1349 float *workbuffer = (float *)
1338 fftw_malloc(windowSize * sizeof(float)); 1350 fftwf_malloc(windowSize * sizeof(float));
1339 1351
1340 fftw_plan plan = fftw_plan_dft_r2c_1d(windowSize, input, 1352 fftwf_plan plan = fftwf_plan_dft_r2c_1d(windowSize, input,
1341 output, FFTW_ESTIMATE); 1353 output, FFTW_ESTIMATE);
1342 1354
1343 if (!plan) { 1355 if (!plan) {
1344 std::cerr << "WARNING: fftw_plan_dft_r2c_1d(" << windowSize << ") failed!" << std::endl; 1356 std::cerr << "WARNING: fftwf_plan_dft_r2c_1d(" << windowSize << ") failed!" << std::endl;
1345 fftw_free(input); 1357 fftwf_free(input);
1346 fftw_free(output); 1358 fftwf_free(output);
1347 fftw_free(workbuffer); 1359 fftwf_free(workbuffer);
1348 continue; 1360 continue;
1349 } 1361 }
1350 1362
1351 // We don't need a lock when writing to or reading from 1363 // We don't need a lock when writing to or reading from
1352 // the pixels in the cache. We do need to ensure we have 1364 // the pixels in the cache. We do need to ensure we have
1357 // happens, because they will continue to match the 1369 // happens, because they will continue to match the
1358 // dimensions of the actual cache (which this thread 1370 // dimensions of the actual cache (which this thread
1359 // manages, not the layer's). 1371 // manages, not the layer's).
1360 m_layer.m_mutex.unlock(); 1372 m_layer.m_mutex.unlock();
1361 1373
1362 Window<double> windower(windowType, windowSize); 1374 Window<fftsample> windower(windowType, windowSize);
1363 1375
1364 int counter = 0; 1376 int counter = 0;
1365 int updateAt = (end / windowIncrement) / 20; 1377 int updateAt = (end / windowIncrement) / 20;
1366 if (updateAt < 100) updateAt = 100; 1378 if (updateAt < 100) updateAt = 100;
1367 1379
1422 counter = 0; 1434 counter = 0;
1423 } 1435 }
1424 } 1436 }
1425 } 1437 }
1426 1438
1427 fftw_destroy_plan(plan); 1439 fftwf_destroy_plan(plan);
1428 fftw_free(output); 1440 fftwf_free(output);
1429 fftw_free(input); 1441 fftwf_free(input);
1430 fftw_free(workbuffer); 1442 fftwf_free(workbuffer);
1431 1443
1432 if (!interrupted) { 1444 if (!interrupted) {
1433 m_fillExtent = end; 1445 m_fillExtent = end;
1434 m_fillCompletion = 100; 1446 m_fillCompletion = 100;
1435 } 1447 }