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");