comparison layer/SpectrogramLayer.cpp @ 946:36cddc3de023 alignment_view

Merge from default branch
author Chris Cannam
date Mon, 20 Apr 2015 09:19:52 +0100
parents 28d05ae8741c
children 94e4952a6774 b8187c83b93a
comparison
equal deleted inserted replaced
897:499b637f2a26 946:36cddc3de023
39 #include <QMouseEvent> 39 #include <QMouseEvent>
40 #include <QTextStream> 40 #include <QTextStream>
41 41
42 #include <iostream> 42 #include <iostream>
43 43
44
45
46 #include <cassert> 44 #include <cassert>
47 #include <cmath> 45 #include <cmath>
48 46
49 #ifndef __GNUC__ 47 #ifndef __GNUC__
50 #include <alloca.h> 48 #include <alloca.h>
51 #endif 49 #endif
52 50
53 //#define DEBUG_SPECTROGRAM_REPAINT 1 51 //#define DEBUG_SPECTROGRAM_REPAINT 1
52
53 using std::vector;
54 54
55 SpectrogramLayer::SpectrogramLayer(Configuration config) : 55 SpectrogramLayer::SpectrogramLayer(Configuration config) :
56 m_model(0), 56 m_model(0),
57 m_channel(0), 57 m_channel(0),
58 m_windowSize(1024), 58 m_windowSize(1024),
139 if (!m_model || !m_model->isOK()) return; 139 if (!m_model || !m_model->isOK()) return;
140 140
141 connectSignals(m_model); 141 connectSignals(m_model);
142 142
143 connect(m_model, SIGNAL(modelChanged()), this, SLOT(cacheInvalid())); 143 connect(m_model, SIGNAL(modelChanged()), this, SLOT(cacheInvalid()));
144 connect(m_model, SIGNAL(modelChangedWithin(int, int)), 144 connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)),
145 this, SLOT(cacheInvalid(int, int))); 145 this, SLOT(cacheInvalid(sv_frame_t, sv_frame_t)));
146 146
147 emit modelReplaced(); 147 emit modelReplaced();
148 } 148 }
149 149
150 Layer::PropertyList 150 Layer::PropertyList
240 if (name == "Gain") { 240 if (name == "Gain") {
241 241
242 *min = -50; 242 *min = -50;
243 *max = 50; 243 *max = 50;
244 244
245 *deflt = lrintf(log10(m_initialGain) * 20.0);; 245 *deflt = int(lrint(log10(m_initialGain) * 20.0));
246 if (*deflt < *min) *deflt = *min; 246 if (*deflt < *min) *deflt = *min;
247 if (*deflt > *max) *deflt = *max; 247 if (*deflt > *max) *deflt = *max;
248 248
249 val = lrintf(log10(m_gain) * 20.0); 249 val = int(lrint(log10(m_gain) * 20.0));
250 if (val < *min) val = *min; 250 if (val < *min) val = *min;
251 if (val > *max) val = *max; 251 if (val > *max) val = *max;
252 252
253 } else if (name == "Threshold") { 253 } else if (name == "Threshold") {
254 254
255 *min = -50; 255 *min = -50;
256 *max = 0; 256 *max = 0;
257 257
258 *deflt = lrintf(AudioLevel::multiplier_to_dB(m_initialThreshold)); 258 *deflt = int(lrint(AudioLevel::multiplier_to_dB(m_initialThreshold)));
259 if (*deflt < *min) *deflt = *min; 259 if (*deflt < *min) *deflt = *min;
260 if (*deflt > *max) *deflt = *max; 260 if (*deflt > *max) *deflt = *max;
261 261
262 val = lrintf(AudioLevel::multiplier_to_dB(m_threshold)); 262 val = int(lrint(AudioLevel::multiplier_to_dB(m_threshold)));
263 if (val < *min) val = *min; 263 if (val < *min) val = *min;
264 if (val > *max) val = *max; 264 if (val > *max) val = *max;
265 265
266 } else if (name == "Colour Rotation") { 266 } else if (name == "Colour Rotation") {
267 267
479 479
480 void 480 void
481 SpectrogramLayer::setProperty(const PropertyName &name, int value) 481 SpectrogramLayer::setProperty(const PropertyName &name, int value)
482 { 482 {
483 if (name == "Gain") { 483 if (name == "Gain") {
484 setGain(pow(10, float(value)/20.0)); 484 setGain(float(pow(10, float(value)/20.0)));
485 } else if (name == "Threshold") { 485 } else if (name == "Threshold") {
486 if (value == -50) setThreshold(0.0); 486 if (value == -50) setThreshold(0.0);
487 else setThreshold(AudioLevel::dB_to_multiplier(value)); 487 else setThreshold(float(AudioLevel::dB_to_multiplier(value)));
488 } else if (name == "Colour Rotation") { 488 } else if (name == "Colour Rotation") {
489 setColourRotation(value); 489 setColourRotation(value);
490 } else if (name == "Colour") { 490 } else if (name == "Colour") {
491 setColourMap(value); 491 setColourMap(value);
492 } else if (name == "Window Size") { 492 } else if (name == "Window Size") {
570 i->second.validArea = QRect(); 570 i->second.validArea = QRect();
571 } 571 }
572 } 572 }
573 573
574 void 574 void
575 SpectrogramLayer::invalidateImageCaches(int startFrame, int endFrame) 575 SpectrogramLayer::invalidateImageCaches(sv_frame_t startFrame, sv_frame_t endFrame)
576 { 576 {
577 for (ViewImageCache::iterator i = m_imageCaches.begin(); 577 for (ViewImageCache::iterator i = m_imageCaches.begin();
578 i != m_imageCaches.end(); ++i) { 578 i != m_imageCaches.end(); ++i) {
579 579
580 //!!! when are views removed from the map? on setLayerDormant? 580 //!!! when are views removed from the map? on setLayerDormant?
1047 invalidateImageCaches(); 1047 invalidateImageCaches();
1048 invalidateMagnitudes(); 1048 invalidateMagnitudes();
1049 } 1049 }
1050 1050
1051 void 1051 void
1052 SpectrogramLayer::cacheInvalid(int from, int to) 1052 SpectrogramLayer::cacheInvalid(sv_frame_t from, sv_frame_t to)
1053 { 1053 {
1054 #ifdef DEBUG_SPECTROGRAM_REPAINT 1054 #ifdef DEBUG_SPECTROGRAM_REPAINT
1055 SVDEBUG << "SpectrogramLayer::cacheInvalid(" << from << ", " << to << ")" << endl; 1055 SVDEBUG << "SpectrogramLayer::cacheInvalid(" << from << ", " << to << ")" << endl;
1056 #endif 1056 #endif
1057 1057
1072 1072
1073 for (ViewFFTMap::iterator i = m_fftModels.begin(); 1073 for (ViewFFTMap::iterator i = m_fftModels.begin();
1074 i != m_fftModels.end(); ++i) { 1074 i != m_fftModels.end(); ++i) {
1075 1075
1076 const FFTModel *model = i->second.first; 1076 const FFTModel *model = i->second.first;
1077 int lastFill = i->second.second; 1077 sv_frame_t lastFill = i->second.second;
1078 1078
1079 if (model) { 1079 if (model) {
1080 1080
1081 int fill = model->getFillExtent(); 1081 sv_frame_t fill = model->getFillExtent();
1082 1082
1083 #ifdef DEBUG_SPECTROGRAM_REPAINT 1083 #ifdef DEBUG_SPECTROGRAM_REPAINT
1084 SVDEBUG << "SpectrogramLayer::fillTimerTimedOut: extent for " << model << ": " << fill << ", last " << lastFill << ", total " << m_model->getEndFrame() << endl; 1084 SVDEBUG << "SpectrogramLayer::fillTimerTimedOut: extent for " << model << ": " << fill << ", last " << lastFill << ", total " << m_model->getEndFrame() << endl;
1085 #endif 1085 #endif
1086 1086
1145 } 1145 }
1146 1146
1147 ColourMapper mapper(m_colourMap, 1.f, 255.f); 1147 ColourMapper mapper(m_colourMap, 1.f, 255.f);
1148 1148
1149 for (int pixel = 1; pixel < 256; ++pixel) { 1149 for (int pixel = 1; pixel < 256; ++pixel) {
1150 m_palette.setColour(pixel, mapper.map(pixel)); 1150 m_palette.setColour((unsigned char)pixel, mapper.map(pixel));
1151 } 1151 }
1152 1152
1153 m_crosshairColour = mapper.getContrastingColour(); 1153 m_crosshairColour = mapper.getContrastingColour();
1154 1154
1155 m_colourRotation = 0; 1155 m_colourRotation = 0;
1168 1168
1169 for (int pixel = 1; pixel < 256; ++pixel) { 1169 for (int pixel = 1; pixel < 256; ++pixel) {
1170 int target = pixel + distance; 1170 int target = pixel + distance;
1171 while (target < 1) target += 255; 1171 while (target < 1) target += 255;
1172 while (target > 255) target -= 255; 1172 while (target > 255) target -= 255;
1173 newPixels[target] = m_palette.getColour(pixel); 1173 newPixels[target] = m_palette.getColour((unsigned char)pixel);
1174 } 1174 }
1175 1175
1176 for (int pixel = 0; pixel < 256; ++pixel) { 1176 for (int pixel = 0; pixel < 256; ++pixel) {
1177 m_palette.setColour(pixel, newPixels[pixel]); 1177 m_palette.setColour((unsigned char)pixel, newPixels[pixel]);
1178 } 1178 }
1179 1179
1180 m_drawBuffer = QImage(); 1180 m_drawBuffer = QImage();
1181 } 1181 }
1182 1182
1183 unsigned char 1183 unsigned char
1184 SpectrogramLayer::getDisplayValue(View *v, float input) const 1184 SpectrogramLayer::getDisplayValue(View *v, double input) const
1185 { 1185 {
1186 int value; 1186 int value;
1187 1187
1188 float min = 0.f; 1188 double min = 0.0;
1189 float max = 1.f; 1189 double max = 1.0;
1190 1190
1191 if (m_normalizeVisibleArea) { 1191 if (m_normalizeVisibleArea) {
1192 min = m_viewMags[v].getMin(); 1192 min = m_viewMags[v].getMin();
1193 max = m_viewMags[v].getMax(); 1193 max = m_viewMags[v].getMax();
1194 } else if (!m_normalizeColumns) { 1194 } else if (!m_normalizeColumns) {
1195 if (m_colourScale == LinearColourScale //|| 1195 if (m_colourScale == LinearColourScale //||
1196 // m_colourScale == MeterColourScale) { 1196 // m_colourScale == MeterColourScale) {
1197 ) { 1197 ) {
1198 max = 0.1f; 1198 max = 0.1;
1199 } 1199 }
1200 } 1200 }
1201 1201
1202 float thresh = -80.f; 1202 double thresh = -80.0;
1203 1203
1204 if (max == 0.f) max = 1.f; 1204 if (max == 0.0) max = 1.0;
1205 if (max == min) min = max - 0.0001f; 1205 if (max == min) min = max - 0.0001;
1206 1206
1207 switch (m_colourScale) { 1207 switch (m_colourScale) {
1208 1208
1209 default: 1209 default:
1210 case LinearColourScale: 1210 case LinearColourScale:
1211 value = int(((input - min) / (max - min)) * 255.f) + 1; 1211 value = int(((input - min) / (max - min)) * 255.0) + 1;
1212 break; 1212 break;
1213 1213
1214 case MeterColourScale: 1214 case MeterColourScale:
1215 value = AudioLevel::multiplier_to_preview 1215 value = AudioLevel::multiplier_to_preview
1216 ((input - min) / (max - min), 254) + 1; 1216 ((input - min) / (max - min), 254) + 1;
1217 break; 1217 break;
1218 1218
1219 case dBSquaredColourScale: 1219 case dBSquaredColourScale:
1220 input = ((input - min) * (input - min)) / ((max - min) * (max - min)); 1220 input = ((input - min) * (input - min)) / ((max - min) * (max - min));
1221 if (input > 0.f) { 1221 if (input > 0.0) {
1222 input = 10.f * log10f(input); 1222 input = 10.0 * log10(input);
1223 } else { 1223 } else {
1224 input = thresh; 1224 input = thresh;
1225 } 1225 }
1226 if (min > 0.f) { 1226 if (min > 0.0) {
1227 thresh = 10.f * log10f(min * min); 1227 thresh = 10.0 * log10(min * min);
1228 if (thresh < -80.f) thresh = -80.f; 1228 if (thresh < -80.0) thresh = -80.0;
1229 } 1229 }
1230 input = (input - thresh) / (-thresh); 1230 input = (input - thresh) / (-thresh);
1231 if (input < 0.f) input = 0.f; 1231 if (input < 0.0) input = 0.0;
1232 if (input > 1.f) input = 1.f; 1232 if (input > 1.0) input = 1.0;
1233 value = int(input * 255.f) + 1; 1233 value = int(input * 255.0) + 1;
1234 break; 1234 break;
1235 1235
1236 case dBColourScale: 1236 case dBColourScale:
1237 //!!! experiment with normalizing the visible area this way. 1237 //!!! experiment with normalizing the visible area this way.
1238 //In any case, we need to have some indication of what the dB 1238 //In any case, we need to have some indication of what the dB
1239 //scale is relative to. 1239 //scale is relative to.
1240 input = (input - min) / (max - min); 1240 input = (input - min) / (max - min);
1241 if (input > 0.f) { 1241 if (input > 0.0) {
1242 input = 10.f * log10f(input); 1242 input = 10.0 * log10(input);
1243 } else { 1243 } else {
1244 input = thresh; 1244 input = thresh;
1245 } 1245 }
1246 if (min > 0.f) { 1246 if (min > 0.0) {
1247 thresh = 10.f * log10f(min); 1247 thresh = 10.0 * log10(min);
1248 if (thresh < -80.f) thresh = -80.f; 1248 if (thresh < -80.0) thresh = -80.0;
1249 } 1249 }
1250 input = (input - thresh) / (-thresh); 1250 input = (input - thresh) / (-thresh);
1251 if (input < 0.f) input = 0.f; 1251 if (input < 0.0) input = 0.0;
1252 if (input > 1.f) input = 1.f; 1252 if (input > 1.0) input = 1.0;
1253 value = int(input * 255.f) + 1; 1253 value = int(input * 255.0) + 1;
1254 break; 1254 break;
1255 1255
1256 case PhaseColourScale: 1256 case PhaseColourScale:
1257 value = int((input * 127.0 / M_PI) + 128); 1257 value = int((input * 127.0 / M_PI) + 128);
1258 break; 1258 break;
1259 } 1259 }
1260 1260
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 (unsigned char)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 sv_samplerate_t 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 sv_samplerate_t 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 sv_samplerate_t 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 sv_samplerate_t 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 sv_frame_t modelStart = m_model->getStartFrame();
1352 int modelEnd = m_model->getEndFrame(); 1352 sv_frame_t 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:
1355 int f0 = v->getFrameForX(x) - modelStart; 1355 sv_frame_t f0 = v->getFrameForX(x) - modelStart;
1356 int f1 = v->getFrameForX(x + 1) - modelStart - 1; 1356 sv_frame_t f1 = v->getFrameForX(x + 1) - modelStart - 1;
1357 1357
1358 if (f1 < int(modelStart) || f0 > int(modelEnd)) { 1358 if (f1 < int(modelStart) || f0 > int(modelEnd)) {
1359 return false; 1359 return false;
1360 } 1360 }
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
1401 int sr = m_model->getSampleRate(); 1401 sv_samplerate_t sr = m_model->getSampleRate();
1402 1402
1403 for (int q = q0i; q <= q1i; ++q) { 1403 for (int q = q0i; q <= q1i; ++q) {
1404 if (q == q0i) freqMin = (sr * q) / m_fftSize; 1404 if (q == q0i) freqMin = (sr * q) / m_fftSize;
1405 if (q == q1i) freqMax = (sr * (q+1)) / m_fftSize; 1405 if (q == q1i) freqMax = (sr * (q+1)) / m_fftSize;
1406 } 1406 }
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
1432 int q0i = int(q0 + 0.001); 1432 int q0i = int(q0 + 0.001);
1433 int q1i = int(q1); 1433 int q1i = int(q1);
1434 1434
1435 int sr = m_model->getSampleRate(); 1435 sv_samplerate_t sr = m_model->getSampleRate();
1436 1436
1437 bool haveAdj = false; 1437 bool haveAdj = false;
1438 1438
1439 bool peaksOnly = (m_binDisplay == PeakBins || 1439 bool peaksOnly = (m_binDisplay == PeakBins ||
1440 m_binDisplay == PeakFrequencies); 1440 m_binDisplay == PeakFrequencies);
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, float(m_threshold * double(m_fftSize)/2.0))) 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
1529 value = fft->getMagnitudeAt(s, q) / (m_fftSize/2); 1529 value = fft->getMagnitudeAt(s, q) / (m_fftSize/2.0);
1530 if (!have || value < min) { min = value; } 1530 if (!have || value < min) { min = value; }
1531 if (!have || value > max) { max = value; } 1531 if (!have || value > max) { max = value; }
1532 1532
1533 have = true; 1533 have = true;
1534 } 1534 }
1556 if (smoothing == Preferences::NoSpectrogramSmoothing || 1556 if (smoothing == Preferences::NoSpectrogramSmoothing ||
1557 smoothing == Preferences::SpectrogramInterpolated) return 0; 1557 smoothing == Preferences::SpectrogramInterpolated) return 0;
1558 1558
1559 if (m_frequencyScale == LogFrequencyScale) return 3; 1559 if (m_frequencyScale == LogFrequencyScale) return 3;
1560 1560
1561 int sr = m_model->getSampleRate(); 1561 sv_samplerate_t sr = m_model->getSampleRate();
1562 1562
1563 int maxbin = m_fftSize / 2; 1563 int maxbin = m_fftSize / 2;
1564 if (m_maxFrequency > 0) { 1564 if (m_maxFrequency > 0) {
1565 maxbin = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1); 1565 maxbin = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1);
1566 if (maxbin > m_fftSize / 2) maxbin = m_fftSize / 2; 1566 if (maxbin > m_fftSize / 2) maxbin = m_fftSize / 2;
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 = double(m_model->getStartFrame()) / getWindowIncrement();
1731 } 1731 }
1732 1732
1733 if (!getXBinRange(v, x1, s10, s11)) { 1733 if (!getXBinRange(v, x1, s10, s11)) {
1734 s10 = s11 = m_model->getEndFrame() / getWindowIncrement(); 1734 s10 = s11 = double(m_model->getEndFrame()) / getWindowIncrement();
1735 } 1735 }
1736 1736
1737 int s0 = int(std::min(s00, s10) + 0.0001); 1737 int s0 = int(std::min(s00, s10) + 0.0001);
1738 int s1 = int(std::max(s01, s11) + 0.0001); 1738 int s1 = int(std::max(s01, s11) + 0.0001);
1739 1739
1778 SVDEBUG << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", m_updateTimer " << m_updateTimer << endl; 1778 SVDEBUG << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", m_updateTimer " << m_updateTimer << endl;
1779 1779
1780 cerr << "rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl; 1780 cerr << "rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl;
1781 #endif 1781 #endif
1782 1782
1783 int startFrame = v->getStartFrame(); 1783 sv_frame_t startFrame = v->getStartFrame();
1784 if (startFrame < 0) m_candidateFillStartFrame = 0; 1784 if (startFrame < 0) m_candidateFillStartFrame = 0;
1785 else m_candidateFillStartFrame = startFrame; 1785 else m_candidateFillStartFrame = startFrame;
1786 1786
1787 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1787 if (!m_model || !m_model->isOK() || !m_model->isReady()) {
1788 return; 1788 return;
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
1879 dx > -cw && 1879 dx > -cw &&
1880 dx < cw) { 1880 dx < cw) {
1881 1881
1882 int dxp = dx; 1882 int dxp = dx;
1883 if (dxp < 0) dxp = -dxp; 1883 if (dxp < 0) dxp = -dxp;
1884 int copy = (cw - dxp) * sizeof(QRgb); 1884 size_t copy = (cw - dxp) * sizeof(QRgb);
1885 for (int y = 0; y < ch; ++y) { 1885 for (int y = 0; y < ch; ++y) {
1886 QRgb *line = (QRgb *)cache.image.scanLine(y); 1886 QRgb *line = (QRgb *)cache.image.scanLine(y);
1887 if (dx < 0) { 1887 if (dx < 0) {
1888 memmove(line, line + dxp, copy); 1888 memmove(line, line + dxp, copy);
1889 } else { 1889 } else {
2104 2104
2105 #ifdef DEBUG_SPECTROGRAM_REPAINT 2105 #ifdef DEBUG_SPECTROGRAM_REPAINT
2106 cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << endl; 2106 cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << endl;
2107 #endif 2107 #endif
2108 2108
2109 int sr = m_model->getSampleRate(); 2109 sv_samplerate_t sr = m_model->getSampleRate();
2110 2110
2111 // Set minFreq and maxFreq to the frequency extents of the possibly 2111 // Set minFreq and maxFreq to the frequency extents of the possibly
2112 // zero-padded visible bin range, and displayMinFreq and displayMaxFreq 2112 // zero-padded visible bin range, and displayMinFreq and displayMaxFreq
2113 // to the actual scale frequency extents (presumably not zero padded). 2113 // to the actual scale frequency extents (presumably not zero padded).
2114 2114
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 }
2194 // we draw up to, and one which we subsequently crop at. 2194 // we draw up to, and one which we subsequently crop at.
2195 2195
2196 bool bufferBinResolution = false; 2196 bool bufferBinResolution = false;
2197 if (increment > zoomLevel) bufferBinResolution = true; 2197 if (increment > zoomLevel) bufferBinResolution = true;
2198 2198
2199 int leftBoundaryFrame = -1, leftCropFrame = -1; 2199 sv_frame_t leftBoundaryFrame = -1, leftCropFrame = -1;
2200 int rightBoundaryFrame = -1, rightCropFrame = -1; 2200 sv_frame_t rightBoundaryFrame = -1, rightCropFrame = -1;
2201 2201
2202 int bufwid; 2202 int bufwid;
2203 2203
2204 if (bufferBinResolution) { 2204 if (bufferBinResolution) {
2205 2205
2206 for (int x = x0; ; --x) { 2206 for (int x = x0; ; --x) {
2207 int f = v->getFrameForX(x); 2207 sv_frame_t f = v->getFrameForX(x);
2208 if ((f / increment) * increment == f) { 2208 if ((f / increment) * increment == f) {
2209 if (leftCropFrame == -1) leftCropFrame = f; 2209 if (leftCropFrame == -1) leftCropFrame = f;
2210 else if (x < x0 - 2) { leftBoundaryFrame = f; break; } 2210 else if (x < x0 - 2) { leftBoundaryFrame = f; break; }
2211 } 2211 }
2212 } 2212 }
2213 for (int x = x0 + w; ; ++x) { 2213 for (int x = x0 + w; ; ++x) {
2214 int f = v->getFrameForX(x); 2214 sv_frame_t f = v->getFrameForX(x);
2215 if ((f / increment) * increment == f) { 2215 if ((f / increment) * increment == f) {
2216 if (rightCropFrame == -1) rightCropFrame = f; 2216 if (rightCropFrame == -1) rightCropFrame = f;
2217 else if (x > x0 + w + 2) { rightBoundaryFrame = f; break; } 2217 else if (x > x0 + w + 2) { rightBoundaryFrame = f; break; }
2218 } 2218 }
2219 } 2219 }
2220 #ifdef DEBUG_SPECTROGRAM_REPAINT 2220 #ifdef DEBUG_SPECTROGRAM_REPAINT
2221 cerr << "Left: crop: " << leftCropFrame << " (bin " << leftCropFrame/increment << "); boundary: " << leftBoundaryFrame << " (bin " << leftBoundaryFrame/increment << ")" << endl; 2221 cerr << "Left: crop: " << leftCropFrame << " (bin " << leftCropFrame/increment << "); boundary: " << leftBoundaryFrame << " (bin " << leftBoundaryFrame/increment << ")" << endl;
2222 cerr << "Right: crop: " << rightCropFrame << " (bin " << rightCropFrame/increment << "); boundary: " << rightBoundaryFrame << " (bin " << rightBoundaryFrame/increment << ")" << endl; 2222 cerr << "Right: crop: " << rightCropFrame << " (bin " << rightCropFrame/increment << "); boundary: " << rightBoundaryFrame << " (bin " << rightBoundaryFrame/increment << ")" << endl;
2223 #endif 2223 #endif
2224 2224
2225 bufwid = (rightBoundaryFrame - leftBoundaryFrame) / increment; 2225 bufwid = int((rightBoundaryFrame - leftBoundaryFrame) / increment);
2226 2226
2227 } else { 2227 } else {
2228 2228
2229 bufwid = w; 2229 bufwid = w;
2230 } 2230 }
2231 2231
2232 #ifdef __GNUC__ 2232 vector<int> binforx(bufwid);
2233 int binforx[bufwid]; 2233 vector<double> binfory(h);
2234 float binfory[h]; 2234
2235 #else
2236 int *binforx = (int *)alloca(bufwid * sizeof(int));
2237 float *binfory = (float *)alloca(h * sizeof(float));
2238 #endif
2239
2240 bool usePeaksCache = false; 2235 bool usePeaksCache = false;
2241 2236
2242 if (bufferBinResolution) { 2237 if (bufferBinResolution) {
2243 for (int x = 0; x < bufwid; ++x) { 2238 for (int x = 0; x < bufwid; ++x) {
2244 binforx[x] = (leftBoundaryFrame / increment) + x; 2239 binforx[x] = int(leftBoundaryFrame / increment) + x;
2245 // cerr << "binforx[" << x << "] = " << binforx[x] << endl; 2240 // cerr << "binforx[" << x << "] = " << binforx[x] << endl;
2246 } 2241 }
2247 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8); 2242 m_drawBuffer = QImage(bufwid, h, QImage::Format_Indexed8);
2248 } else { 2243 } else {
2249 for (int x = 0; x < bufwid; ++x) { 2244 for (int x = 0; x < bufwid; ++x) {
2250 float s0 = 0, s1 = 0; 2245 double s0 = 0, s1 = 0;
2251 if (getXBinRange(v, x + x0, s0, s1)) { 2246 if (getXBinRange(v, x + x0, s0, s1)) {
2252 binforx[x] = int(s0 + 0.0001); 2247 binforx[x] = int(s0 + 0.0001);
2253 } else { 2248 } else {
2254 binforx[x] = -1; //??? 2249 binforx[x] = -1; //???
2255 } 2250 }
2261 if (m_colourScale == PhaseColourScale) usePeaksCache = false; 2256 if (m_colourScale == PhaseColourScale) usePeaksCache = false;
2262 } 2257 }
2263 2258
2264 // No longer exists in Qt5: m_drawBuffer.setNumColors(256); 2259 // No longer exists in Qt5: m_drawBuffer.setNumColors(256);
2265 for (int pixel = 0; pixel < 256; ++pixel) { 2260 for (int pixel = 0; pixel < 256; ++pixel) {
2266 m_drawBuffer.setColor(pixel, m_palette.getColour(pixel).rgb()); 2261 m_drawBuffer.setColor((unsigned char)pixel,
2262 m_palette.getColour((unsigned char)pixel).rgb());
2267 } 2263 }
2268 2264
2269 m_drawBuffer.fill(0); 2265 m_drawBuffer.fill(0);
2270 2266
2271 if (m_binDisplay != PeakFrequencies) { 2267 if (m_binDisplay != PeakFrequencies) {
2272 2268
2273 for (int y = 0; y < h; ++y) { 2269 for (int y = 0; y < h; ++y) {
2274 float q0 = 0, q1 = 0; 2270 double q0 = 0, q1 = 0;
2275 if (!getSmoothedYBinRange(v, h-y-1, q0, q1)) { 2271 if (!getSmoothedYBinRange(v, h-y-1, q0, q1)) {
2276 binfory[y] = -1; 2272 binfory[y] = -1;
2277 } else { 2273 } else {
2278 binfory[y] = q0; 2274 binfory[y] = q0;
2279 // cerr << "binfory[" << y << "] = " << binfory[y] << endl; 2275 // cerr << "binfory[" << y << "] = " << binfory[y] << endl;
2455 2451
2456 bool 2452 bool
2457 SpectrogramLayer::paintDrawBufferPeakFrequencies(View *v, 2453 SpectrogramLayer::paintDrawBufferPeakFrequencies(View *v,
2458 int w, 2454 int w,
2459 int h, 2455 int h,
2460 int *binforx, 2456 const vector<int> &binforx,
2461 int minbin, 2457 int minbin,
2462 int maxbin, 2458 int maxbin,
2463 float displayMinFreq, 2459 double displayMinFreq,
2464 float displayMaxFreq, 2460 double displayMaxFreq,
2465 bool logarithmic, 2461 bool logarithmic,
2466 MagnitudeRange &overallMag, 2462 MagnitudeRange &overallMag,
2467 bool &overallMagChanged) const 2463 bool &overallMagChanged) const
2468 { 2464 {
2469 Profiler profiler("SpectrogramLayer::paintDrawBufferPeakFrequencies"); 2465 Profiler profiler("SpectrogramLayer::paintDrawBufferPeakFrequencies");
2520 fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1); 2516 fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1);
2521 } else if (m_normalizeColumns) { 2517 } else if (m_normalizeColumns) {
2522 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); 2518 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
2523 } else if (m_normalizeHybrid) { 2519 } else if (m_normalizeHybrid) {
2524 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); 2520 fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
2525 float max = fft->getMaximumMagnitudeAt(sx); 2521 double max = fft->getMaximumMagnitudeAt(sx);
2526 if (max > 0.f) { 2522 if (max > 0.f) {
2527 for (int i = minbin; i <= maxbin; ++i) { 2523 for (int i = minbin; i <= maxbin; ++i) {
2528 values[i - minbin] *= log10(max); 2524 values[i - minbin] = float(values[i - minbin] * log10(max));
2529 } 2525 }
2530 } 2526 }
2531 } else { 2527 } else {
2532 fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1); 2528 fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
2533 } 2529 }
2536 2532
2537 for (FFTModel::PeakSet::const_iterator pi = peakfreqs.begin(); 2533 for (FFTModel::PeakSet::const_iterator pi = peakfreqs.begin();
2538 pi != peakfreqs.end(); ++pi) { 2534 pi != peakfreqs.end(); ++pi) {
2539 2535
2540 int bin = pi->first; 2536 int bin = pi->first;
2541 int freq = pi->second; 2537 double freq = pi->second;
2542 2538
2543 if (bin < minbin) continue; 2539 if (bin < minbin) continue;
2544 if (bin > maxbin) break; 2540 if (bin > maxbin) break;
2545 2541
2546 float value = values[bin - minbin]; 2542 double value = values[bin - minbin];
2547 2543
2548 if (m_colourScale != PhaseColourScale) { 2544 if (m_colourScale != PhaseColourScale) {
2549 if (!m_normalizeColumns && !m_normalizeHybrid) { 2545 if (!m_normalizeColumns && !m_normalizeHybrid) {
2550 value /= (m_fftSize/2.f); 2546 value /= (m_fftSize/2.0);
2551 } 2547 }
2552 mag.sample(value); 2548 mag.sample(float(value));
2553 value *= m_gain; 2549 value *= m_gain;
2554 } 2550 }
2555 2551
2556 float y = v->getYForFrequency 2552 double y = v->getYForFrequency
2557 (freq, displayMinFreq, displayMaxFreq, logarithmic); 2553 (freq, displayMinFreq, displayMaxFreq, logarithmic);
2558 2554
2559 int iy = int(y + 0.5); 2555 int iy = int(y + 0.5);
2560 if (iy < 0 || iy >= h) continue; 2556 if (iy < 0 || iy >= h) continue;
2561 2557
2583 2579
2584 bool 2580 bool
2585 SpectrogramLayer::paintDrawBuffer(View *v, 2581 SpectrogramLayer::paintDrawBuffer(View *v,
2586 int w, 2582 int w,
2587 int h, 2583 int h,
2588 int *binforx, 2584 const vector<int> &binforx,
2589 float *binfory, 2585 const vector<double> &binfory,
2590 bool usePeaksCache, 2586 bool usePeaksCache,
2591 MagnitudeRange &overallMag, 2587 MagnitudeRange &overallMag,
2592 bool &overallMagChanged) const 2588 bool &overallMagChanged) const
2593 { 2589 {
2594 Profiler profiler("SpectrogramLayer::paintDrawBuffer"); 2590 Profiler profiler("SpectrogramLayer::paintDrawBuffer");
2595 2591
2596 int minbin = int(binfory[0] + 0.0001); 2592 int minbin = int(binfory[0] + 0.0001);
2597 int maxbin = binfory[h-1]; 2593 int maxbin = int(binfory[h-1]);
2598 2594
2599 #ifdef DEBUG_SPECTROGRAM_REPAINT 2595 #ifdef DEBUG_SPECTROGRAM_REPAINT
2600 cerr << "minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl; 2596 cerr << "minbin " << minbin << ", maxbin " << maxbin << "; w " << w << ", h " << h << endl;
2601 #endif 2597 #endif
2602 if (minbin < 0) minbin = 0; 2598 if (minbin < 0) minbin = 0;
2687 fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1); 2683 fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1);
2688 } else if (m_normalizeColumns) { 2684 } else if (m_normalizeColumns) {
2689 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); 2685 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1);
2690 } else if (m_normalizeHybrid) { 2686 } else if (m_normalizeHybrid) {
2691 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); 2687 fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1);
2692 float max = fft->getMaximumMagnitudeAt(sx); 2688 double max = fft->getMaximumMagnitudeAt(sx);
2693 for (int i = minbin; i <= maxbin; ++i) { 2689 for (int i = minbin; i <= maxbin; ++i) {
2694 if (max > 0.f) { 2690 if (max > 0.0) {
2695 autoarray[i - minbin] *= log10(max); 2691 autoarray[i - minbin] = float(autoarray[i - minbin] * log10(max));
2696 } 2692 }
2697 } 2693 }
2698 } else { 2694 } else {
2699 fft->getMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1); 2695 fft->getMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1);
2700 } 2696 }
2713 psx = sx; 2709 psx = sx;
2714 } 2710 }
2715 2711
2716 for (int y = 0; y < h; ++y) { 2712 for (int y = 0; y < h; ++y) {
2717 2713
2718 float sy0 = binfory[y]; 2714 double sy0 = binfory[y];
2719 float sy1 = sy0 + 1; 2715 double sy1 = sy0 + 1;
2720 if (y+1 < h) sy1 = binfory[y+1]; 2716 if (y+1 < h) sy1 = binfory[y+1];
2721 2717
2722 float value = 0.f; 2718 double value = 0.0;
2723 2719
2724 if (interpolate && fabsf(sy1 - sy0) < 1.f) { 2720 if (interpolate && fabs(sy1 - sy0) < 1.0) {
2725 2721
2726 float centre = (sy0 + sy1) / 2; 2722 double centre = (sy0 + sy1) / 2;
2727 float dist = (centre - 0.5) - lrintf(centre - 0.5); 2723 double dist = (centre - 0.5) - rint(centre - 0.5);
2728 int bin = int(centre); 2724 int bin = int(centre);
2729 int other = (dist < 0 ? (bin-1) : (bin+1)); 2725 int other = (dist < 0 ? (bin-1) : (bin+1));
2730 if (bin < minbin) bin = minbin; 2726 if (bin < minbin) bin = minbin;
2731 if (bin > maxbin) bin = maxbin; 2727 if (bin > maxbin) bin = maxbin;
2732 if (other < minbin || other > maxbin) other = bin; 2728 if (other < minbin || other > maxbin) other = bin;
2733 float prop = 1.f - fabsf(dist); 2729 double prop = 1.0 - fabs(dist);
2734 2730
2735 float v0 = values[bin - minbin]; 2731 double v0 = values[bin - minbin];
2736 float v1 = values[other - minbin]; 2732 double v1 = values[other - minbin];
2737 if (m_binDisplay == PeakBins) { 2733 if (m_binDisplay == PeakBins) {
2738 if (bin == minbin || bin == maxbin || 2734 if (bin == minbin || bin == maxbin ||
2739 v0 < values[bin-minbin-1] || 2735 v0 < values[bin-minbin-1] ||
2740 v0 < values[bin-minbin+1]) v0 = 0.f; 2736 v0 < values[bin-minbin+1]) v0 = 0.0;
2741 if (other == minbin || other == maxbin || 2737 if (other == minbin || other == maxbin ||
2742 v1 < values[other-minbin-1] || 2738 v1 < values[other-minbin-1] ||
2743 v1 < values[other-minbin+1]) v1 = 0.f; 2739 v1 < values[other-minbin+1]) v1 = 0.0;
2744 } 2740 }
2745 if (v0 == 0.f && v1 == 0.f) continue; 2741 if (v0 == 0.0 && v1 == 0.0) continue;
2746 value = prop * v0 + (1.f - prop) * v1; 2742 value = prop * v0 + (1.0 - prop) * v1;
2747 2743
2748 if (m_colourScale != PhaseColourScale) { 2744 if (m_colourScale != PhaseColourScale) {
2749 if (!m_normalizeColumns) { 2745 if (!m_normalizeColumns) {
2750 value /= (m_fftSize/2.f); 2746 value /= (m_fftSize/2.0);
2751 } 2747 }
2752 mag.sample(value); 2748 mag.sample(float(value));
2753 value *= m_gain; 2749 value *= m_gain;
2754 } 2750 }
2755 2751
2756 peaks[y] = value; 2752 peaks[y] = float(value);
2757 2753
2758 } else { 2754 } else {
2759 2755
2760 int by0 = int(sy0 + 0.0001); 2756 int by0 = int(sy0 + 0.0001);
2761 int by1 = int(sy1 + 0.0001); 2757 int by1 = int(sy1 + 0.0001);
2770 value < values[bin-minbin+1]) continue; 2766 value < values[bin-minbin+1]) continue;
2771 } 2767 }
2772 2768
2773 if (m_colourScale != PhaseColourScale) { 2769 if (m_colourScale != PhaseColourScale) {
2774 if (!m_normalizeColumns) { 2770 if (!m_normalizeColumns) {
2775 value /= (m_fftSize/2.f); 2771 value /= (m_fftSize/2.0);
2776 } 2772 }
2777 mag.sample(value); 2773 mag.sample(float(value));
2778 value *= m_gain; 2774 value *= m_gain;
2779 } 2775 }
2780 2776
2781 if (value > peaks[y]) peaks[y] = value; //!!! not right for phase! 2777 if (value > peaks[y]) {
2778 peaks[y] = float(value); //!!! not right for phase!
2779 }
2782 } 2780 }
2783 } 2781 }
2784 } 2782 }
2785 2783
2786 if (mag.isSet()) { 2784 if (mag.isSet()) {
2798 } 2796 }
2799 } 2797 }
2800 2798
2801 for (int y = 0; y < h; ++y) { 2799 for (int y = 0; y < h; ++y) {
2802 2800
2803 float peak = peaks[y]; 2801 double peak = peaks[y];
2804 2802
2805 if (m_colourScale != PhaseColourScale && 2803 if (m_colourScale != PhaseColourScale &&
2806 (m_normalizeColumns || m_normalizeHybrid) && 2804 (m_normalizeColumns || m_normalizeHybrid) &&
2807 columnMax > 0.f) { 2805 columnMax > 0.f) {
2808 peak /= columnMax; 2806 peak /= columnMax;
2831 } 2829 }
2832 2830
2833 // cerr << "SpectrogramLayer: illuminateLocalFeatures(" 2831 // cerr << "SpectrogramLayer: illuminateLocalFeatures("
2834 // << localPos.x() << "," << localPos.y() << ")" << endl; 2832 // << localPos.x() << "," << localPos.y() << ")" << endl;
2835 2833
2836 float s0, s1; 2834 double s0, s1;
2837 float f0, f1; 2835 double f0, f1;
2838 2836
2839 if (getXBinRange(v, localPos.x(), s0, s1) && 2837 if (getXBinRange(v, localPos.x(), s0, s1) &&
2840 getYBinSourceRange(v, localPos.y(), f0, f1)) { 2838 getYBinSourceRange(v, localPos.y(), f0, f1)) {
2841 2839
2842 int s0i = int(s0 + 0.001); 2840 int s0i = int(s0 + 0.001);
2857 2855
2858 paint.drawRect(x0, y1, x1 - x0 + 1, y0 - y1 + 1); 2856 paint.drawRect(x0, y1, x1 - x0 + 1, y0 - y1 + 1);
2859 } 2857 }
2860 } 2858 }
2861 2859
2862 float 2860 double
2863 SpectrogramLayer::getYForFrequency(const View *v, float frequency) const 2861 SpectrogramLayer::getYForFrequency(const View *v, double frequency) const
2864 { 2862 {
2865 return v->getYForFrequency(frequency, 2863 return v->getYForFrequency(frequency,
2866 getEffectiveMinFrequency(), 2864 getEffectiveMinFrequency(),
2867 getEffectiveMaxFrequency(), 2865 getEffectiveMaxFrequency(),
2868 m_frequencyScale == LogFrequencyScale); 2866 m_frequencyScale == LogFrequencyScale);
2869 } 2867 }
2870 2868
2871 float 2869 double
2872 SpectrogramLayer::getFrequencyForY(const View *v, int y) const 2870 SpectrogramLayer::getFrequencyForY(const View *v, int y) const
2873 { 2871 {
2874 return v->getFrequencyForY(y, 2872 return v->getFrequencyForY(y,
2875 getEffectiveMinFrequency(), 2873 getEffectiveMinFrequency(),
2876 getEffectiveMaxFrequency(), 2874 getEffectiveMaxFrequency(),
2896 if (m_fftModels.find(v) == m_fftModels.end()) return ""; 2894 if (m_fftModels.find(v) == m_fftModels.end()) return "";
2897 return m_fftModels[v].first->getError(); 2895 return m_fftModels[v].first->getError();
2898 } 2896 }
2899 2897
2900 bool 2898 bool
2901 SpectrogramLayer::getValueExtents(float &min, float &max, 2899 SpectrogramLayer::getValueExtents(double &min, double &max,
2902 bool &logarithmic, QString &unit) const 2900 bool &logarithmic, QString &unit) const
2903 { 2901 {
2904 if (!m_model) return false; 2902 if (!m_model) return false;
2905 2903
2906 int sr = m_model->getSampleRate(); 2904 sv_samplerate_t sr = m_model->getSampleRate();
2907 min = float(sr) / m_fftSize; 2905 min = double(sr) / m_fftSize;
2908 max = float(sr) / 2; 2906 max = double(sr) / 2;
2909 2907
2910 logarithmic = (m_frequencyScale == LogFrequencyScale); 2908 logarithmic = (m_frequencyScale == LogFrequencyScale);
2911 unit = "Hz"; 2909 unit = "Hz";
2912 return true; 2910 return true;
2913 } 2911 }
2914 2912
2915 bool 2913 bool
2916 SpectrogramLayer::getDisplayExtents(float &min, float &max) const 2914 SpectrogramLayer::getDisplayExtents(double &min, double &max) const
2917 { 2915 {
2918 min = getEffectiveMinFrequency(); 2916 min = getEffectiveMinFrequency();
2919 max = getEffectiveMaxFrequency(); 2917 max = getEffectiveMaxFrequency();
2920 2918
2921 // SVDEBUG << "SpectrogramLayer::getDisplayExtents: " << min << "->" << max << endl; 2919 // SVDEBUG << "SpectrogramLayer::getDisplayExtents: " << min << "->" << max << endl;
2922 return true; 2920 return true;
2923 } 2921 }
2924 2922
2925 bool 2923 bool
2926 SpectrogramLayer::setDisplayExtents(float min, float max) 2924 SpectrogramLayer::setDisplayExtents(double min, double max)
2927 { 2925 {
2928 if (!m_model) return false; 2926 if (!m_model) return false;
2929 2927
2930 // SVDEBUG << "SpectrogramLayer::setDisplayExtents: " << min << "->" << max << endl; 2928 // SVDEBUG << "SpectrogramLayer::setDisplayExtents: " << min << "->" << max << endl;
2931 2929
2932 if (min < 0) min = 0; 2930 if (min < 0) min = 0;
2933 if (max > m_model->getSampleRate()/2.f) max = m_model->getSampleRate()/2.f; 2931 if (max > m_model->getSampleRate()/2.0) max = m_model->getSampleRate()/2.0;
2934 2932
2935 int minf = lrintf(min); 2933 int minf = int(lrint(min));
2936 int maxf = lrintf(max); 2934 int maxf = int(lrint(max));
2937 2935
2938 if (m_minFrequency == minf && m_maxFrequency == maxf) return true; 2936 if (m_minFrequency == minf && m_maxFrequency == maxf) return true;
2939 2937
2940 invalidateImageCaches(); 2938 invalidateImageCaches();
2941 invalidateMagnitudes(); 2939 invalidateMagnitudes();
2954 return true; 2952 return true;
2955 } 2953 }
2956 2954
2957 bool 2955 bool
2958 SpectrogramLayer::getYScaleValue(const View *v, int y, 2956 SpectrogramLayer::getYScaleValue(const View *v, int y,
2959 float &value, QString &unit) const 2957 double &value, QString &unit) const
2960 { 2958 {
2961 value = getFrequencyForY(v, y); 2959 value = getFrequencyForY(v, y);
2962 unit = "Hz"; 2960 unit = "Hz";
2963 return true; 2961 return true;
2964 } 2962 }
2965 2963
2966 bool 2964 bool
2967 SpectrogramLayer::snapToFeatureFrame(View *, int &frame, 2965 SpectrogramLayer::snapToFeatureFrame(View *,
2966 sv_frame_t &frame,
2968 int &resolution, 2967 int &resolution,
2969 SnapType snap) const 2968 SnapType snap) const
2970 { 2969 {
2971 resolution = getWindowIncrement(); 2970 resolution = getWindowIncrement();
2972 int left = (frame / resolution) * resolution; 2971 sv_frame_t left = (frame / resolution) * resolution;
2973 int right = left + resolution; 2972 sv_frame_t right = left + resolution;
2974 2973
2975 switch (snap) { 2974 switch (snap) {
2976 case SnapLeft: frame = left; break; 2975 case SnapLeft: frame = left; break;
2977 case SnapRight: frame = right; break; 2976 case SnapRight: frame = right; break;
2978 case SnapNearest: 2977 case SnapNearest:
3060 paint.setPen(m_crosshairColour); 3059 paint.setPen(m_crosshairColour);
3061 3060
3062 paint.drawLine(0, cursorPos.y(), cursorPos.x() - 1, cursorPos.y()); 3061 paint.drawLine(0, cursorPos.y(), cursorPos.x() - 1, cursorPos.y());
3063 paint.drawLine(cursorPos.x(), 0, cursorPos.x(), v->height()); 3062 paint.drawLine(cursorPos.x(), 0, cursorPos.x(), v->height());
3064 3063
3065 float fundamental = getFrequencyForY(v, cursorPos.y()); 3064 double fundamental = getFrequencyForY(v, cursorPos.y());
3066 3065
3067 v->drawVisibleText(paint, 3066 v->drawVisibleText(paint,
3068 sw + 2, 3067 sw + 2,
3069 cursorPos.y() - 2, 3068 cursorPos.y() - 2,
3070 QString("%1 Hz").arg(fundamental), 3069 QString("%1 Hz").arg(fundamental),
3077 cursorPos.y() + paint.fontMetrics().ascent() + 2, 3076 cursorPos.y() + paint.fontMetrics().ascent() + 2,
3078 pitchLabel, 3077 pitchLabel,
3079 View::OutlinedText); 3078 View::OutlinedText);
3080 } 3079 }
3081 3080
3082 int frame = v->getFrameForX(cursorPos.x()); 3081 sv_frame_t frame = v->getFrameForX(cursorPos.x());
3083 RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate()); 3082 RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate());
3084 QString rtLabel = QString("%1 s").arg(rt.toText(true).c_str()); 3083 QString rtLabel = QString("%1 s").arg(rt.toText(true).c_str());
3085 QString frameLabel = QString("%1").arg(frame); 3084 QString frameLabel = QString("%1").arg(frame);
3086 v->drawVisibleText(paint, 3085 v->drawVisibleText(paint,
3087 cursorPos.x() - paint.fontMetrics().width(frameLabel) - 2, 3086 cursorPos.x() - paint.fontMetrics().width(frameLabel) - 2,
3096 3095
3097 int harmonic = 2; 3096 int harmonic = 2;
3098 3097
3099 while (harmonic < 100) { 3098 while (harmonic < 100) {
3100 3099
3101 float hy = lrintf(getYForFrequency(v, fundamental * harmonic)); 3100 int hy = int(lrint(getYForFrequency(v, fundamental * harmonic)));
3102 if (hy < 0 || hy > v->height()) break; 3101 if (hy < 0 || hy > v->height()) break;
3103 3102
3104 int len = 7; 3103 int len = 7;
3105 3104
3106 if (harmonic % 2 == 0) { 3105 if (harmonic % 2 == 0) {
3110 len = 10; 3109 len = 10;
3111 } 3110 }
3112 } 3111 }
3113 3112
3114 paint.drawLine(cursorPos.x() - len, 3113 paint.drawLine(cursorPos.x() - len,
3115 int(hy), 3114 hy,
3116 cursorPos.x(), 3115 cursorPos.x(),
3117 int(hy)); 3116 hy);
3118 3117
3119 ++harmonic; 3118 ++harmonic;
3120 } 3119 }
3121 3120
3122 paint.restore(); 3121 paint.restore();
3128 int x = pos.x(); 3127 int x = pos.x();
3129 int y = pos.y(); 3128 int y = pos.y();
3130 3129
3131 if (!m_model || !m_model->isOK()) return ""; 3130 if (!m_model || !m_model->isOK()) return "";
3132 3131
3133 float magMin = 0, magMax = 0; 3132 double magMin = 0, magMax = 0;
3134 float phaseMin = 0, phaseMax = 0; 3133 double phaseMin = 0, phaseMax = 0;
3135 float freqMin = 0, freqMax = 0; 3134 double freqMin = 0, freqMax = 0;
3136 float adjFreqMin = 0, adjFreqMax = 0; 3135 double adjFreqMin = 0, adjFreqMax = 0;
3137 QString pitchMin, pitchMax; 3136 QString pitchMin, pitchMax;
3138 RealTime rtMin, rtMax; 3137 RealTime rtMin, rtMax;
3139 3138
3140 bool haveValues = false; 3139 bool haveValues = false;
3141 3140
3203 .arg(adjPitchText) 3202 .arg(adjPitchText)
3204 .arg(Pitch::getPitchLabelForFrequency(freqMin)); 3203 .arg(Pitch::getPitchLabelForFrequency(freqMin));
3205 } 3204 }
3206 3205
3207 if (haveValues) { 3206 if (haveValues) {
3208 float dbMin = AudioLevel::multiplier_to_dB(magMin); 3207 double dbMin = AudioLevel::multiplier_to_dB(magMin);
3209 float dbMax = AudioLevel::multiplier_to_dB(magMax); 3208 double dbMax = AudioLevel::multiplier_to_dB(magMax);
3210 QString dbMinString; 3209 QString dbMinString;
3211 QString dbMaxString; 3210 QString dbMaxString;
3212 if (dbMin == AudioLevel::DB_FLOOR) { 3211 if (dbMin == AudioLevel::DB_FLOOR) {
3213 dbMinString = tr("-Inf"); 3212 dbMinString = tr("-Inf");
3214 } else { 3213 } else {
3215 dbMinString = QString("%1").arg(lrintf(dbMin)); 3214 dbMinString = QString("%1").arg(lrint(dbMin));
3216 } 3215 }
3217 if (dbMax == AudioLevel::DB_FLOOR) { 3216 if (dbMax == AudioLevel::DB_FLOOR) {
3218 dbMaxString = tr("-Inf"); 3217 dbMaxString = tr("-Inf");
3219 } else { 3218 } else {
3220 dbMaxString = QString("%1").arg(lrintf(dbMax)); 3219 dbMaxString = QString("%1").arg(lrint(dbMax));
3221 } 3220 }
3222 if (lrintf(dbMin) != lrintf(dbMax)) { 3221 if (lrint(dbMin) != lrint(dbMax)) {
3223 text += tr("dB:\t%1 - %2").arg(dbMinString).arg(dbMaxString); 3222 text += tr("dB:\t%1 - %2").arg(dbMinString).arg(dbMaxString);
3224 } else { 3223 } else {
3225 text += tr("dB:\t%1").arg(dbMinString); 3224 text += tr("dB:\t%1").arg(dbMinString);
3226 } 3225 }
3227 if (phaseMin != phaseMax) { 3226 if (phaseMin != phaseMax) {
3280 3279
3281 int tickw = (m_frequencyScale == LogFrequencyScale ? 10 : 4); 3280 int tickw = (m_frequencyScale == LogFrequencyScale ? 10 : 4);
3282 int pkw = (m_frequencyScale == LogFrequencyScale ? 10 : 0); 3281 int pkw = (m_frequencyScale == LogFrequencyScale ? 10 : 0);
3283 3282
3284 int bins = m_fftSize / 2; 3283 int bins = m_fftSize / 2;
3285 int sr = m_model->getSampleRate(); 3284 sv_samplerate_t sr = m_model->getSampleRate();
3286 3285
3287 if (m_maxFrequency > 0) { 3286 if (m_maxFrequency > 0) {
3288 bins = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1); 3287 bins = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1);
3289 if (bins > m_fftSize / 2) bins = m_fftSize / 2; 3288 if (bins > m_fftSize / 2) bins = m_fftSize / 2;
3290 } 3289 }
3306 int ch = h - textHeight * (topLines + 1) - 8; 3305 int ch = h - textHeight * (topLines + 1) - 8;
3307 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1); 3306 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1);
3308 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1); 3307 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1);
3309 3308
3310 QString top, bottom; 3309 QString top, bottom;
3311 float min = m_viewMags[v].getMin(); 3310 double min = m_viewMags[v].getMin();
3312 float max = m_viewMags[v].getMax(); 3311 double max = m_viewMags[v].getMax();
3313 3312
3314 float dBmin = AudioLevel::multiplier_to_dB(min); 3313 double dBmin = AudioLevel::multiplier_to_dB(min);
3315 float dBmax = AudioLevel::multiplier_to_dB(max); 3314 double dBmax = AudioLevel::multiplier_to_dB(max);
3316 3315
3317 if (dBmax < -60.f) dBmax = -60.f; 3316 if (dBmax < -60.f) dBmax = -60.f;
3318 else top = QString("%1").arg(lrintf(dBmax)); 3317 else top = QString("%1").arg(lrint(dBmax));
3319 3318
3320 if (dBmin < dBmax - 60.f) dBmin = dBmax - 60.f; 3319 if (dBmin < dBmax - 60.f) dBmin = dBmax - 60.f;
3321 bottom = QString("%1").arg(lrintf(dBmin)); 3320 bottom = QString("%1").arg(lrint(dBmin));
3322 3321
3323 //!!! & phase etc 3322 //!!! & phase etc
3324 3323
3325 if (m_colourScale != PhaseColourScale) { 3324 if (m_colourScale != PhaseColourScale) {
3326 paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2, 3325 paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2,
3340 int lasty = 0; 3339 int lasty = 0;
3341 int lastdb = 0; 3340 int lastdb = 0;
3342 3341
3343 for (int i = 0; i < ch; ++i) { 3342 for (int i = 0; i < ch; ++i) {
3344 3343
3345 float dBval = dBmin + (((dBmax - dBmin) * i) / (ch - 1)); 3344 double dBval = dBmin + (((dBmax - dBmin) * i) / (ch - 1));
3346 int idb = int(dBval); 3345 int idb = int(dBval);
3347 3346
3348 float value = AudioLevel::dB_to_multiplier(dBval); 3347 double value = AudioLevel::dB_to_multiplier(dBval);
3349 int colour = getDisplayValue(v, value * m_gain); 3348 int colour = getDisplayValue(v, value * m_gain);
3350 3349
3351 paint.setPen(m_palette.getColour(colour)); 3350 paint.setPen(m_palette.getColour((unsigned char)colour));
3352 3351
3353 int y = textHeight * topLines + 4 + ch - i; 3352 int y = textHeight * topLines + 4 + ch - i;
3354 3353
3355 paint.drawLine(5 + cw - cbw, y, cw + 2, y); 3354 paint.drawLine(5 + cw - cbw, y, cw + 2, y);
3356 3355
3380 3379
3381 int bin = -1; 3380 int bin = -1;
3382 3381
3383 for (int y = 0; y < v->height(); ++y) { 3382 for (int y = 0; y < v->height(); ++y) {
3384 3383
3385 float q0, q1; 3384 double q0, q1;
3386 if (!getYBinRange(v, v->height() - y, q0, q1)) continue; 3385 if (!getYBinRange(v, v->height() - y, q0, q1)) continue;
3387 3386
3388 int vy; 3387 int vy;
3389 3388
3390 if (int(q0) > bin) { 3389 if (int(q0) > bin) {
3392 bin = int(q0); 3391 bin = int(q0);
3393 } else { 3392 } else {
3394 continue; 3393 continue;
3395 } 3394 }
3396 3395
3397 int freq = (sr * bin) / m_fftSize; 3396 int freq = int((sr * bin) / m_fftSize);
3398 3397
3399 if (py >= 0 && (vy - py) < textHeight - 1) { 3398 if (py >= 0 && (vy - py) < textHeight - 1) {
3400 if (m_frequencyScale == LinearFrequencyScale) { 3399 if (m_frequencyScale == LinearFrequencyScale) {
3401 paint.drawLine(w - tickw, h - vy, w, h - vy); 3400 paint.drawLine(w - tickw, h - vy, w, h - vy);
3402 } 3401 }
3428 } 3427 }
3429 3428
3430 class SpectrogramRangeMapper : public RangeMapper 3429 class SpectrogramRangeMapper : public RangeMapper
3431 { 3430 {
3432 public: 3431 public:
3433 SpectrogramRangeMapper(int sr, int /* fftsize */) : 3432 SpectrogramRangeMapper(sv_samplerate_t sr, int /* fftsize */) :
3434 m_dist(float(sr) / 2), 3433 m_dist(sr / 2),
3435 m_s2(sqrtf(sqrtf(2))) { } 3434 m_s2(sqrt(sqrt(2))) { }
3436 ~SpectrogramRangeMapper() { } 3435 ~SpectrogramRangeMapper() { }
3437 3436
3438 virtual int getPositionForValue(float value) const { 3437 virtual int getPositionForValue(double value) const {
3439 3438
3440 float dist = m_dist; 3439 double dist = m_dist;
3441 3440
3442 int n = 0; 3441 int n = 0;
3443 3442
3444 while (dist > (value + 0.00001) && dist > 0.1f) { 3443 while (dist > (value + 0.00001) && dist > 0.1) {
3445 dist /= m_s2; 3444 dist /= m_s2;
3446 ++n; 3445 ++n;
3447 } 3446 }
3448 3447
3449 return n; 3448 return n;
3450 } 3449 }
3451 3450
3452 virtual int getPositionForValueUnclamped(float value) const { 3451 virtual int getPositionForValueUnclamped(double value) const {
3453 // We don't really support this 3452 // We don't really support this
3454 return getPositionForValue(value); 3453 return getPositionForValue(value);
3455 } 3454 }
3456 3455
3457 virtual float getValueForPosition(int position) const { 3456 virtual double getValueForPosition(int position) const {
3458 3457
3459 // Vertical zoom step 0 shows the entire range from DC -> 3458 // Vertical zoom step 0 shows the entire range from DC ->
3460 // Nyquist frequency. Step 1 shows 2^(1/4) of the range of 3459 // Nyquist frequency. Step 1 shows 2^(1/4) of the range of
3461 // step 0, and so on until the visible range is smaller than 3460 // step 0, and so on until the visible range is smaller than
3462 // the frequency step between bins at the current fft size. 3461 // the frequency step between bins at the current fft size.
3463 3462
3464 float dist = m_dist; 3463 double dist = m_dist;
3465 3464
3466 int n = 0; 3465 int n = 0;
3467 while (n < position) { 3466 while (n < position) {
3468 dist /= m_s2; 3467 dist /= m_s2;
3469 ++n; 3468 ++n;
3470 } 3469 }
3471 3470
3472 return dist; 3471 return dist;
3473 } 3472 }
3474 3473
3475 virtual float getValueForPositionUnclamped(int position) const { 3474 virtual double getValueForPositionUnclamped(int position) const {
3476 // We don't really support this 3475 // We don't really support this
3477 return getValueForPosition(position); 3476 return getValueForPosition(position);
3478 } 3477 }
3479 3478
3480 virtual QString getUnit() const { return "Hz"; } 3479 virtual QString getUnit() const { return "Hz"; }
3481 3480
3482 protected: 3481 protected:
3483 float m_dist; 3482 double m_dist;
3484 float m_s2; 3483 double m_s2;
3485 }; 3484 };
3486 3485
3487 int 3486 int
3488 SpectrogramLayer::getVerticalZoomSteps(int &defaultStep) const 3487 SpectrogramLayer::getVerticalZoomSteps(int &defaultStep) const
3489 { 3488 {
3490 if (!m_model) return 0; 3489 if (!m_model) return 0;
3491 3490
3492 int sr = m_model->getSampleRate(); 3491 sv_samplerate_t sr = m_model->getSampleRate();
3493 3492
3494 SpectrogramRangeMapper mapper(sr, m_fftSize); 3493 SpectrogramRangeMapper mapper(sr, m_fftSize);
3495 3494
3496 // int maxStep = mapper.getPositionForValue((float(sr) / m_fftSize) + 0.001); 3495 // int maxStep = mapper.getPositionForValue((double(sr) / m_fftSize) + 0.001);
3497 int maxStep = mapper.getPositionForValue(0); 3496 int maxStep = mapper.getPositionForValue(0);
3498 int minStep = mapper.getPositionForValue(float(sr) / 2); 3497 int minStep = mapper.getPositionForValue(double(sr) / 2);
3499 3498
3500 int initialMax = m_initialMaxFrequency; 3499 int initialMax = m_initialMaxFrequency;
3501 if (initialMax == 0) initialMax = sr / 2; 3500 if (initialMax == 0) initialMax = int(sr / 2);
3502 3501
3503 defaultStep = mapper.getPositionForValue(initialMax) - minStep; 3502 defaultStep = mapper.getPositionForValue(initialMax) - minStep;
3504 3503
3505 // SVDEBUG << "SpectrogramLayer::getVerticalZoomSteps: " << maxStep - minStep << " (" << maxStep <<"-" << minStep << "), default is " << defaultStep << " (from initial max freq " << initialMax << ")" << endl; 3504 // SVDEBUG << "SpectrogramLayer::getVerticalZoomSteps: " << maxStep - minStep << " (" << maxStep <<"-" << minStep << "), default is " << defaultStep << " (from initial max freq " << initialMax << ")" << endl;
3506 3505
3510 int 3509 int
3511 SpectrogramLayer::getCurrentVerticalZoomStep() const 3510 SpectrogramLayer::getCurrentVerticalZoomStep() const
3512 { 3511 {
3513 if (!m_model) return 0; 3512 if (!m_model) return 0;
3514 3513
3515 float dmin, dmax; 3514 double dmin, dmax;
3516 getDisplayExtents(dmin, dmax); 3515 getDisplayExtents(dmin, dmax);
3517 3516
3518 SpectrogramRangeMapper mapper(m_model->getSampleRate(), m_fftSize); 3517 SpectrogramRangeMapper mapper(m_model->getSampleRate(), m_fftSize);
3519 int n = mapper.getPositionForValue(dmax - dmin); 3518 int n = mapper.getPositionForValue(dmax - dmin);
3520 // SVDEBUG << "SpectrogramLayer::getCurrentVerticalZoomStep: " << n << endl; 3519 // SVDEBUG << "SpectrogramLayer::getCurrentVerticalZoomStep: " << n << endl;
3524 void 3523 void
3525 SpectrogramLayer::setVerticalZoomStep(int step) 3524 SpectrogramLayer::setVerticalZoomStep(int step)
3526 { 3525 {
3527 if (!m_model) return; 3526 if (!m_model) return;
3528 3527
3529 float dmin = m_minFrequency, dmax = m_maxFrequency; 3528 double dmin = m_minFrequency, dmax = m_maxFrequency;
3530 // getDisplayExtents(dmin, dmax); 3529 // getDisplayExtents(dmin, dmax);
3531 3530
3532 // cerr << "current range " << dmin << " -> " << dmax << ", range " << dmax-dmin << ", mid " << (dmax + dmin)/2 << endl; 3531 // cerr << "current range " << dmin << " -> " << dmax << ", range " << dmax-dmin << ", mid " << (dmax + dmin)/2 << endl;
3533 3532
3534 int sr = m_model->getSampleRate(); 3533 sv_samplerate_t sr = m_model->getSampleRate();
3535 SpectrogramRangeMapper mapper(sr, m_fftSize); 3534 SpectrogramRangeMapper mapper(sr, m_fftSize);
3536 float newdist = mapper.getValueForPosition(step); 3535 double newdist = mapper.getValueForPosition(step);
3537 3536
3538 float newmin, newmax; 3537 double newmin, newmax;
3539 3538
3540 if (m_frequencyScale == LogFrequencyScale) { 3539 if (m_frequencyScale == LogFrequencyScale) {
3541 3540
3542 // need to pick newmin and newmax such that 3541 // need to pick newmin and newmax such that
3543 // 3542 //
3558 // so exp(2logmid) = exp(log(dmin) + log(dmax)) 3557 // so exp(2logmid) = exp(log(dmin) + log(dmax))
3559 // = exp(log(dmin.dmax)) 3558 // = exp(log(dmin.dmax))
3560 // = dmin.dmax 3559 // = dmin.dmax
3561 // so newmax = (newdist + sqrtf(newdist^2 + 4dmin.dmax)) / 2 3560 // so newmax = (newdist + sqrtf(newdist^2 + 4dmin.dmax)) / 2
3562 3561
3563 newmax = (newdist + sqrtf(newdist*newdist + 4*dmin*dmax)) / 2; 3562 newmax = (newdist + sqrt(newdist*newdist + 4*dmin*dmax)) / 2;
3564 newmin = newmax - newdist; 3563 newmin = newmax - newdist;
3565 3564
3566 // cerr << "newmin = " << newmin << ", newmax = " << newmax << endl; 3565 // cerr << "newmin = " << newmin << ", newmax = " << newmax << endl;
3567 3566
3568 } else { 3567 } else {
3569 float dmid = (dmax + dmin) / 2; 3568 double dmid = (dmax + dmin) / 2;
3570 newmin = dmid - newdist / 2; 3569 newmin = dmid - newdist / 2;
3571 newmax = dmid + newdist / 2; 3570 newmax = dmid + newdist / 2;
3572 } 3571 }
3573 3572
3574 float mmin, mmax; 3573 double mmin, mmax;
3575 mmin = 0; 3574 mmin = 0;
3576 mmax = float(sr) / 2; 3575 mmax = double(sr) / 2;
3577 3576
3578 if (newmin < mmin) { 3577 if (newmin < mmin) {
3579 newmax += (mmin - newmin); 3578 newmax += (mmin - newmin);
3580 newmin = mmin; 3579 newmin = mmin;
3581 } 3580 }
3583 newmax = mmax; 3582 newmax = mmax;
3584 } 3583 }
3585 3584
3586 // SVDEBUG << "SpectrogramLayer::setVerticalZoomStep: " << step << ": " << newmin << " -> " << newmax << " (range " << newdist << ")" << endl; 3585 // SVDEBUG << "SpectrogramLayer::setVerticalZoomStep: " << step << ": " << newmin << " -> " << newmax << " (range " << newdist << ")" << endl;
3587 3586
3588 setMinFrequency(lrintf(newmin)); 3587 setMinFrequency(int(lrint(newmin)));
3589 setMaxFrequency(lrintf(newmax)); 3588 setMaxFrequency(int(lrint(newmax)));
3590 } 3589 }
3591 3590
3592 RangeMapper * 3591 RangeMapper *
3593 SpectrogramLayer::getNewVerticalZoomRangeMapper() const 3592 SpectrogramLayer::getNewVerticalZoomRangeMapper() const
3594 { 3593 {
3598 3597
3599 void 3598 void
3600 SpectrogramLayer::updateMeasureRectYCoords(View *v, const MeasureRect &r) const 3599 SpectrogramLayer::updateMeasureRectYCoords(View *v, const MeasureRect &r) const
3601 { 3600 {
3602 int y0 = 0; 3601 int y0 = 0;
3603 if (r.startY > 0.0) y0 = getYForFrequency(v, r.startY); 3602 if (r.startY > 0.0) y0 = int(getYForFrequency(v, r.startY));
3604 3603
3605 int y1 = y0; 3604 int y1 = y0;
3606 if (r.endY > 0.0) y1 = getYForFrequency(v, r.endY); 3605 if (r.endY > 0.0) y1 = int(getYForFrequency(v, r.endY));
3607 3606
3608 // SVDEBUG << "SpectrogramLayer::updateMeasureRectYCoords: start " << r.startY << " -> " << y0 << ", end " << r.endY << " -> " << y1 << endl; 3607 // SVDEBUG << "SpectrogramLayer::updateMeasureRectYCoords: start " << r.startY << " -> " << y0 << ", end " << r.endY << " -> " << y1 << endl;
3609 3608
3610 r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0); 3609 r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0);
3611 } 3610 }