comparison layer/WaveformLayer.cpp @ 25:dcdb21b62dbb

* Refactor sparse models. Previously the 1D and time-value models duplicated a lot of code; now there is a base class (SparseModel) templated on the stored point type, and the subclasses define point types with the necessary characteristics. * Add NoteModel, a new SparseModel subclass. * Reorganise local feature description display. Instead of asking the layer to draw its own, just query it for a textual description and draw that in Pane. Greatly simplifies this part of the layer code. * Add local feature descriptions to colour 3D plot and waveform layers. * Add pitch in MIDI-pitch-and-cents to spectrogram layer. * Give AudioGenerator its own mutex to shorten lock times in CallbackPlaySource. * Minor adjustments to layers menu &c
author Chris Cannam
date Thu, 02 Feb 2006 16:10:19 +0000
parents 01849cd277e6
children 38fe0ea9e46e
comparison
equal deleted inserted replaced
24:6b794a2af3d9 25:dcdb21b62dbb
397 x0 = rect.left(); 397 x0 = rect.left();
398 x1 = rect.right(); 398 x1 = rect.right();
399 y0 = rect.top(); 399 y0 = rect.top();
400 y1 = rect.bottom(); 400 y1 = rect.bottom();
401 401
402 long frame0 = startFrame + x0 * zoomLevel; 402 long frame0 = getFrameForX(x0);
403 long frame1 = startFrame + (x1 + 1) * zoomLevel; 403 long frame1 = getFrameForX(x1 + 1);
404 404
405 #ifdef DEBUG_WAVEFORM_PAINT 405 #ifdef DEBUG_WAVEFORM_PAINT
406 std::cerr << "Painting waveform from " << frame0 << " to " << frame1 << " (" << (x1-x0+1) << " pixels at zoom " << zoomLevel << ")" << std::endl; 406 std::cerr << "Painting waveform from " << frame0 << " to " << frame1 << " (" << (x1-x0+1) << " pixels at zoom " << zoomLevel << ")" << std::endl;
407 #endif 407 #endif
408 408
642 } 642 }
643 paint->end(); 643 paint->end();
644 delete paint; 644 delete paint;
645 viewPainter.drawPixmap(rect, *m_cache, rect); 645 viewPainter.drawPixmap(rect, *m_cache, rect);
646 } 646 }
647 }
648
649 QString
650 WaveformLayer::getFeatureDescription(QPoint &pos) const
651 {
652 int x = pos.x();
653
654 if (!m_model || !m_model->isOK()) return "";
655
656 long f0 = getFrameForX(x);
657 long f1 = getFrameForX(x + 1);
658
659 if (f0 < 0) f0 = 0;
660 if (f1 <= f0) return "";
661
662 QString text;
663
664 RealTime rt0 = RealTime::frame2RealTime(f0, m_model->getSampleRate());
665 RealTime rt1 = RealTime::frame2RealTime(f1, m_model->getSampleRate());
666
667 if (f1 != f0 + 1 && (rt0.sec != rt1.sec || rt0.msec() != rt1.msec())) {
668 text += tr("Time:\t%1 - %2")
669 .arg(rt0.toText(true).c_str())
670 .arg(rt1.toText(true).c_str());
671 } else {
672 text += tr("Time:\t%1")
673 .arg(rt0.toText(true).c_str());
674 }
675
676 size_t channels = 0, minChannel = 0, maxChannel = 0;
677 bool mergingChannels = false;
678
679 channels = getChannelArrangement(minChannel, maxChannel, mergingChannels);
680 if (channels == 0) return "";
681
682 for (size_t ch = minChannel; ch <= maxChannel; ++ch) {
683
684 size_t blockSize = m_view->getZoomLevel();
685 RangeSummarisableTimeValueModel::RangeBlock ranges =
686 m_model->getRanges(ch, f0, f1, blockSize);
687
688 if (ranges.empty()) continue;
689
690 RangeSummarisableTimeValueModel::Range range = ranges[0];
691
692 QString label = tr("Level:");
693 if (minChannel != maxChannel) {
694 if (ch == 0) label = tr("Left:");
695 else if (ch == 1) label = tr("Right:");
696 else label = tr("Channel %1").arg(ch + 1);
697 }
698
699 int min = int(range.min * 1000);
700 int max = int(range.max * 1000);
701 int db = int(AudioLevel::multiplier_to_dB(std::max(fabsf(range.min),
702 fabsf(range.max)))
703 * 100);
704
705 if (min != max) {
706 text += tr("\n%1\t%2 - %3 (%4 dB peak)")
707 .arg(label).arg(float(min)/1000).arg(float(max)/1000).arg(float(db)/100);
708 } else {
709 text += tr("\n%1\t%2 (%3 dB peak)")
710 .arg(label).arg(float(min)/1000).arg(float(db)/100);
711 }
712 }
713
714 return text;
647 } 715 }
648 716
649 int 717 int
650 WaveformLayer::getVerticalScaleWidth(QPainter &paint) const 718 WaveformLayer::getVerticalScaleWidth(QPainter &paint) const
651 { 719 {