comparison layer/WaveformLayer.cpp @ 374:64e84e5efb76 spectrogram-cache-rejig

* Merge from trunk
author Chris Cannam
date Wed, 27 Feb 2008 11:59:42 +0000
parents 1f67b110c1a3
children
comparison
equal deleted inserted replaced
332:6440e280122e 374:64e84e5efb76
104 if (name == "Scale") return tr("Scale"); 104 if (name == "Scale") return tr("Scale");
105 if (name == "Gain") return tr("Gain"); 105 if (name == "Gain") return tr("Gain");
106 if (name == "Normalize Visible Area") return tr("Normalize Visible Area"); 106 if (name == "Normalize Visible Area") return tr("Normalize Visible Area");
107 if (name == "Channels") return tr("Channels"); 107 if (name == "Channels") return tr("Channels");
108 return SingleColourLayer::getPropertyLabel(name); 108 return SingleColourLayer::getPropertyLabel(name);
109 }
110
111 QString
112 WaveformLayer::getPropertyIconName(const PropertyName &name) const
113 {
114 if (name == "Normalize Visible Area") return "normalise";
115 return "";
109 } 116 }
110 117
111 Layer::PropertyType 118 Layer::PropertyType
112 WaveformLayer::getPropertyType(const PropertyName &name) const 119 WaveformLayer::getPropertyType(const PropertyName &name) const
113 { 120 {
387 } 394 }
388 395
389 static float meterdbs[] = { -40, -30, -20, -15, -10, 396 static float meterdbs[] = { -40, -30, -20, -15, -10,
390 -5, -3, -2, -1, -0.5, 0 }; 397 -5, -3, -2, -1, -0.5, 0 };
391 398
399 bool
400 WaveformLayer::getSourceFramesForX(View *v, int x, size_t modelZoomLevel,
401 size_t &f0, size_t &f1) const
402 {
403 long viewFrame = v->getFrameForX(x);
404 if (viewFrame < 0) {
405 f0 = 0;
406 f1 = 0;
407 return false;
408 }
409
410 f0 = viewFrame;
411
412 f0 = f0 / modelZoomLevel;
413 f0 = f0 * modelZoomLevel;
414
415 viewFrame = v->getFrameForX(x + 1);
416
417 f1 = viewFrame;
418 f1 = f1 / modelZoomLevel;
419 f1 = f1 * modelZoomLevel;
420
421 return (f0 < m_model->getEndFrame());
422 }
423
424 float
425 WaveformLayer::getNormalizeGain(View *v, int channel) const
426 {
427 long startFrame = v->getStartFrame();
428 long endFrame = v->getEndFrame();
429
430 // Although a long for purposes of comparison against the view
431 // start and end frames, these are known to be non-negative
432 long modelStart = long(m_model->getStartFrame());
433 long modelEnd = long(m_model->getEndFrame());
434
435 size_t rangeStart, rangeEnd;
436
437 if (startFrame < modelStart) rangeStart = modelStart;
438 else rangeStart = startFrame;
439
440 if (endFrame < 0) rangeEnd = 0;
441 else if (endFrame > modelEnd) rangeEnd = modelEnd;
442 else rangeEnd = endFrame;
443
444 if (rangeEnd < rangeStart) rangeEnd = rangeStart;
445
446 RangeSummarisableTimeValueModel::Range range =
447 m_model->getSummary(channel, rangeStart, rangeEnd - rangeStart);
448
449 size_t minChannel = 0, maxChannel = 0;
450 bool mergingChannels = false, mixingChannels = false;
451
452 getChannelArrangement(minChannel, maxChannel,
453 mergingChannels, mixingChannels);
454
455 if (mergingChannels || mixingChannels) {
456 RangeSummarisableTimeValueModel::Range otherRange =
457 m_model->getSummary(1, rangeStart, rangeEnd - rangeStart);
458 range.max = std::max(range.max, otherRange.max);
459 range.min = std::min(range.min, otherRange.min);
460 range.absmean = std::min(range.absmean, otherRange.absmean);
461 }
462
463 return 1.0 / std::max(fabsf(range.max), fabsf(range.min));
464 }
465
392 void 466 void
393 WaveformLayer::paint(View *v, QPainter &viewPainter, QRect rect) const 467 WaveformLayer::paint(View *v, QPainter &viewPainter, QRect rect) const
394 { 468 {
395 if (!m_model || !m_model->isOK()) { 469 if (!m_model || !m_model->isOK()) {
396 return; 470 return;
397 } 471 }
398 472
399 long startFrame = v->getStartFrame();
400 long endFrame = v->getEndFrame();
401 int zoomLevel = v->getZoomLevel(); 473 int zoomLevel = v->getZoomLevel();
402 474
403 #ifdef DEBUG_WAVEFORM_PAINT 475 #ifdef DEBUG_WAVEFORM_PAINT
404 Profiler profiler("WaveformLayer::paint", true); 476 Profiler profiler("WaveformLayer::paint", true);
405 std::cerr << "WaveformLayer::paint (" << rect.x() << "," << rect.y() 477 std::cerr << "WaveformLayer::paint (" << rect.x() << "," << rect.y()
469 y1 = rect.bottom(); 541 y1 = rect.bottom();
470 542
471 if (x0 > 0) --x0; 543 if (x0 > 0) --x0;
472 if (x1 < v->width()) ++x1; 544 if (x1 < v->width()) ++x1;
473 545
474 long frame0 = v->getFrameForX(x0); 546 // Our zoom level may differ from that at which the underlying
475 long frame1 = v->getFrameForX(x1 + 1); 547 // model has its blocks.
476 548
549 // Each pixel within our visible range must always draw from
550 // exactly the same set of underlying audio frames, no matter what
551 // the range being drawn is. And that set of underlying frames
552 // must remain the same when we scroll one or more pixels left or
553 // right.
554
555 size_t modelZoomLevel = m_model->getSummaryBlockSize(zoomLevel);
556
557 size_t frame0;
558 size_t frame1;
559 size_t spare;
560
561 getSourceFramesForX(v, x0, modelZoomLevel, frame0, spare);
562 getSourceFramesForX(v, x1, modelZoomLevel, spare, frame1);
563
477 #ifdef DEBUG_WAVEFORM_PAINT 564 #ifdef DEBUG_WAVEFORM_PAINT
478 std::cerr << "Painting waveform from " << frame0 << " to " << frame1 << " (" << (x1-x0+1) << " pixels at zoom " << zoomLevel << ")" << std::endl; 565 std::cerr << "Painting waveform from " << frame0 << " to " << frame1 << " (" << (x1-x0+1) << " pixels at zoom " << zoomLevel << " and model zoom " << modelZoomLevel << ")" << std::endl;
479 #endif 566 #endif
480 567
481 RangeSummarisableTimeValueModel::RangeBlock *ranges = 568 RangeSummarisableTimeValueModel::RangeBlock *ranges =
482 new RangeSummarisableTimeValueModel::RangeBlock; 569 new RangeSummarisableTimeValueModel::RangeBlock;
483 570
498 585
499 while (m_effectiveGains.size() <= maxChannel) { 586 while (m_effectiveGains.size() <= maxChannel) {
500 m_effectiveGains.push_back(m_gain); 587 m_effectiveGains.push_back(m_gain);
501 } 588 }
502 589
503 // Although a long for purposes of comparison against the view
504 // start and end frames, these are known to be non-negative
505 long modelStart = long(m_model->getStartFrame());
506 long modelEnd = long(m_model->getEndFrame());
507
508 #ifdef DEBUG_WAVEFORM_PAINT
509 std::cerr << "Model start = " << modelStart << ", end = " << modelEnd << std::endl;
510 #endif
511
512 for (size_t ch = minChannel; ch <= maxChannel; ++ch) { 590 for (size_t ch = minChannel; ch <= maxChannel; ++ch) {
513 591
514 int prevRangeBottom = -1, prevRangeTop = -1; 592 int prevRangeBottom = -1, prevRangeTop = -1;
515 QColor prevRangeBottomColour = baseColour, prevRangeTopColour = baseColour; 593 QColor prevRangeBottomColour = baseColour, prevRangeTopColour = baseColour;
516 size_t rangeStart, rangeEnd;
517 594
518 m_effectiveGains[ch] = m_gain; 595 m_effectiveGains[ch] = m_gain;
519 596
520 if (m_autoNormalize) { 597 if (m_autoNormalize) {
521 598 m_effectiveGains[ch] = getNormalizeGain(v, ch);
522 if (startFrame < modelStart) rangeStart = modelStart;
523 else rangeStart = startFrame;
524
525 if (endFrame < 0) rangeEnd = 0;
526 else if (endFrame > modelEnd) rangeEnd = modelEnd;
527 else rangeEnd = endFrame;
528
529 if (rangeEnd < rangeStart) rangeEnd = rangeStart;
530
531 RangeSummarisableTimeValueModel::Range range =
532 m_model->getSummary(ch, rangeStart, rangeEnd - rangeStart);
533 if (mergingChannels || mixingChannels) {
534 RangeSummarisableTimeValueModel::Range otherRange =
535 m_model->getSummary(1, rangeStart, rangeEnd - rangeStart);
536 range.max = std::max(range.max, otherRange.max);
537 range.min = std::min(range.min, otherRange.min);
538 range.absmean = std::min(range.absmean, otherRange.absmean);
539 }
540 m_effectiveGains[ch] = 1.0 / std::max(fabsf(range.max),
541 fabsf(range.min));
542 } 599 }
543 600
544 float gain = m_effectiveGains[ch]; 601 float gain = m_effectiveGains[ch];
545 602
546 int m = (h / channels) / 2; 603 int m = (h / channels) / 2;
604 if (ny != y) { 661 if (ny != y) {
605 paint->drawLine(x0, ny, x1, ny); 662 paint->drawLine(x0, ny, x1, ny);
606 } 663 }
607 } 664 }
608 } 665 }
609 666
610 if (frame1 < modelStart) continue; 667 m_model->getSummaries(ch, frame0, frame1 - frame0,
611 668 *ranges, modelZoomLevel);
612 size_t modelZoomLevel = zoomLevel; 669
613 670 #ifdef DEBUG_WAVEFORM_PAINT
614 if (frame0 < modelStart) rangeStart = modelStart; 671 std::cerr << ranges->size() << " ranges from " << frame0 << " to " << frame1 << std::endl;
615 else rangeStart = frame0; 672 #endif
616 673
617 if (frame1 < 0) rangeEnd = 0;
618 else if (frame1 > modelEnd) rangeEnd = modelEnd;
619 else rangeEnd = frame1;
620
621 if (rangeEnd < rangeStart) rangeEnd = rangeStart;
622
623 m_model->getSummaries
624 (ch, rangeStart, rangeEnd - rangeStart, *ranges, modelZoomLevel);
625
626 // std::cerr << ranges->size() << " ranges" << std::endl;
627
628 if (mergingChannels || mixingChannels) { 674 if (mergingChannels || mixingChannels) {
629 if (m_model->getChannelCount() > 1) { 675 if (m_model->getChannelCount() > 1) {
630 if (!otherChannelRanges) { 676 if (!otherChannelRanges) {
631 otherChannelRanges = 677 otherChannelRanges =
632 new RangeSummarisableTimeValueModel::RangeBlock; 678 new RangeSummarisableTimeValueModel::RangeBlock;
633 } 679 }
634 m_model->getSummaries 680 m_model->getSummaries
635 (1, rangeStart, rangeEnd - rangeStart, *otherChannelRanges, 681 (1, frame0, frame1 - frame0, *otherChannelRanges,
636 modelZoomLevel); 682 modelZoomLevel);
637 } else { 683 } else {
638 if (otherChannelRanges != ranges) delete otherChannelRanges; 684 if (otherChannelRanges != ranges) delete otherChannelRanges;
639 otherChannelRanges = ranges; 685 otherChannelRanges = ranges;
640 } 686 }
641 } 687 }
642 688
643 for (int x = x0; x <= x1; ++x) { 689 for (int x = x0; x <= x1; ++x) {
644 690
645 range = RangeSummarisableTimeValueModel::Range(); 691 range = RangeSummarisableTimeValueModel::Range();
646 size_t index = x - x0; 692
647 size_t maxIndex = index; 693 size_t f0, f1;
648 694 if (!getSourceFramesForX(v, x, modelZoomLevel, f0, f1)) continue;
649 if (frame0 < modelStart) { 695 f1 = f1 - 1;
650 if (index < size_t((modelStart - frame0) / zoomLevel)) { 696
651 continue; 697 if (f0 < frame0) {
652 } else { 698 std::cerr << "ERROR: WaveformLayer::paint: pixel " << x << " has f0 = " << f0 << " which is less than range frame0 " << frame0 << " for x0 = " << x0 << std::endl;
653 index -= ((modelStart - frame0) / zoomLevel); 699 continue;
654 maxIndex = index;
655 }
656 } 700 }
657 701
658 if (int(modelZoomLevel) != zoomLevel) { 702 size_t i0 = (f0 - frame0) / modelZoomLevel;
659 703 size_t i1 = (f1 - frame0) / modelZoomLevel;
660 index = size_t((double(index) * zoomLevel) / modelZoomLevel); 704
661 705 #ifdef DEBUG_WAVEFORM_PAINT
662 if (int(modelZoomLevel) < zoomLevel) { 706 std::cerr << "WaveformLayer::paint: pixel " << x << ": i0 " << i0 << " (f " << f0 << "), i1 " << i1 << " (f " << f1 << ")" << std::endl;
663 // Peaks may be missed! The model should avoid 707 #endif
664 // this by rounding zoom levels up rather than 708
665 // down, but we'd better cope in case it doesn't 709 if (i1 > i0 + 1) {
666 maxIndex = index; 710 std::cerr << "WaveformLayer::paint: ERROR: i1 " << i1 << " > i0 " << i0 << " plus one (zoom = " << zoomLevel << ", model zoom = " << modelZoomLevel << ")" << std::endl;
667 } else { 711 }
668 maxIndex = size_t((double(index + 1) * zoomLevel) 712
669 / modelZoomLevel) - 1; 713 if (ranges && i0 < ranges->size()) {
670 } 714
671 } 715 range = (*ranges)[i0];
672 716
673 if (ranges && index < ranges->size()) { 717 if (i1 > i0 && i1 < ranges->size()) {
674 718 range.max = std::max(range.max, (*ranges)[i1].max);
675 range = (*ranges)[index]; 719 range.min = std::min(range.min, (*ranges)[i1].min);
676 720 range.absmean = (range.absmean + (*ranges)[i1].absmean) / 2;
677 if (maxIndex > index && maxIndex < ranges->size()) {
678 range.max = std::max(range.max, (*ranges)[maxIndex].max);
679 range.min = std::min(range.min, (*ranges)[maxIndex].min);
680 range.absmean = (range.absmean +
681 (*ranges)[maxIndex].absmean) / 2;
682 } 721 }
683 722
684 } else { 723 } else {
685 continue; 724 continue;
686 } 725 }
687 726
688 int rangeBottom = 0, rangeTop = 0, meanBottom = 0, meanTop = 0; 727 int rangeBottom = 0, rangeTop = 0, meanBottom = 0, meanTop = 0;
689 728
690 if (mergingChannels) { 729 if (mergingChannels) {
691 730
692 if (otherChannelRanges && index < otherChannelRanges->size()) { 731 if (otherChannelRanges && i0 < otherChannelRanges->size()) {
693 732
694 range.max = fabsf(range.max); 733 range.max = fabsf(range.max);
695 range.min = -fabsf((*otherChannelRanges)[index].max); 734 range.min = -fabsf((*otherChannelRanges)[i0].max);
696 range.absmean = (range.absmean + 735 range.absmean = (range.absmean +
697 (*otherChannelRanges)[index].absmean) / 2; 736 (*otherChannelRanges)[i0].absmean) / 2;
698 737
699 if (maxIndex > index && maxIndex < otherChannelRanges->size()) { 738 if (i1 > i0 && i1 < otherChannelRanges->size()) {
700 // let's not concern ourselves about the mean 739 // let's not concern ourselves about the mean
701 range.min = std::min 740 range.min = std::min
702 (range.min, 741 (range.min,
703 -fabsf((*otherChannelRanges)[maxIndex].max)); 742 -fabsf((*otherChannelRanges)[i1].max));
704 } 743 }
705 } 744 }
706 745
707 } else if (mixingChannels) { 746 } else if (mixingChannels) {
708 747
709 if (otherChannelRanges && index < otherChannelRanges->size()) { 748 if (otherChannelRanges && i0 < otherChannelRanges->size()) {
710 749
711 range.max = (range.max + (*otherChannelRanges)[index].max) / 2; 750 range.max = (range.max + (*otherChannelRanges)[i0].max) / 2;
712 range.min = (range.min + (*otherChannelRanges)[index].min) / 2; 751 range.min = (range.min + (*otherChannelRanges)[i0].min) / 2;
713 range.absmean = (range.absmean + (*otherChannelRanges)[index].absmean) / 2; 752 range.absmean = (range.absmean + (*otherChannelRanges)[i0].absmean) / 2;
714 } 753 }
715 } 754 }
716 755
717 int greyLevels = 1; 756 int greyLevels = 1;
718 if (m_greyscale && (m_scale == LinearScale)) greyLevels = 4; 757 if (m_greyscale && (m_scale == LinearScale)) greyLevels = 4;
881 { 920 {
882 int x = pos.x(); 921 int x = pos.x();
883 922
884 if (!m_model || !m_model->isOK()) return ""; 923 if (!m_model || !m_model->isOK()) return "";
885 924
886 long f0 = v->getFrameForX(x); 925 int zoomLevel = v->getZoomLevel();
887 long f1 = v->getFrameForX(x + 1); 926
888 927 size_t modelZoomLevel = m_model->getSummaryBlockSize(zoomLevel);
889 if (f0 < 0) f0 = 0; 928
890 if (f1 <= f0) return ""; 929 size_t f0, f1;
930 if (!getSourceFramesForX(v, x, modelZoomLevel, f0, f1)) return "";
891 931
892 QString text; 932 QString text;
893 933
894 RealTime rt0 = RealTime::frame2RealTime(f0, m_model->getSampleRate()); 934 RealTime rt0 = RealTime::frame2RealTime(f0, m_model->getSampleRate());
895 RealTime rt1 = RealTime::frame2RealTime(f1, m_model->getSampleRate()); 935 RealTime rt1 = RealTime::frame2RealTime(f1, m_model->getSampleRate());