Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 922:26da827e8fb5 tonioni
Merge from cxx11 branch
| author | Chris Cannam |
|---|---|
| date | Mon, 23 Mar 2015 11:26:28 +0000 |
| parents | 28d05ae8741c |
| children | 94e4952a6774 b8187c83b93a |
comparison
equal
deleted
inserted
replaced
| 921:4968bbaf1ed8 | 922:26da827e8fb5 |
|---|---|
| 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 } |
