Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 1234:81dfe06a45c9
Untabify
author | Chris Cannam |
---|---|
date | Fri, 27 Jan 2017 11:39:29 +0000 |
parents | de1792daae07 |
children | a496986aa61b |
comparison
equal
deleted
inserted
replaced
1233:1a7c2ca31579 | 1234:81dfe06a45c9 |
---|---|
91 | 91 |
92 if (config == FullRangeDb) { | 92 if (config == FullRangeDb) { |
93 m_initialMaxFrequency = 0; | 93 m_initialMaxFrequency = 0; |
94 setMaxFrequency(0); | 94 setMaxFrequency(0); |
95 } else if (config == MelodicRange) { | 95 } else if (config == MelodicRange) { |
96 setWindowSize(8192); | 96 setWindowSize(8192); |
97 setWindowHopLevel(4); | 97 setWindowHopLevel(4); |
98 m_initialMaxFrequency = 1500; | 98 m_initialMaxFrequency = 1500; |
99 setMaxFrequency(1500); | 99 setMaxFrequency(1500); |
100 setMinFrequency(40); | 100 setMinFrequency(40); |
101 setColourScale(ColourScaleType::Linear); | 101 setColourScale(ColourScaleType::Linear); |
102 setColourMap(ColourMapper::Sunset); | 102 setColourMap(ColourMapper::Sunset); |
103 setBinScale(BinScale::Log); | 103 setBinScale(BinScale::Log); |
104 colourConfigName = "spectrogram-melodic-colour"; | 104 colourConfigName = "spectrogram-melodic-colour"; |
105 colourConfigDefault = int(ColourMapper::Sunset); | 105 colourConfigDefault = int(ColourMapper::Sunset); |
106 // setGain(20); | 106 // setGain(20); |
107 } else if (config == MelodicPeaks) { | 107 } else if (config == MelodicPeaks) { |
108 setWindowSize(4096); | 108 setWindowSize(4096); |
109 setWindowHopLevel(5); | 109 setWindowHopLevel(5); |
110 m_initialMaxFrequency = 2000; | 110 m_initialMaxFrequency = 2000; |
111 setMaxFrequency(2000); | 111 setMaxFrequency(2000); |
112 setMinFrequency(40); | 112 setMinFrequency(40); |
113 setBinScale(BinScale::Log); | 113 setBinScale(BinScale::Log); |
114 setColourScale(ColourScaleType::Linear); | 114 setColourScale(ColourScaleType::Linear); |
115 setBinDisplay(BinDisplay::PeakFrequencies); | 115 setBinDisplay(BinDisplay::PeakFrequencies); |
116 setNormalization(ColumnNormalization::Max1); | 116 setNormalization(ColumnNormalization::Max1); |
117 colourConfigName = "spectrogram-melodic-colour"; | 117 colourConfigName = "spectrogram-melodic-colour"; |
118 colourConfigDefault = int(ColourMapper::Sunset); | 118 colourConfigDefault = int(ColourMapper::Sunset); |
119 } | 119 } |
120 | 120 |
206 | 206 |
207 connectSignals(m_model); | 207 connectSignals(m_model); |
208 | 208 |
209 connect(m_model, SIGNAL(modelChanged()), this, SLOT(cacheInvalid())); | 209 connect(m_model, SIGNAL(modelChanged()), this, SLOT(cacheInvalid())); |
210 connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), | 210 connect(m_model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), |
211 this, SLOT(cacheInvalid(sv_frame_t, sv_frame_t))); | 211 this, SLOT(cacheInvalid(sv_frame_t, sv_frame_t))); |
212 | 212 |
213 emit modelReplaced(); | 213 emit modelReplaced(); |
214 } | 214 } |
215 | 215 |
216 Layer::PropertyList | 216 Layer::PropertyList |
270 SpectrogramLayer::getPropertyGroupName(const PropertyName &name) const | 270 SpectrogramLayer::getPropertyGroupName(const PropertyName &name) const |
271 { | 271 { |
272 if (name == "Bin Display" || | 272 if (name == "Bin Display" || |
273 name == "Frequency Scale") return tr("Bins"); | 273 name == "Frequency Scale") return tr("Bins"); |
274 if (name == "Window Size" || | 274 if (name == "Window Size" || |
275 name == "Window Increment") return tr("Window"); | 275 name == "Window Increment") return tr("Window"); |
276 if (name == "Colour" || | 276 if (name == "Colour" || |
277 name == "Threshold" || | 277 name == "Threshold" || |
278 name == "Colour Rotation") return tr("Colour"); | 278 name == "Colour Rotation") return tr("Colour"); |
279 if (name == "Normalization" || | 279 if (name == "Normalization" || |
280 name == "Gain" || | 280 name == "Gain" || |
281 name == "Colour Scale") return tr("Scale"); | 281 name == "Colour Scale") return tr("Scale"); |
282 return QString(); | 282 return QString(); |
283 } | 283 } |
284 | 284 |
285 int | 285 int |
286 SpectrogramLayer::getPropertyRangeAndValue(const PropertyName &name, | 286 SpectrogramLayer::getPropertyRangeAndValue(const PropertyName &name, |
287 int *min, int *max, int *deflt) const | 287 int *min, int *max, int *deflt) const |
288 { | 288 { |
289 int val = 0; | 289 int val = 0; |
290 | 290 |
291 int garbage0, garbage1, garbage2; | 291 int garbage0, garbage1, garbage2; |
292 if (!min) min = &garbage0; | 292 if (!min) min = &garbage0; |
293 if (!max) max = &garbage1; | 293 if (!max) max = &garbage1; |
294 if (!deflt) deflt = &garbage2; | 294 if (!deflt) deflt = &garbage2; |
295 | 295 |
296 if (name == "Gain") { | 296 if (name == "Gain") { |
297 | 297 |
298 *min = -50; | 298 *min = -50; |
299 *max = 50; | 299 *max = 50; |
300 | 300 |
301 *deflt = int(lrint(log10(m_initialGain) * 20.0)); | 301 *deflt = int(lrint(log10(m_initialGain) * 20.0)); |
302 if (*deflt < *min) *deflt = *min; | 302 if (*deflt < *min) *deflt = *min; |
303 if (*deflt > *max) *deflt = *max; | 303 if (*deflt > *max) *deflt = *max; |
304 | 304 |
305 val = int(lrint(log10(m_gain) * 20.0)); | 305 val = int(lrint(log10(m_gain) * 20.0)); |
306 if (val < *min) val = *min; | 306 if (val < *min) val = *min; |
307 if (val > *max) val = *max; | 307 if (val > *max) val = *max; |
308 | 308 |
309 } else if (name == "Threshold") { | 309 } else if (name == "Threshold") { |
310 | 310 |
311 *min = -81; | 311 *min = -81; |
312 *max = -1; | 312 *max = -1; |
313 | 313 |
314 *deflt = int(lrint(AudioLevel::multiplier_to_dB(m_initialThreshold))); | 314 *deflt = int(lrint(AudioLevel::multiplier_to_dB(m_initialThreshold))); |
315 if (*deflt < *min) *deflt = *min; | 315 if (*deflt < *min) *deflt = *min; |
316 if (*deflt > *max) *deflt = *max; | 316 if (*deflt > *max) *deflt = *max; |
317 | 317 |
318 val = int(lrint(AudioLevel::multiplier_to_dB(m_threshold))); | 318 val = int(lrint(AudioLevel::multiplier_to_dB(m_threshold))); |
319 if (val < *min) val = *min; | 319 if (val < *min) val = *min; |
320 if (val > *max) val = *max; | 320 if (val > *max) val = *max; |
321 | 321 |
322 } else if (name == "Colour Rotation") { | 322 } else if (name == "Colour Rotation") { |
323 | 323 |
324 *min = 0; | 324 *min = 0; |
325 *max = 256; | 325 *max = 256; |
326 *deflt = m_initialRotation; | 326 *deflt = m_initialRotation; |
327 | 327 |
328 val = m_colourRotation; | 328 val = m_colourRotation; |
329 | 329 |
330 } else if (name == "Colour Scale") { | 330 } else if (name == "Colour Scale") { |
331 | 331 |
332 // linear, meter, db^2, db, phase | 332 // linear, meter, db^2, db, phase |
333 *min = 0; | 333 *min = 0; |
334 *max = 4; | 334 *max = 4; |
335 *deflt = 2; | 335 *deflt = 2; |
336 | 336 |
337 val = convertFromColourScale(m_colourScale, m_colourScaleMultiple); | 337 val = convertFromColourScale(m_colourScale, m_colourScaleMultiple); |
338 | 338 |
339 } else if (name == "Colour") { | 339 } else if (name == "Colour") { |
340 | 340 |
341 *min = 0; | 341 *min = 0; |
342 *max = ColourMapper::getColourMapCount() - 1; | 342 *max = ColourMapper::getColourMapCount() - 1; |
343 *deflt = 0; | 343 *deflt = 0; |
344 | 344 |
345 val = m_colourMap; | 345 val = m_colourMap; |
346 | 346 |
347 } else if (name == "Window Size") { | 347 } else if (name == "Window Size") { |
348 | 348 |
349 *min = 0; | 349 *min = 0; |
350 *max = 10; | 350 *max = 10; |
351 *deflt = 5; | 351 *deflt = 5; |
352 | 352 |
353 val = 0; | 353 val = 0; |
354 int ws = m_windowSize; | 354 int ws = m_windowSize; |
355 while (ws > 32) { ws >>= 1; val ++; } | 355 while (ws > 32) { ws >>= 1; val ++; } |
356 | 356 |
357 } else if (name == "Window Increment") { | 357 } else if (name == "Window Increment") { |
358 | 358 |
359 *min = 0; | 359 *min = 0; |
360 *max = 5; | 360 *max = 5; |
361 *deflt = 2; | 361 *deflt = 2; |
362 | 362 |
363 val = m_windowHopLevel; | 363 val = m_windowHopLevel; |
364 | 364 |
365 } else if (name == "Min Frequency") { | 365 } else if (name == "Min Frequency") { |
366 | 366 |
367 *min = 0; | 367 *min = 0; |
368 *max = 9; | 368 *max = 9; |
369 *deflt = 1; | 369 *deflt = 1; |
370 | 370 |
371 switch (m_minFrequency) { | 371 switch (m_minFrequency) { |
372 case 0: default: val = 0; break; | 372 case 0: default: val = 0; break; |
373 case 10: val = 1; break; | 373 case 10: val = 1; break; |
374 case 20: val = 2; break; | 374 case 20: val = 2; break; |
375 case 40: val = 3; break; | 375 case 40: val = 3; break; |
376 case 100: val = 4; break; | 376 case 100: val = 4; break; |
377 case 250: val = 5; break; | 377 case 250: val = 5; break; |
378 case 500: val = 6; break; | 378 case 500: val = 6; break; |
379 case 1000: val = 7; break; | 379 case 1000: val = 7; break; |
380 case 4000: val = 8; break; | 380 case 4000: val = 8; break; |
381 case 10000: val = 9; break; | 381 case 10000: val = 9; break; |
382 } | 382 } |
383 | 383 |
384 } else if (name == "Max Frequency") { | 384 } else if (name == "Max Frequency") { |
385 | 385 |
386 *min = 0; | 386 *min = 0; |
387 *max = 9; | 387 *max = 9; |
388 *deflt = 6; | 388 *deflt = 6; |
389 | 389 |
390 switch (m_maxFrequency) { | 390 switch (m_maxFrequency) { |
391 case 500: val = 0; break; | 391 case 500: val = 0; break; |
392 case 1000: val = 1; break; | 392 case 1000: val = 1; break; |
393 case 1500: val = 2; break; | 393 case 1500: val = 2; break; |
394 case 2000: val = 3; break; | 394 case 2000: val = 3; break; |
395 case 4000: val = 4; break; | 395 case 4000: val = 4; break; |
396 case 6000: val = 5; break; | 396 case 6000: val = 5; break; |
397 case 8000: val = 6; break; | 397 case 8000: val = 6; break; |
398 case 12000: val = 7; break; | 398 case 12000: val = 7; break; |
399 case 16000: val = 8; break; | 399 case 16000: val = 8; break; |
400 default: val = 9; break; | 400 default: val = 9; break; |
401 } | 401 } |
402 | 402 |
403 } else if (name == "Frequency Scale") { | 403 } else if (name == "Frequency Scale") { |
404 | 404 |
405 *min = 0; | 405 *min = 0; |
406 *max = 1; | 406 *max = 1; |
407 *deflt = int(BinScale::Linear); | 407 *deflt = int(BinScale::Linear); |
408 val = (int)m_binScale; | 408 val = (int)m_binScale; |
409 | 409 |
410 } else if (name == "Bin Display") { | 410 } else if (name == "Bin Display") { |
411 | 411 |
412 *min = 0; | 412 *min = 0; |
413 *max = 2; | 413 *max = 2; |
414 *deflt = int(BinDisplay::AllBins); | 414 *deflt = int(BinDisplay::AllBins); |
415 val = (int)m_binDisplay; | 415 val = (int)m_binDisplay; |
416 | 416 |
417 } else if (name == "Normalization") { | 417 } else if (name == "Normalization") { |
418 | 418 |
419 *min = 0; | 419 *min = 0; |
420 *max = 3; | 420 *max = 3; |
421 *deflt = 0; | 421 *deflt = 0; |
422 | 422 |
423 val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea); | 423 val = convertFromColumnNorm(m_normalization, m_normalizeVisibleArea); |
424 | 424 |
425 } else { | 425 } else { |
426 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); | 426 val = Layer::getPropertyRangeAndValue(name, min, max, deflt); |
427 } | 427 } |
428 | 428 |
429 return val; | 429 return val; |
430 } | 430 } |
431 | 431 |
432 QString | 432 QString |
433 SpectrogramLayer::getPropertyValueLabel(const PropertyName &name, | 433 SpectrogramLayer::getPropertyValueLabel(const PropertyName &name, |
434 int value) const | 434 int value) const |
435 { | 435 { |
436 if (name == "Colour") { | 436 if (name == "Colour") { |
437 return ColourMapper::getColourMapName(value); | 437 return ColourMapper::getColourMapName(value); |
438 } | 438 } |
439 if (name == "Colour Scale") { | 439 if (name == "Colour Scale") { |
440 switch (value) { | 440 switch (value) { |
441 default: | 441 default: |
442 case 0: return tr("Linear"); | 442 case 0: return tr("Linear"); |
443 case 1: return tr("Meter"); | 443 case 1: return tr("Meter"); |
444 case 2: return tr("dBV^2"); | 444 case 2: return tr("dBV^2"); |
445 case 3: return tr("dBV"); | 445 case 3: return tr("dBV"); |
446 case 4: return tr("Phase"); | 446 case 4: return tr("Phase"); |
447 } | 447 } |
448 } | 448 } |
449 if (name == "Normalization") { | 449 if (name == "Normalization") { |
450 switch(value) { | 450 switch(value) { |
451 default: | 451 default: |
452 case 0: return tr("None"); | 452 case 0: return tr("None"); |
455 case 3: return tr("Hybrid"); | 455 case 3: return tr("Hybrid"); |
456 } | 456 } |
457 // return ""; // icon only | 457 // return ""; // icon only |
458 } | 458 } |
459 if (name == "Window Size") { | 459 if (name == "Window Size") { |
460 return QString("%1").arg(32 << value); | 460 return QString("%1").arg(32 << value); |
461 } | 461 } |
462 if (name == "Window Increment") { | 462 if (name == "Window Increment") { |
463 switch (value) { | 463 switch (value) { |
464 default: | 464 default: |
465 case 0: return tr("None"); | 465 case 0: return tr("None"); |
466 case 1: return tr("25 %"); | 466 case 1: return tr("25 %"); |
467 case 2: return tr("50 %"); | 467 case 2: return tr("50 %"); |
468 case 3: return tr("75 %"); | 468 case 3: return tr("75 %"); |
469 case 4: return tr("87.5 %"); | 469 case 4: return tr("87.5 %"); |
470 case 5: return tr("93.75 %"); | 470 case 5: return tr("93.75 %"); |
471 } | 471 } |
472 } | 472 } |
473 if (name == "Min Frequency") { | 473 if (name == "Min Frequency") { |
474 switch (value) { | 474 switch (value) { |
475 default: | 475 default: |
476 case 0: return tr("No min"); | 476 case 0: return tr("No min"); |
477 case 1: return tr("10 Hz"); | 477 case 1: return tr("10 Hz"); |
478 case 2: return tr("20 Hz"); | 478 case 2: return tr("20 Hz"); |
479 case 3: return tr("40 Hz"); | 479 case 3: return tr("40 Hz"); |
480 case 4: return tr("100 Hz"); | 480 case 4: return tr("100 Hz"); |
481 case 5: return tr("250 Hz"); | 481 case 5: return tr("250 Hz"); |
482 case 6: return tr("500 Hz"); | 482 case 6: return tr("500 Hz"); |
483 case 7: return tr("1 KHz"); | 483 case 7: return tr("1 KHz"); |
484 case 8: return tr("4 KHz"); | 484 case 8: return tr("4 KHz"); |
485 case 9: return tr("10 KHz"); | 485 case 9: return tr("10 KHz"); |
486 } | 486 } |
487 } | 487 } |
488 if (name == "Max Frequency") { | 488 if (name == "Max Frequency") { |
489 switch (value) { | 489 switch (value) { |
490 default: | 490 default: |
491 case 0: return tr("500 Hz"); | 491 case 0: return tr("500 Hz"); |
492 case 1: return tr("1 KHz"); | 492 case 1: return tr("1 KHz"); |
493 case 2: return tr("1.5 KHz"); | 493 case 2: return tr("1.5 KHz"); |
494 case 3: return tr("2 KHz"); | 494 case 3: return tr("2 KHz"); |
495 case 4: return tr("4 KHz"); | 495 case 4: return tr("4 KHz"); |
496 case 5: return tr("6 KHz"); | 496 case 5: return tr("6 KHz"); |
497 case 6: return tr("8 KHz"); | 497 case 6: return tr("8 KHz"); |
498 case 7: return tr("12 KHz"); | 498 case 7: return tr("12 KHz"); |
499 case 8: return tr("16 KHz"); | 499 case 8: return tr("16 KHz"); |
500 case 9: return tr("No max"); | 500 case 9: return tr("No max"); |
501 } | 501 } |
502 } | 502 } |
503 if (name == "Frequency Scale") { | 503 if (name == "Frequency Scale") { |
504 switch (value) { | 504 switch (value) { |
505 default: | 505 default: |
506 case 0: return tr("Linear"); | 506 case 0: return tr("Linear"); |
507 case 1: return tr("Log"); | 507 case 1: return tr("Log"); |
508 } | 508 } |
509 } | 509 } |
510 if (name == "Bin Display") { | 510 if (name == "Bin Display") { |
511 switch (value) { | 511 switch (value) { |
512 default: | 512 default: |
513 case 0: return tr("All Bins"); | 513 case 0: return tr("All Bins"); |
514 case 1: return tr("Peak Bins"); | 514 case 1: return tr("Peak Bins"); |
515 case 2: return tr("Frequencies"); | 515 case 2: return tr("Frequencies"); |
516 } | 516 } |
517 } | 517 } |
518 return tr("<unknown>"); | 518 return tr("<unknown>"); |
519 } | 519 } |
520 | 520 |
521 QString | 521 QString |
549 | 549 |
550 void | 550 void |
551 SpectrogramLayer::setProperty(const PropertyName &name, int value) | 551 SpectrogramLayer::setProperty(const PropertyName &name, int value) |
552 { | 552 { |
553 if (name == "Gain") { | 553 if (name == "Gain") { |
554 setGain(float(pow(10, float(value)/20.0))); | 554 setGain(float(pow(10, float(value)/20.0))); |
555 } else if (name == "Threshold") { | 555 } else if (name == "Threshold") { |
556 if (value == -81) setThreshold(0.0); | 556 if (value == -81) setThreshold(0.0); |
557 else setThreshold(float(AudioLevel::dB_to_multiplier(value))); | 557 else setThreshold(float(AudioLevel::dB_to_multiplier(value))); |
558 } else if (name == "Colour Rotation") { | 558 } else if (name == "Colour Rotation") { |
559 setColourRotation(value); | 559 setColourRotation(value); |
560 } else if (name == "Colour") { | 560 } else if (name == "Colour") { |
561 setColourMap(value); | 561 setColourMap(value); |
562 } else if (name == "Window Size") { | 562 } else if (name == "Window Size") { |
563 setWindowSize(32 << value); | 563 setWindowSize(32 << value); |
564 } else if (name == "Window Increment") { | 564 } else if (name == "Window Increment") { |
565 setWindowHopLevel(value); | 565 setWindowHopLevel(value); |
566 } else if (name == "Min Frequency") { | 566 } else if (name == "Min Frequency") { |
567 switch (value) { | 567 switch (value) { |
568 default: | 568 default: |
569 case 0: setMinFrequency(0); break; | 569 case 0: setMinFrequency(0); break; |
570 case 1: setMinFrequency(10); break; | 570 case 1: setMinFrequency(10); break; |
571 case 2: setMinFrequency(20); break; | 571 case 2: setMinFrequency(20); break; |
572 case 3: setMinFrequency(40); break; | 572 case 3: setMinFrequency(40); break; |
573 case 4: setMinFrequency(100); break; | 573 case 4: setMinFrequency(100); break; |
574 case 5: setMinFrequency(250); break; | 574 case 5: setMinFrequency(250); break; |
575 case 6: setMinFrequency(500); break; | 575 case 6: setMinFrequency(500); break; |
576 case 7: setMinFrequency(1000); break; | 576 case 7: setMinFrequency(1000); break; |
577 case 8: setMinFrequency(4000); break; | 577 case 8: setMinFrequency(4000); break; |
578 case 9: setMinFrequency(10000); break; | 578 case 9: setMinFrequency(10000); break; |
579 } | 579 } |
580 int vs = getCurrentVerticalZoomStep(); | 580 int vs = getCurrentVerticalZoomStep(); |
581 if (vs != m_lastEmittedZoomStep) { | 581 if (vs != m_lastEmittedZoomStep) { |
582 emit verticalZoomChanged(); | 582 emit verticalZoomChanged(); |
583 m_lastEmittedZoomStep = vs; | 583 m_lastEmittedZoomStep = vs; |
584 } | 584 } |
585 } else if (name == "Max Frequency") { | 585 } else if (name == "Max Frequency") { |
586 switch (value) { | 586 switch (value) { |
587 case 0: setMaxFrequency(500); break; | 587 case 0: setMaxFrequency(500); break; |
588 case 1: setMaxFrequency(1000); break; | 588 case 1: setMaxFrequency(1000); break; |
589 case 2: setMaxFrequency(1500); break; | 589 case 2: setMaxFrequency(1500); break; |
590 case 3: setMaxFrequency(2000); break; | 590 case 3: setMaxFrequency(2000); break; |
591 case 4: setMaxFrequency(4000); break; | 591 case 4: setMaxFrequency(4000); break; |
592 case 5: setMaxFrequency(6000); break; | 592 case 5: setMaxFrequency(6000); break; |
593 case 6: setMaxFrequency(8000); break; | 593 case 6: setMaxFrequency(8000); break; |
594 case 7: setMaxFrequency(12000); break; | 594 case 7: setMaxFrequency(12000); break; |
595 case 8: setMaxFrequency(16000); break; | 595 case 8: setMaxFrequency(16000); break; |
596 default: | 596 default: |
597 case 9: setMaxFrequency(0); break; | 597 case 9: setMaxFrequency(0); break; |
598 } | 598 } |
599 int vs = getCurrentVerticalZoomStep(); | 599 int vs = getCurrentVerticalZoomStep(); |
600 if (vs != m_lastEmittedZoomStep) { | 600 if (vs != m_lastEmittedZoomStep) { |
601 emit verticalZoomChanged(); | 601 emit verticalZoomChanged(); |
602 m_lastEmittedZoomStep = vs; | 602 m_lastEmittedZoomStep = vs; |
603 } | 603 } |
604 } else if (name == "Colour Scale") { | 604 } else if (name == "Colour Scale") { |
605 setColourScaleMultiple(1.0); | 605 setColourScaleMultiple(1.0); |
606 switch (value) { | 606 switch (value) { |
607 default: | 607 default: |
608 case 0: setColourScale(ColourScaleType::Linear); break; | 608 case 0: setColourScale(ColourScaleType::Linear); break; |
609 case 1: setColourScale(ColourScaleType::Meter); break; | 609 case 1: setColourScale(ColourScaleType::Meter); break; |
610 case 2: | 610 case 2: |
611 setColourScale(ColourScaleType::Log); | 611 setColourScale(ColourScaleType::Log); |
612 setColourScaleMultiple(2.0); | 612 setColourScaleMultiple(2.0); |
613 break; | 613 break; |
614 case 3: setColourScale(ColourScaleType::Log); break; | 614 case 3: setColourScale(ColourScaleType::Log); break; |
615 case 4: setColourScale(ColourScaleType::Phase); break; | 615 case 4: setColourScale(ColourScaleType::Phase); break; |
616 } | 616 } |
617 } else if (name == "Frequency Scale") { | 617 } else if (name == "Frequency Scale") { |
618 switch (value) { | 618 switch (value) { |
619 default: | 619 default: |
620 case 0: setBinScale(BinScale::Linear); break; | 620 case 0: setBinScale(BinScale::Linear); break; |
621 case 1: setBinScale(BinScale::Log); break; | 621 case 1: setBinScale(BinScale::Log); break; |
622 } | 622 } |
623 } else if (name == "Bin Display") { | 623 } else if (name == "Bin Display") { |
624 switch (value) { | 624 switch (value) { |
625 default: | 625 default: |
626 case 0: setBinDisplay(BinDisplay::AllBins); break; | 626 case 0: setBinDisplay(BinDisplay::AllBins); break; |
627 case 1: setBinDisplay(BinDisplay::PeakBins); break; | 627 case 1: setBinDisplay(BinDisplay::PeakBins); break; |
628 case 2: setBinDisplay(BinDisplay::PeakFrequencies); break; | 628 case 2: setBinDisplay(BinDisplay::PeakFrequencies); break; |
629 } | 629 } |
630 } else if (name == "Normalization") { | 630 } else if (name == "Normalization") { |
631 auto n = convertToColumnNorm(value); | 631 auto n = convertToColumnNorm(value); |
632 setNormalization(n.first); | 632 setNormalization(n.first); |
633 setNormalizeVisibleArea(n.second); | 633 setNormalizeVisibleArea(n.second); |
634 } | 634 } |
777 | 777 |
778 void | 778 void |
779 SpectrogramLayer::setGain(float gain) | 779 SpectrogramLayer::setGain(float gain) |
780 { | 780 { |
781 // SVDEBUG << "SpectrogramLayer::setGain(" << gain << ") (my gain is now " | 781 // SVDEBUG << "SpectrogramLayer::setGain(" << gain << ") (my gain is now " |
782 // << m_gain << ")" << endl; | 782 // << m_gain << ")" << endl; |
783 | 783 |
784 if (m_gain == gain) return; | 784 if (m_gain == gain) return; |
785 | 785 |
786 invalidateRenderers(); | 786 invalidateRenderers(); |
787 | 787 |
862 if (r < 0) r = 0; | 862 if (r < 0) r = 0; |
863 if (r > 256) r = 256; | 863 if (r > 256) r = 256; |
864 int distance = r - m_colourRotation; | 864 int distance = r - m_colourRotation; |
865 | 865 |
866 if (distance != 0) { | 866 if (distance != 0) { |
867 m_colourRotation = r; | 867 m_colourRotation = r; |
868 } | 868 } |
869 | 869 |
870 // Initially the idea with colour rotation was that we would just | 870 // Initially the idea with colour rotation was that we would just |
871 // rotate the palette of an already-generated cache. That's not | 871 // rotate the palette of an already-generated cache. That's not |
872 // really practical now that cacheing is handled in a separate | 872 // really practical now that cacheing is handled in a separate |
1014 return; | 1014 return; |
1015 } | 1015 } |
1016 | 1016 |
1017 Layer::setLayerDormant(v, true); | 1017 Layer::setLayerDormant(v, true); |
1018 | 1018 |
1019 invalidateRenderers(); | 1019 invalidateRenderers(); |
1020 | 1020 |
1021 } else { | 1021 } else { |
1022 | 1022 |
1023 Layer::setLayerDormant(v, false); | 1023 Layer::setLayerDormant(v, false); |
1024 } | 1024 } |
1025 } | 1025 } |
1075 { | 1075 { |
1076 sv_samplerate_t sr = m_model->getSampleRate(); | 1076 sv_samplerate_t sr = m_model->getSampleRate(); |
1077 double minf = double(sr) / getFFTSize(); | 1077 double minf = double(sr) / getFFTSize(); |
1078 | 1078 |
1079 if (m_minFrequency > 0.0) { | 1079 if (m_minFrequency > 0.0) { |
1080 int minbin = int((double(m_minFrequency) * getFFTSize()) / sr + 0.01); | 1080 int minbin = int((double(m_minFrequency) * getFFTSize()) / sr + 0.01); |
1081 if (minbin < 1) minbin = 1; | 1081 if (minbin < 1) minbin = 1; |
1082 minf = minbin * sr / getFFTSize(); | 1082 minf = minbin * sr / getFFTSize(); |
1083 } | 1083 } |
1084 | 1084 |
1085 return minf; | 1085 return minf; |
1086 } | 1086 } |
1087 | 1087 |
1090 { | 1090 { |
1091 sv_samplerate_t sr = m_model->getSampleRate(); | 1091 sv_samplerate_t sr = m_model->getSampleRate(); |
1092 double maxf = double(sr) / 2; | 1092 double maxf = double(sr) / 2; |
1093 | 1093 |
1094 if (m_maxFrequency > 0.0) { | 1094 if (m_maxFrequency > 0.0) { |
1095 int maxbin = int((double(m_maxFrequency) * getFFTSize()) / sr + 0.1); | 1095 int maxbin = int((double(m_maxFrequency) * getFFTSize()) / sr + 0.1); |
1096 if (maxbin > getFFTSize() / 2) maxbin = getFFTSize() / 2; | 1096 if (maxbin > getFFTSize() / 2) maxbin = getFFTSize() / 2; |
1097 maxf = maxbin * sr / getFFTSize(); | 1097 maxf = maxbin * sr / getFFTSize(); |
1098 } | 1098 } |
1099 | 1099 |
1100 return maxf; | 1100 return maxf; |
1101 } | 1101 } |
1102 | 1102 |
1152 // Each pixel column covers an exact range of sample frames: | 1152 // Each pixel column covers an exact range of sample frames: |
1153 sv_frame_t f0 = v->getFrameForX(x) - modelStart; | 1153 sv_frame_t f0 = v->getFrameForX(x) - modelStart; |
1154 sv_frame_t f1 = v->getFrameForX(x + 1) - modelStart - 1; | 1154 sv_frame_t f1 = v->getFrameForX(x + 1) - modelStart - 1; |
1155 | 1155 |
1156 if (f1 < int(modelStart) || f0 > int(modelEnd)) { | 1156 if (f1 < int(modelStart) || f0 > int(modelEnd)) { |
1157 return false; | 1157 return false; |
1158 } | 1158 } |
1159 | 1159 |
1160 // And that range may be drawn from a possibly non-integral | 1160 // And that range may be drawn from a possibly non-integral |
1161 // range of spectrogram windows: | 1161 // range of spectrogram windows: |
1162 | 1162 |
1177 int s1i = int(s1); | 1177 int s1i = int(s1); |
1178 | 1178 |
1179 int windowIncrement = getWindowIncrement(); | 1179 int windowIncrement = getWindowIncrement(); |
1180 int w0 = s0i * windowIncrement - (m_windowSize - windowIncrement)/2; | 1180 int w0 = s0i * windowIncrement - (m_windowSize - windowIncrement)/2; |
1181 int w1 = s1i * windowIncrement + windowIncrement + | 1181 int w1 = s1i * windowIncrement + windowIncrement + |
1182 (m_windowSize - windowIncrement)/2 - 1; | 1182 (m_windowSize - windowIncrement)/2 - 1; |
1183 | 1183 |
1184 min = RealTime::frame2RealTime(w0, m_model->getSampleRate()); | 1184 min = RealTime::frame2RealTime(w0, m_model->getSampleRate()); |
1185 max = RealTime::frame2RealTime(w1, m_model->getSampleRate()); | 1185 max = RealTime::frame2RealTime(w1, m_model->getSampleRate()); |
1186 return true; | 1186 return true; |
1187 } | 1187 } |
1197 int q1i = int(q1); | 1197 int q1i = int(q1); |
1198 | 1198 |
1199 sv_samplerate_t sr = m_model->getSampleRate(); | 1199 sv_samplerate_t sr = m_model->getSampleRate(); |
1200 | 1200 |
1201 for (int q = q0i; q <= q1i; ++q) { | 1201 for (int q = q0i; q <= q1i; ++q) { |
1202 if (q == q0i) freqMin = (sr * q) / getFFTSize(); | 1202 if (q == q0i) freqMin = (sr * q) / getFFTSize(); |
1203 if (q == q1i) freqMax = (sr * (q+1)) / getFFTSize(); | 1203 if (q == q1i) freqMax = (sr * (q+1)) / getFFTSize(); |
1204 } | 1204 } |
1205 return true; | 1205 return true; |
1206 } | 1206 } |
1207 | 1207 |
1208 bool | 1208 bool |
1209 SpectrogramLayer::getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y, | 1209 SpectrogramLayer::getAdjustedYBinSourceRange(LayerGeometryProvider *v, int x, int y, |
1210 double &freqMin, double &freqMax, | 1210 double &freqMin, double &freqMax, |
1211 double &adjFreqMin, double &adjFreqMax) | 1211 double &adjFreqMin, double &adjFreqMax) |
1212 const | 1212 const |
1213 { | 1213 { |
1214 if (!m_model || !m_model->isOK() || !m_model->isReady()) { | 1214 if (!m_model || !m_model->isOK() || !m_model->isReady()) { |
1215 return false; | 1215 return false; |
1216 } | 1216 } |
1217 | 1217 |
1218 FFTModel *fft = getFFTModel(); | 1218 FFTModel *fft = getFFTModel(); |
1219 if (!fft) return false; | 1219 if (!fft) return false; |
1220 | 1220 |
1233 sv_samplerate_t sr = m_model->getSampleRate(); | 1233 sv_samplerate_t sr = m_model->getSampleRate(); |
1234 | 1234 |
1235 bool haveAdj = false; | 1235 bool haveAdj = false; |
1236 | 1236 |
1237 bool peaksOnly = (m_binDisplay == BinDisplay::PeakBins || | 1237 bool peaksOnly = (m_binDisplay == BinDisplay::PeakBins || |
1238 m_binDisplay == BinDisplay::PeakFrequencies); | 1238 m_binDisplay == BinDisplay::PeakFrequencies); |
1239 | 1239 |
1240 for (int q = q0i; q <= q1i; ++q) { | 1240 for (int q = q0i; q <= q1i; ++q) { |
1241 | 1241 |
1242 for (int s = s0i; s <= s1i; ++s) { | 1242 for (int s = s0i; s <= s1i; ++s) { |
1243 | 1243 |
1244 double binfreq = (double(sr) * q) / m_windowSize; | 1244 double binfreq = (double(sr) * q) / m_windowSize; |
1245 if (q == q0i) freqMin = binfreq; | 1245 if (q == q0i) freqMin = binfreq; |
1246 if (q == q1i) freqMax = binfreq; | 1246 if (q == q1i) freqMax = binfreq; |
1247 | 1247 |
1248 if (peaksOnly && !fft->isLocalPeak(s, q)) continue; | 1248 if (peaksOnly && !fft->isLocalPeak(s, q)) continue; |
1249 | 1249 |
1250 if (!fft->isOverThreshold | 1250 if (!fft->isOverThreshold |
1251 (s, q, float(m_threshold * double(getFFTSize())/2.0))) { | 1251 (s, q, float(m_threshold * double(getFFTSize())/2.0))) { |
1252 continue; | 1252 continue; |
1253 } | 1253 } |
1254 | 1254 |
1255 double freq = binfreq; | 1255 double freq = binfreq; |
1256 | 1256 |
1257 if (s < int(fft->getWidth()) - 1) { | 1257 if (s < int(fft->getWidth()) - 1) { |
1258 | 1258 |
1259 fft->estimateStableFrequency(s, q, freq); | 1259 fft->estimateStableFrequency(s, q, freq); |
1260 | 1260 |
1261 if (!haveAdj || freq < adjFreqMin) adjFreqMin = freq; | 1261 if (!haveAdj || freq < adjFreqMin) adjFreqMin = freq; |
1262 if (!haveAdj || freq > adjFreqMax) adjFreqMax = freq; | 1262 if (!haveAdj || freq > adjFreqMax) adjFreqMax = freq; |
1263 | 1263 |
1264 haveAdj = true; | 1264 haveAdj = true; |
1265 } | 1265 } |
1266 } | 1266 } |
1267 } | 1267 } |
1268 | 1268 |
1269 if (!haveAdj) { | 1269 if (!haveAdj) { |
1270 adjFreqMin = adjFreqMax = 0.0; | 1270 adjFreqMin = adjFreqMax = 0.0; |
1271 } | 1271 } |
1272 | 1272 |
1273 return haveAdj; | 1273 return haveAdj; |
1274 } | 1274 } |
1275 | 1275 |
1276 bool | 1276 bool |
1277 SpectrogramLayer::getXYBinSourceRange(LayerGeometryProvider *v, int x, int y, | 1277 SpectrogramLayer::getXYBinSourceRange(LayerGeometryProvider *v, int x, int y, |
1278 double &min, double &max, | 1278 double &min, double &max, |
1279 double &phaseMin, double &phaseMax) const | 1279 double &phaseMin, double &phaseMax) const |
1280 { | 1280 { |
1281 if (!m_model || !m_model->isOK() || !m_model->isReady()) { | 1281 if (!m_model || !m_model->isOK() || !m_model->isReady()) { |
1282 return false; | 1282 return false; |
1283 } | 1283 } |
1284 | 1284 |
1285 double q0 = 0, q1 = 0; | 1285 double q0 = 0, q1 = 0; |
1286 if (!getYBinRange(v, y, q0, q1)) return false; | 1286 if (!getYBinRange(v, y, q0, q1)) return false; |
1287 | 1287 |
1322 value = fft->getMagnitudeAt(s, q) / (getFFTSize()/2.0); | 1322 value = fft->getMagnitudeAt(s, q) / (getFFTSize()/2.0); |
1323 if (!have || value < min) { min = value; } | 1323 if (!have || value < min) { min = value; } |
1324 if (!have || value > max) { max = value; } | 1324 if (!have || value > max) { max = value; } |
1325 | 1325 |
1326 have = true; | 1326 have = true; |
1327 } | 1327 } |
1328 } | 1328 } |
1329 } | 1329 } |
1330 | 1330 |
1331 if (have) { | 1331 if (have) { |
1332 rv = true; | 1332 rv = true; |
1333 } | 1333 } |
1334 } | 1334 } |
1335 | 1335 |
1336 return rv; | 1336 return rv; |
1337 } | 1337 } |
1338 | 1338 |
1339 void | 1339 void |
1340 SpectrogramLayer::recreateFFTModel() | 1340 SpectrogramLayer::recreateFFTModel() |
1341 { | 1341 { |
1342 #ifdef DEBUG_SPECTROGRAM | 1342 #ifdef DEBUG_SPECTROGRAM |
1343 cerr << "SpectrogramLayer::recreateFFTModel called" << endl; | 1343 cerr << "SpectrogramLayer::recreateFFTModel called" << endl; |
1468 if (m_colourScale != ColourScaleType::Phase) { | 1468 if (m_colourScale != ColourScaleType::Phase) { |
1469 cparams.gain = m_gain; | 1469 cparams.gain = m_gain; |
1470 cparams.threshold = m_threshold; | 1470 cparams.threshold = m_threshold; |
1471 } | 1471 } |
1472 | 1472 |
1473 float minValue = 0.0f; | 1473 double minValue = 0.0f; |
1474 float maxValue = 1.0f; | 1474 double maxValue = 1.0f; |
1475 | 1475 |
1476 if (m_normalizeVisibleArea && m_viewMags[viewId].isSet()) { | 1476 if (m_normalizeVisibleArea && m_viewMags[viewId].isSet()) { |
1477 minValue = m_viewMags[viewId].getMin(); | 1477 minValue = m_viewMags[viewId].getMin(); |
1478 maxValue = m_viewMags[viewId].getMax(); | 1478 maxValue = m_viewMags[viewId].getMax(); |
1479 } else if (m_colourScale == ColourScaleType::Linear && | 1479 } else if (m_colourScale == ColourScaleType::Linear && |
1489 } | 1489 } |
1490 | 1490 |
1491 cparams.minValue = minValue; | 1491 cparams.minValue = minValue; |
1492 cparams.maxValue = maxValue; | 1492 cparams.maxValue = maxValue; |
1493 | 1493 |
1494 m_lastRenderedMags[viewId] = MagnitudeRange(minValue, maxValue); | 1494 m_lastRenderedMags[viewId] = MagnitudeRange(float(minValue), |
1495 float(maxValue)); | |
1495 | 1496 |
1496 Colour3DPlotRenderer::Parameters params; | 1497 Colour3DPlotRenderer::Parameters params; |
1497 params.colourScale = ColourScale(cparams); | 1498 params.colourScale = ColourScale(cparams); |
1498 params.normalization = m_normalization; | 1499 params.normalization = m_normalization; |
1499 params.binDisplay = m_binDisplay; | 1500 params.binDisplay = m_binDisplay; |
1512 Preferences::getInstance()->getSpectrogramSmoothing(); | 1513 Preferences::getInstance()->getSpectrogramSmoothing(); |
1513 params.interpolate = | 1514 params.interpolate = |
1514 (smoothing == Preferences::SpectrogramInterpolated || | 1515 (smoothing == Preferences::SpectrogramInterpolated || |
1515 smoothing == Preferences::SpectrogramZeroPaddedAndInterpolated); | 1516 smoothing == Preferences::SpectrogramZeroPaddedAndInterpolated); |
1516 | 1517 |
1517 m_renderers[v->getId()] = new Colour3DPlotRenderer(sources, params); | 1518 m_renderers[viewId] = new Colour3DPlotRenderer(sources, params); |
1518 } | 1519 } |
1519 | 1520 |
1520 return m_renderers[v->getId()]; | 1521 return m_renderers[viewId]; |
1521 } | 1522 } |
1522 | 1523 |
1523 void | 1524 void |
1524 SpectrogramLayer::paintWithRenderer(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 1525 SpectrogramLayer::paintWithRenderer(LayerGeometryProvider *v, QPainter &paint, QRect rect) const |
1525 { | 1526 { |
1589 | 1590 |
1590 cerr << "SpectrogramLayer::paint(): rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl; | 1591 cerr << "SpectrogramLayer::paint(): rect is " << rect.x() << "," << rect.y() << " " << rect.width() << "x" << rect.height() << endl; |
1591 #endif | 1592 #endif |
1592 | 1593 |
1593 if (!m_model || !m_model->isOK() || !m_model->isReady()) { | 1594 if (!m_model || !m_model->isOK() || !m_model->isReady()) { |
1594 return; | 1595 return; |
1595 } | |
1596 | |
1597 if (isLayerDormant(v)) { | |
1598 SVDEBUG << "SpectrogramLayer::paint(): Layer is dormant, making it undormant again" << endl; | |
1599 } | 1596 } |
1600 | 1597 |
1601 paintWithRenderer(v, paint, rect); | 1598 paintWithRenderer(v, paint, rect); |
1602 | 1599 |
1603 illuminateLocalFeatures(v, paint); | 1600 illuminateLocalFeatures(v, paint); |
1648 | 1645 |
1649 double | 1646 double |
1650 SpectrogramLayer::getYForFrequency(const LayerGeometryProvider *v, double frequency) const | 1647 SpectrogramLayer::getYForFrequency(const LayerGeometryProvider *v, double frequency) const |
1651 { | 1648 { |
1652 return v->getYForFrequency(frequency, | 1649 return v->getYForFrequency(frequency, |
1653 getEffectiveMinFrequency(), | 1650 getEffectiveMinFrequency(), |
1654 getEffectiveMaxFrequency(), | 1651 getEffectiveMaxFrequency(), |
1655 m_binScale == BinScale::Log); | 1652 m_binScale == BinScale::Log); |
1656 } | 1653 } |
1657 | 1654 |
1658 double | 1655 double |
1659 SpectrogramLayer::getFrequencyForY(const LayerGeometryProvider *v, int y) const | 1656 SpectrogramLayer::getFrequencyForY(const LayerGeometryProvider *v, int y) const |
1660 { | 1657 { |
1661 return v->getFrequencyForY(y, | 1658 return v->getFrequencyForY(y, |
1662 getEffectiveMinFrequency(), | 1659 getEffectiveMinFrequency(), |
1663 getEffectiveMaxFrequency(), | 1660 getEffectiveMaxFrequency(), |
1664 m_binScale == BinScale::Log); | 1661 m_binScale == BinScale::Log); |
1665 } | 1662 } |
1666 | 1663 |
1667 int | 1664 int |
1668 SpectrogramLayer::getCompletion(LayerGeometryProvider *) const | 1665 SpectrogramLayer::getCompletion(LayerGeometryProvider *) const |
1669 { | 1666 { |
1749 } | 1746 } |
1750 | 1747 |
1751 bool | 1748 bool |
1752 SpectrogramLayer::snapToFeatureFrame(LayerGeometryProvider *, | 1749 SpectrogramLayer::snapToFeatureFrame(LayerGeometryProvider *, |
1753 sv_frame_t &frame, | 1750 sv_frame_t &frame, |
1754 int &resolution, | 1751 int &resolution, |
1755 SnapType snap) const | 1752 SnapType snap) const |
1756 { | 1753 { |
1757 resolution = getWindowIncrement(); | 1754 resolution = getWindowIncrement(); |
1758 sv_frame_t left = (frame / resolution) * resolution; | 1755 sv_frame_t left = (frame / resolution) * resolution; |
1759 sv_frame_t right = left + resolution; | 1756 sv_frame_t right = left + resolution; |
1760 | 1757 |
1761 switch (snap) { | 1758 switch (snap) { |
1762 case SnapLeft: frame = left; break; | 1759 case SnapLeft: frame = left; break; |
1763 case SnapRight: frame = right; break; | 1760 case SnapRight: frame = right; break; |
1764 case SnapNearest: | 1761 case SnapNearest: |
1765 case SnapNeighbouring: | 1762 case SnapNeighbouring: |
1766 if (frame - left > right - frame) frame = right; | 1763 if (frame - left > right - frame) frame = right; |
1767 else frame = left; | 1764 else frame = left; |
1768 break; | 1765 break; |
1769 } | 1766 } |
1770 | 1767 |
1771 return true; | 1768 return true; |
1772 } | 1769 } |
1773 | 1770 |
1919 RealTime rtMin, rtMax; | 1916 RealTime rtMin, rtMax; |
1920 | 1917 |
1921 bool haveValues = false; | 1918 bool haveValues = false; |
1922 | 1919 |
1923 if (!getXBinSourceRange(v, x, rtMin, rtMax)) { | 1920 if (!getXBinSourceRange(v, x, rtMin, rtMax)) { |
1924 return ""; | 1921 return ""; |
1925 } | 1922 } |
1926 if (getXYBinSourceRange(v, x, y, magMin, magMax, phaseMin, phaseMax)) { | 1923 if (getXYBinSourceRange(v, x, y, magMin, magMax, phaseMin, phaseMax)) { |
1927 haveValues = true; | 1924 haveValues = true; |
1928 } | 1925 } |
1929 | 1926 |
1930 QString adjFreqText = "", adjPitchText = ""; | 1927 QString adjFreqText = "", adjPitchText = ""; |
1931 | 1928 |
1932 if (m_binDisplay == BinDisplay::PeakFrequencies) { | 1929 if (m_binDisplay == BinDisplay::PeakFrequencies) { |
1933 | 1930 |
1934 if (!getAdjustedYBinSourceRange(v, x, y, freqMin, freqMax, | 1931 if (!getAdjustedYBinSourceRange(v, x, y, freqMin, freqMax, |
1935 adjFreqMin, adjFreqMax)) { | 1932 adjFreqMin, adjFreqMax)) { |
1936 return ""; | 1933 return ""; |
1937 } | 1934 } |
1938 | 1935 |
1939 if (adjFreqMin != adjFreqMax) { | 1936 if (adjFreqMin != adjFreqMax) { |
1940 adjFreqText = tr("Peak Frequency:\t%1 - %2 Hz\n") | 1937 adjFreqText = tr("Peak Frequency:\t%1 - %2 Hz\n") |
1941 .arg(adjFreqMin).arg(adjFreqMax); | 1938 .arg(adjFreqMin).arg(adjFreqMax); |
1942 } else { | 1939 } else { |
1943 adjFreqText = tr("Peak Frequency:\t%1 Hz\n") | 1940 adjFreqText = tr("Peak Frequency:\t%1 Hz\n") |
1944 .arg(adjFreqMin); | 1941 .arg(adjFreqMin); |
1945 } | 1942 } |
1946 | 1943 |
1947 QString pmin = Pitch::getPitchLabelForFrequency(adjFreqMin); | 1944 QString pmin = Pitch::getPitchLabelForFrequency(adjFreqMin); |
1948 QString pmax = Pitch::getPitchLabelForFrequency(adjFreqMax); | 1945 QString pmax = Pitch::getPitchLabelForFrequency(adjFreqMax); |
1949 | 1946 |
1950 if (pmin != pmax) { | 1947 if (pmin != pmax) { |
1951 adjPitchText = tr("Peak Pitch:\t%3 - %4\n").arg(pmin).arg(pmax); | 1948 adjPitchText = tr("Peak Pitch:\t%3 - %4\n").arg(pmin).arg(pmax); |
1952 } else { | 1949 } else { |
1953 adjPitchText = tr("Peak Pitch:\t%2\n").arg(pmin); | 1950 adjPitchText = tr("Peak Pitch:\t%2\n").arg(pmin); |
1954 } | 1951 } |
1955 | 1952 |
1956 } else { | 1953 } else { |
1957 | 1954 |
1958 if (!getYBinSourceRange(v, y, freqMin, freqMax)) return ""; | 1955 if (!getYBinSourceRange(v, y, freqMin, freqMax)) return ""; |
1959 } | 1956 } |
1960 | 1957 |
1961 QString text; | 1958 QString text; |
1962 | 1959 |
1963 if (rtMin != rtMax) { | 1960 if (rtMin != rtMax) { |
1964 text += tr("Time:\t%1 - %2\n") | 1961 text += tr("Time:\t%1 - %2\n") |
1965 .arg(rtMin.toText(true).c_str()) | 1962 .arg(rtMin.toText(true).c_str()) |
1966 .arg(rtMax.toText(true).c_str()); | 1963 .arg(rtMax.toText(true).c_str()); |
1967 } else { | 1964 } else { |
1968 text += tr("Time:\t%1\n") | 1965 text += tr("Time:\t%1\n") |
1969 .arg(rtMin.toText(true).c_str()); | 1966 .arg(rtMin.toText(true).c_str()); |
1970 } | 1967 } |
1971 | 1968 |
1972 if (freqMin != freqMax) { | 1969 if (freqMin != freqMax) { |
1973 text += tr("%1Bin Frequency:\t%2 - %3 Hz\n%4Bin Pitch:\t%5 - %6\n") | 1970 text += tr("%1Bin Frequency:\t%2 - %3 Hz\n%4Bin Pitch:\t%5 - %6\n") |
1974 .arg(adjFreqText) | 1971 .arg(adjFreqText) |
1975 .arg(freqMin) | 1972 .arg(freqMin) |
1976 .arg(freqMax) | 1973 .arg(freqMax) |
1977 .arg(adjPitchText) | 1974 .arg(adjPitchText) |
1978 .arg(Pitch::getPitchLabelForFrequency(freqMin)) | 1975 .arg(Pitch::getPitchLabelForFrequency(freqMin)) |
1979 .arg(Pitch::getPitchLabelForFrequency(freqMax)); | 1976 .arg(Pitch::getPitchLabelForFrequency(freqMax)); |
1980 } else { | 1977 } else { |
1981 text += tr("%1Bin Frequency:\t%2 Hz\n%3Bin Pitch:\t%4\n") | 1978 text += tr("%1Bin Frequency:\t%2 Hz\n%3Bin Pitch:\t%4\n") |
1982 .arg(adjFreqText) | 1979 .arg(adjFreqText) |
1983 .arg(freqMin) | 1980 .arg(freqMin) |
1984 .arg(adjPitchText) | 1981 .arg(adjPitchText) |
1985 .arg(Pitch::getPitchLabelForFrequency(freqMin)); | 1982 .arg(Pitch::getPitchLabelForFrequency(freqMin)); |
1986 } | 1983 } |
1987 | 1984 |
1988 if (haveValues) { | 1985 if (haveValues) { |
1989 double dbMin = AudioLevel::multiplier_to_dB(magMin); | 1986 double dbMin = AudioLevel::multiplier_to_dB(magMin); |
1990 double dbMax = AudioLevel::multiplier_to_dB(magMax); | 1987 double dbMax = AudioLevel::multiplier_to_dB(magMax); |
1991 QString dbMinString; | 1988 QString dbMinString; |
1992 QString dbMaxString; | 1989 QString dbMaxString; |
1993 if (dbMin == AudioLevel::DB_FLOOR) { | 1990 if (dbMin == AudioLevel::DB_FLOOR) { |
1994 dbMinString = Strings::minus_infinity; | 1991 dbMinString = Strings::minus_infinity; |
1995 } else { | 1992 } else { |
1996 dbMinString = QString("%1").arg(lrint(dbMin)); | 1993 dbMinString = QString("%1").arg(lrint(dbMin)); |
1997 } | 1994 } |
1998 if (dbMax == AudioLevel::DB_FLOOR) { | 1995 if (dbMax == AudioLevel::DB_FLOOR) { |
1999 dbMaxString = Strings::minus_infinity; | 1996 dbMaxString = Strings::minus_infinity; |
2000 } else { | 1997 } else { |
2001 dbMaxString = QString("%1").arg(lrint(dbMax)); | 1998 dbMaxString = QString("%1").arg(lrint(dbMax)); |
2002 } | 1999 } |
2003 if (lrint(dbMin) != lrint(dbMax)) { | 2000 if (lrint(dbMin) != lrint(dbMax)) { |
2004 text += tr("dB:\t%1 - %2").arg(dbMinString).arg(dbMaxString); | 2001 text += tr("dB:\t%1 - %2").arg(dbMinString).arg(dbMaxString); |
2005 } else { | 2002 } else { |
2006 text += tr("dB:\t%1").arg(dbMinString); | 2003 text += tr("dB:\t%1").arg(dbMinString); |
2007 } | 2004 } |
2008 if (phaseMin != phaseMax) { | 2005 if (phaseMin != phaseMax) { |
2009 text += tr("\nPhase:\t%1 - %2").arg(phaseMin).arg(phaseMax); | 2006 text += tr("\nPhase:\t%1 - %2").arg(phaseMin).arg(phaseMax); |
2010 } else { | 2007 } else { |
2011 text += tr("\nPhase:\t%1").arg(phaseMin); | 2008 text += tr("\nPhase:\t%1").arg(phaseMin); |
2012 } | 2009 } |
2013 } | 2010 } |
2014 | 2011 |
2015 return text; | 2012 return text; |
2016 } | 2013 } |
2017 | 2014 |
2032 | 2029 |
2033 int cw = 0; | 2030 int cw = 0; |
2034 if (detailed) cw = getColourScaleWidth(paint); | 2031 if (detailed) cw = getColourScaleWidth(paint); |
2035 | 2032 |
2036 int tw = paint.fontMetrics().width(QString("%1") | 2033 int tw = paint.fontMetrics().width(QString("%1") |
2037 .arg(m_maxFrequency > 0 ? | 2034 .arg(m_maxFrequency > 0 ? |
2038 m_maxFrequency - 1 : | 2035 m_maxFrequency - 1 : |
2039 m_model->getSampleRate() / 2)); | 2036 m_model->getSampleRate() / 2)); |
2040 | 2037 |
2041 int fw = paint.fontMetrics().width(tr("43Hz")); | 2038 int fw = paint.fontMetrics().width(tr("43Hz")); |
2042 if (tw < fw) tw = fw; | 2039 if (tw < fw) tw = fw; |
2043 | 2040 |
2044 int tickw = (m_binScale == BinScale::Log ? 10 : 4); | 2041 int tickw = (m_binScale == BinScale::Log ? 10 : 4); |
2049 void | 2046 void |
2050 SpectrogramLayer::paintVerticalScale(LayerGeometryProvider *v, bool detailed, | 2047 SpectrogramLayer::paintVerticalScale(LayerGeometryProvider *v, bool detailed, |
2051 QPainter &paint, QRect rect) const | 2048 QPainter &paint, QRect rect) const |
2052 { | 2049 { |
2053 if (!m_model || !m_model->isOK()) { | 2050 if (!m_model || !m_model->isOK()) { |
2054 return; | 2051 return; |
2055 } | 2052 } |
2056 | 2053 |
2057 Profiler profiler("SpectrogramLayer::paintVerticalScale"); | 2054 Profiler profiler("SpectrogramLayer::paintVerticalScale"); |
2058 | 2055 |
2059 //!!! cache this? | 2056 //!!! cache this? |
2071 | 2068 |
2072 int bins = getFFTSize() / 2; | 2069 int bins = getFFTSize() / 2; |
2073 sv_samplerate_t sr = m_model->getSampleRate(); | 2070 sv_samplerate_t sr = m_model->getSampleRate(); |
2074 | 2071 |
2075 if (m_maxFrequency > 0) { | 2072 if (m_maxFrequency > 0) { |
2076 bins = int((double(m_maxFrequency) * getFFTSize()) / sr + 0.1); | 2073 bins = int((double(m_maxFrequency) * getFFTSize()) / sr + 0.1); |
2077 if (bins > getFFTSize() / 2) bins = getFFTSize() / 2; | 2074 if (bins > getFFTSize() / 2) bins = getFFTSize() / 2; |
2078 } | 2075 } |
2079 | 2076 |
2080 int cw = 0; | 2077 int cw = 0; |
2081 if (detailed) cw = getColourScaleWidth(paint); | 2078 if (detailed) cw = getColourScaleWidth(paint); |
2082 | 2079 |
2087 | 2084 |
2088 int bin = -1; | 2085 int bin = -1; |
2089 | 2086 |
2090 for (int y = 0; y < v->getPaintHeight(); ++y) { | 2087 for (int y = 0; y < v->getPaintHeight(); ++y) { |
2091 | 2088 |
2092 double q0, q1; | 2089 double q0, q1; |
2093 if (!getYBinRange(v, v->getPaintHeight() - y, q0, q1)) continue; | 2090 if (!getYBinRange(v, v->getPaintHeight() - y, q0, q1)) continue; |
2094 | 2091 |
2095 int vy; | 2092 int vy; |
2096 | 2093 |
2097 if (int(q0) > bin) { | 2094 if (int(q0) > bin) { |
2098 vy = y; | 2095 vy = y; |
2099 bin = int(q0); | 2096 bin = int(q0); |
2100 } else { | 2097 } else { |
2101 continue; | 2098 continue; |
2102 } | 2099 } |
2103 | 2100 |
2104 int freq = int((sr * bin) / getFFTSize()); | 2101 int freq = int((sr * bin) / getFFTSize()); |
2105 | 2102 |
2106 if (py >= 0 && (vy - py) < textHeight - 1) { | 2103 if (py >= 0 && (vy - py) < textHeight - 1) { |
2107 if (m_binScale == BinScale::Linear) { | 2104 if (m_binScale == BinScale::Linear) { |
2108 paint.drawLine(w - tickw, h - vy, w, h - vy); | 2105 paint.drawLine(w - tickw, h - vy, w, h - vy); |
2109 } | 2106 } |
2110 continue; | 2107 continue; |
2111 } | 2108 } |
2112 | 2109 |
2113 QString text = QString("%1").arg(freq); | 2110 QString text = QString("%1").arg(freq); |
2114 if (bin == 1) text = tr("%1Hz").arg(freq); // bin 0 is DC | 2111 if (bin == 1) text = tr("%1Hz").arg(freq); // bin 0 is DC |
2115 paint.drawLine(cw + 7, h - vy, w - pkw - 1, h - vy); | 2112 paint.drawLine(cw + 7, h - vy, w - pkw - 1, h - vy); |
2116 | 2113 |
2117 if (h - vy - textHeight >= -2) { | 2114 if (h - vy - textHeight >= -2) { |
2118 int tx = w - 3 - paint.fontMetrics().width(text) - max(tickw, pkw); | 2115 int tx = w - 3 - paint.fontMetrics().width(text) - max(tickw, pkw); |
2119 paint.drawText(tx, h - vy + toff, text); | 2116 paint.drawText(tx, h - vy + toff, text); |
2120 } | 2117 } |
2121 | 2118 |
2122 py = vy; | 2119 py = vy; |
2123 } | 2120 } |
2124 | 2121 |
2125 if (m_binScale == BinScale::Log) { | 2122 if (m_binScale == BinScale::Log) { |
2126 | 2123 |
2127 // piano keyboard | 2124 // piano keyboard |
2153 int cbw = paint.fontMetrics().width("dB"); | 2150 int cbw = paint.fontMetrics().width("dB"); |
2154 | 2151 |
2155 int topLines = 2; | 2152 int topLines = 2; |
2156 | 2153 |
2157 int ch = h - textHeight * (topLines + 1) - 8; | 2154 int ch = h - textHeight * (topLines + 1) - 8; |
2158 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1); | 2155 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1); |
2159 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1); | 2156 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1); |
2160 | 2157 |
2161 QString top, bottom; | 2158 QString top, bottom; |
2162 double min = m_viewMags[v->getId()].getMin(); | 2159 double min = m_viewMags[v->getId()].getMin(); |
2163 double max = m_viewMags[v->getId()].getMax(); | 2160 double max = m_viewMags[v->getId()].getMax(); |
2481 QString indent, QString extraAttributes) const | 2478 QString indent, QString extraAttributes) const |
2482 { | 2479 { |
2483 QString s; | 2480 QString s; |
2484 | 2481 |
2485 s += QString("channel=\"%1\" " | 2482 s += QString("channel=\"%1\" " |
2486 "windowSize=\"%2\" " | 2483 "windowSize=\"%2\" " |
2487 "windowHopLevel=\"%3\" " | 2484 "windowHopLevel=\"%3\" " |
2488 "gain=\"%4\" " | 2485 "gain=\"%4\" " |
2489 "threshold=\"%5\" ") | 2486 "threshold=\"%5\" ") |
2490 .arg(m_channel) | 2487 .arg(m_channel) |
2491 .arg(m_windowSize) | 2488 .arg(m_windowSize) |
2492 .arg(m_windowHopLevel) | 2489 .arg(m_windowHopLevel) |
2493 .arg(m_gain) | 2490 .arg(m_gain) |
2494 .arg(m_threshold); | 2491 .arg(m_threshold); |
2495 | 2492 |
2496 s += QString("minFrequency=\"%1\" " | 2493 s += QString("minFrequency=\"%1\" " |
2497 "maxFrequency=\"%2\" " | 2494 "maxFrequency=\"%2\" " |
2498 "colourScale=\"%3\" " | 2495 "colourScale=\"%3\" " |
2499 "colourScheme=\"%4\" " | 2496 "colourScheme=\"%4\" " |
2500 "colourRotation=\"%5\" " | 2497 "colourRotation=\"%5\" " |
2501 "frequencyScale=\"%6\" " | 2498 "frequencyScale=\"%6\" " |
2502 "binDisplay=\"%7\" ") | 2499 "binDisplay=\"%7\" ") |
2503 .arg(m_minFrequency) | 2500 .arg(m_minFrequency) |
2504 .arg(m_maxFrequency) | 2501 .arg(m_maxFrequency) |
2505 .arg(convertFromColourScale(m_colourScale, m_colourScaleMultiple)) | 2502 .arg(convertFromColourScale(m_colourScale, m_colourScaleMultiple)) |
2506 .arg(m_colourMap) | 2503 .arg(m_colourMap) |
2507 .arg(m_colourRotation) | 2504 .arg(m_colourRotation) |
2508 .arg(int(m_binScale)) | 2505 .arg(int(m_binScale)) |
2509 .arg(int(m_binDisplay)); | 2506 .arg(int(m_binDisplay)); |
2510 | 2507 |
2511 // New-style normalization attributes, allowing for more types of | 2508 // New-style normalization attributes, allowing for more types of |
2512 // normalization in future: write out the column normalization | 2509 // normalization in future: write out the column normalization |
2513 // type separately, and then whether we are normalizing visible | 2510 // type separately, and then whether we are normalizing visible |
2514 // area as well afterwards | 2511 // area as well afterwards |
2522 // it (Tony v1.0) has a totally different scale factor for | 2519 // it (Tony v1.0) has a totally different scale factor for |
2523 // it. We'll just have to accept that session files from Tony | 2520 // it. We'll just have to accept that session files from Tony |
2524 // v2.0+ will look odd in Tony v1.0 | 2521 // v2.0+ will look odd in Tony v1.0 |
2525 | 2522 |
2526 s += QString("normalizeColumns=\"%1\" ") | 2523 s += QString("normalizeColumns=\"%1\" ") |
2527 .arg(m_normalization == ColumnNormalization::Max1 ? "true" : "false"); | 2524 .arg(m_normalization == ColumnNormalization::Max1 ? "true" : "false"); |
2528 | 2525 |
2529 // And this applies to both old- and new-style attributes | 2526 // And this applies to both old- and new-style attributes |
2530 | 2527 |
2531 s += QString("normalizeVisibleArea=\"%1\" ") | 2528 s += QString("normalizeVisibleArea=\"%1\" ") |
2532 .arg(m_normalizeVisibleArea ? "true" : "false"); | 2529 .arg(m_normalizeVisibleArea ? "true" : "false"); |
2589 | 2586 |
2590 int colourRotation = attributes.value("colourRotation").toInt(&ok); | 2587 int colourRotation = attributes.value("colourRotation").toInt(&ok); |
2591 if (ok) setColourRotation(colourRotation); | 2588 if (ok) setColourRotation(colourRotation); |
2592 | 2589 |
2593 BinScale binScale = (BinScale) | 2590 BinScale binScale = (BinScale) |
2594 attributes.value("frequencyScale").toInt(&ok); | 2591 attributes.value("frequencyScale").toInt(&ok); |
2595 if (ok) setBinScale(binScale); | 2592 if (ok) setBinScale(binScale); |
2596 | 2593 |
2597 BinDisplay binDisplay = (BinDisplay) | 2594 BinDisplay binDisplay = (BinDisplay) |
2598 attributes.value("binDisplay").toInt(&ok); | 2595 attributes.value("binDisplay").toInt(&ok); |
2599 if (ok) setBinDisplay(binDisplay); | 2596 if (ok) setBinDisplay(binDisplay); |
2600 | 2597 |
2601 bool haveNewStyleNormalization = false; | 2598 bool haveNewStyleNormalization = false; |
2602 | 2599 |
2603 QString columnNormalization = attributes.value("columnNormalization"); | 2600 QString columnNormalization = attributes.value("columnNormalization"); |