Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 110:f262aa8973e3
* Update SpectrogramLayer to use new FFTDataServer
author | Chris Cannam |
---|---|
date | Tue, 27 Jun 2006 19:18:42 +0000 |
parents | 12340cb6e6cb |
children | ab55c427e068 |
comparison
equal
deleted
inserted
replaced
109:12340cb6e6cb | 110:f262aa8973e3 |
---|---|
18 #include "base/View.h" | 18 #include "base/View.h" |
19 #include "base/Profiler.h" | 19 #include "base/Profiler.h" |
20 #include "base/AudioLevel.h" | 20 #include "base/AudioLevel.h" |
21 #include "base/Window.h" | 21 #include "base/Window.h" |
22 #include "base/Pitch.h" | 22 #include "base/Pitch.h" |
23 #include "fileio/FFTFileCache.h" | 23 #include "fileio/FFTDataServer.h" |
24 | 24 |
25 #include <QPainter> | 25 #include <QPainter> |
26 #include <QImage> | 26 #include <QImage> |
27 #include <QPixmap> | 27 #include <QPixmap> |
28 #include <QRect> | 28 #include <QRect> |
53 m_colourScale(dBColourScale), | 53 m_colourScale(dBColourScale), |
54 m_colourScheme(DefaultColours), | 54 m_colourScheme(DefaultColours), |
55 m_frequencyScale(LinearFrequencyScale), | 55 m_frequencyScale(LinearFrequencyScale), |
56 m_binDisplay(AllBins), | 56 m_binDisplay(AllBins), |
57 m_normalizeColumns(false), | 57 m_normalizeColumns(false), |
58 m_cache(0), | 58 m_fftServer(0), |
59 m_writeCache(0), | 59 // m_fftServerChanged(true), |
60 m_cacheInvalid(true), | |
61 m_fillThread(0), | |
62 m_updateTimer(0), | 60 m_updateTimer(0), |
63 m_candidateFillStartFrame(0), | 61 m_candidateFillStartFrame(0), |
64 m_lastFillExtent(0), | 62 m_lastFillExtent(0), |
65 m_exiting(false) | 63 m_exiting(false) |
66 { | 64 { |
79 setFrequencyScale(LogFrequencyScale); | 77 setFrequencyScale(LogFrequencyScale); |
80 setColourScale(MeterColourScale); | 78 setColourScale(MeterColourScale); |
81 setBinDisplay(PeakFrequencies); | 79 setBinDisplay(PeakFrequencies); |
82 setNormalizeColumns(true); | 80 setNormalizeColumns(true); |
83 } | 81 } |
82 | |
83 setColourmap(); | |
84 } | 84 } |
85 | 85 |
86 SpectrogramLayer::~SpectrogramLayer() | 86 SpectrogramLayer::~SpectrogramLayer() |
87 { | 87 { |
88 delete m_updateTimer; | 88 delete m_updateTimer; |
89 m_updateTimer = 0; | 89 m_updateTimer = 0; |
90 | 90 |
91 m_exiting = true; | 91 if (m_fftServer) { |
92 m_condition.wakeAll(); | 92 FFTDataServer::releaseInstance(m_fftServer); |
93 if (m_fillThread) m_fillThread->wait(); | 93 m_fftServer = 0; |
94 delete m_fillThread; | 94 } |
95 | |
96 delete m_writeCache; | |
97 delete m_cache; | |
98 } | 95 } |
99 | 96 |
100 void | 97 void |
101 SpectrogramLayer::setModel(const DenseTimeValueModel *model) | 98 SpectrogramLayer::setModel(const DenseTimeValueModel *model) |
102 { | 99 { |
103 // std::cerr << "SpectrogramLayer(" << this << "): setModel(" << model << ")" << std::endl; | 100 // std::cerr << "SpectrogramLayer(" << this << "): setModel(" << model << ")" << std::endl; |
104 | 101 |
105 m_mutex.lock(); | 102 if (model == m_model) return; |
106 m_cacheInvalid = true; | 103 |
107 m_model = model; | 104 m_model = model; |
108 m_mutex.unlock(); | 105 getFFTServer(); |
109 | 106 |
110 if (!m_model || !m_model->isOK()) return; | 107 if (!m_model || !m_model->isOK()) return; |
111 | 108 |
112 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged())); | 109 connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged())); |
113 connect(m_model, SIGNAL(modelChanged(size_t, size_t)), | 110 connect(m_model, SIGNAL(modelChanged(size_t, size_t)), |
119 connect(m_model, SIGNAL(modelChanged()), this, SLOT(cacheInvalid())); | 116 connect(m_model, SIGNAL(modelChanged()), this, SLOT(cacheInvalid())); |
120 connect(m_model, SIGNAL(modelChanged(size_t, size_t)), | 117 connect(m_model, SIGNAL(modelChanged(size_t, size_t)), |
121 this, SLOT(cacheInvalid(size_t, size_t))); | 118 this, SLOT(cacheInvalid(size_t, size_t))); |
122 | 119 |
123 emit modelReplaced(); | 120 emit modelReplaced(); |
124 fillCache(); | 121 } |
122 | |
123 void | |
124 SpectrogramLayer::getFFTServer() | |
125 { | |
126 //!!! really want to check that params differ from previous ones | |
127 | |
128 if (m_fftServer) { | |
129 FFTDataServer::releaseInstance(m_fftServer); | |
130 m_fftServer = 0; | |
131 } | |
132 | |
133 if (m_model) { | |
134 m_fftServer = FFTDataServer::getInstance(m_model, | |
135 m_channel, | |
136 m_windowType, | |
137 m_windowSize, | |
138 getWindowIncrement(), | |
139 m_fftSize, | |
140 true, | |
141 m_candidateFillStartFrame); | |
142 | |
143 m_lastFillExtent = 0; | |
144 | |
145 delete m_updateTimer; | |
146 m_updateTimer = new QTimer(this); | |
147 connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(fillTimerTimedOut())); | |
148 m_updateTimer->start(200); | |
149 } | |
125 } | 150 } |
126 | 151 |
127 Layer::PropertyList | 152 Layer::PropertyList |
128 SpectrogramLayer::getProperties() const | 153 SpectrogramLayer::getProperties() const |
129 { | 154 { |
547 void | 572 void |
548 SpectrogramLayer::setChannel(int ch) | 573 SpectrogramLayer::setChannel(int ch) |
549 { | 574 { |
550 if (m_channel == ch) return; | 575 if (m_channel == ch) return; |
551 | 576 |
552 m_mutex.lock(); | |
553 m_cacheInvalid = true; | |
554 invalidatePixmapCaches(); | 577 invalidatePixmapCaches(); |
555 | |
556 m_channel = ch; | 578 m_channel = ch; |
557 | 579 getFFTServer(); |
558 m_mutex.unlock(); | |
559 | 580 |
560 emit layerParametersChanged(); | 581 emit layerParametersChanged(); |
561 | |
562 fillCache(); | |
563 } | 582 } |
564 | 583 |
565 int | 584 int |
566 SpectrogramLayer::getChannel() const | 585 SpectrogramLayer::getChannel() const |
567 { | 586 { |
571 void | 590 void |
572 SpectrogramLayer::setWindowSize(size_t ws) | 591 SpectrogramLayer::setWindowSize(size_t ws) |
573 { | 592 { |
574 if (m_windowSize == ws) return; | 593 if (m_windowSize == ws) return; |
575 | 594 |
576 m_mutex.lock(); | |
577 m_cacheInvalid = true; | |
578 invalidatePixmapCaches(); | 595 invalidatePixmapCaches(); |
579 | 596 |
580 m_windowSize = ws; | 597 m_windowSize = ws; |
581 m_fftSize = ws * (m_zeroPadLevel + 1); | 598 m_fftSize = ws * (m_zeroPadLevel + 1); |
582 | 599 |
583 m_mutex.unlock(); | 600 getFFTServer(); |
584 | 601 |
585 emit layerParametersChanged(); | 602 emit layerParametersChanged(); |
586 | |
587 fillCache(); | |
588 } | 603 } |
589 | 604 |
590 size_t | 605 size_t |
591 SpectrogramLayer::getWindowSize() const | 606 SpectrogramLayer::getWindowSize() const |
592 { | 607 { |
596 void | 611 void |
597 SpectrogramLayer::setWindowHopLevel(size_t v) | 612 SpectrogramLayer::setWindowHopLevel(size_t v) |
598 { | 613 { |
599 if (m_windowHopLevel == v) return; | 614 if (m_windowHopLevel == v) return; |
600 | 615 |
601 m_mutex.lock(); | |
602 m_cacheInvalid = true; | |
603 invalidatePixmapCaches(); | 616 invalidatePixmapCaches(); |
604 | 617 |
605 m_windowHopLevel = v; | 618 m_windowHopLevel = v; |
606 | 619 |
607 m_mutex.unlock(); | 620 getFFTServer(); |
608 | 621 |
609 emit layerParametersChanged(); | 622 emit layerParametersChanged(); |
610 | 623 |
611 fillCache(); | 624 // fillCache(); |
612 } | 625 } |
613 | 626 |
614 size_t | 627 size_t |
615 SpectrogramLayer::getWindowHopLevel() const | 628 SpectrogramLayer::getWindowHopLevel() const |
616 { | 629 { |
620 void | 633 void |
621 SpectrogramLayer::setZeroPadLevel(size_t v) | 634 SpectrogramLayer::setZeroPadLevel(size_t v) |
622 { | 635 { |
623 if (m_zeroPadLevel == v) return; | 636 if (m_zeroPadLevel == v) return; |
624 | 637 |
625 m_mutex.lock(); | |
626 m_cacheInvalid = true; | |
627 invalidatePixmapCaches(); | 638 invalidatePixmapCaches(); |
628 | 639 |
629 m_zeroPadLevel = v; | 640 m_zeroPadLevel = v; |
630 m_fftSize = m_windowSize * (v + 1); | 641 m_fftSize = m_windowSize * (v + 1); |
631 | 642 |
632 m_mutex.unlock(); | 643 getFFTServer(); |
633 | 644 |
634 emit layerParametersChanged(); | 645 emit layerParametersChanged(); |
635 | |
636 fillCache(); | |
637 } | 646 } |
638 | 647 |
639 size_t | 648 size_t |
640 SpectrogramLayer::getZeroPadLevel() const | 649 SpectrogramLayer::getZeroPadLevel() const |
641 { | 650 { |
645 void | 654 void |
646 SpectrogramLayer::setWindowType(WindowType w) | 655 SpectrogramLayer::setWindowType(WindowType w) |
647 { | 656 { |
648 if (m_windowType == w) return; | 657 if (m_windowType == w) return; |
649 | 658 |
650 m_mutex.lock(); | |
651 m_cacheInvalid = true; | |
652 invalidatePixmapCaches(); | 659 invalidatePixmapCaches(); |
653 | 660 |
654 m_windowType = w; | 661 m_windowType = w; |
655 | 662 |
656 m_mutex.unlock(); | 663 getFFTServer(); |
657 | 664 |
658 emit layerParametersChanged(); | 665 emit layerParametersChanged(); |
659 | |
660 fillCache(); | |
661 } | 666 } |
662 | 667 |
663 WindowType | 668 WindowType |
664 SpectrogramLayer::getWindowType() const | 669 SpectrogramLayer::getWindowType() const |
665 { | 670 { |
672 // std::cerr << "SpectrogramLayer::setGain(" << gain << ") (my gain is now " | 677 // std::cerr << "SpectrogramLayer::setGain(" << gain << ") (my gain is now " |
673 // << m_gain << ")" << std::endl; | 678 // << m_gain << ")" << std::endl; |
674 | 679 |
675 if (m_gain == gain) return; | 680 if (m_gain == gain) return; |
676 | 681 |
677 m_mutex.lock(); | |
678 invalidatePixmapCaches(); | 682 invalidatePixmapCaches(); |
679 | 683 |
680 m_gain = gain; | 684 m_gain = gain; |
681 | 685 |
682 m_mutex.unlock(); | |
683 | |
684 emit layerParametersChanged(); | 686 emit layerParametersChanged(); |
685 | |
686 fillCache(); | |
687 } | 687 } |
688 | 688 |
689 float | 689 float |
690 SpectrogramLayer::getGain() const | 690 SpectrogramLayer::getGain() const |
691 { | 691 { |
695 void | 695 void |
696 SpectrogramLayer::setThreshold(float threshold) | 696 SpectrogramLayer::setThreshold(float threshold) |
697 { | 697 { |
698 if (m_threshold == threshold) return; | 698 if (m_threshold == threshold) return; |
699 | 699 |
700 m_mutex.lock(); | |
701 invalidatePixmapCaches(); | 700 invalidatePixmapCaches(); |
702 | 701 |
703 m_threshold = threshold; | 702 m_threshold = threshold; |
704 | |
705 m_mutex.unlock(); | |
706 | 703 |
707 emit layerParametersChanged(); | 704 emit layerParametersChanged(); |
708 | |
709 fillCache(); | |
710 } | 705 } |
711 | 706 |
712 float | 707 float |
713 SpectrogramLayer::getThreshold() const | 708 SpectrogramLayer::getThreshold() const |
714 { | 709 { |
718 void | 713 void |
719 SpectrogramLayer::setMinFrequency(size_t mf) | 714 SpectrogramLayer::setMinFrequency(size_t mf) |
720 { | 715 { |
721 if (m_minFrequency == mf) return; | 716 if (m_minFrequency == mf) return; |
722 | 717 |
723 m_mutex.lock(); | |
724 invalidatePixmapCaches(); | 718 invalidatePixmapCaches(); |
725 | 719 |
726 m_minFrequency = mf; | 720 m_minFrequency = mf; |
727 | |
728 m_mutex.unlock(); | |
729 | 721 |
730 emit layerParametersChanged(); | 722 emit layerParametersChanged(); |
731 } | 723 } |
732 | 724 |
733 size_t | 725 size_t |
739 void | 731 void |
740 SpectrogramLayer::setMaxFrequency(size_t mf) | 732 SpectrogramLayer::setMaxFrequency(size_t mf) |
741 { | 733 { |
742 if (m_maxFrequency == mf) return; | 734 if (m_maxFrequency == mf) return; |
743 | 735 |
744 m_mutex.lock(); | |
745 invalidatePixmapCaches(); | 736 invalidatePixmapCaches(); |
746 | 737 |
747 m_maxFrequency = mf; | 738 m_maxFrequency = mf; |
748 | 739 |
749 m_mutex.unlock(); | |
750 | |
751 emit layerParametersChanged(); | 740 emit layerParametersChanged(); |
752 } | 741 } |
753 | 742 |
754 size_t | 743 size_t |
755 SpectrogramLayer::getMaxFrequency() const | 744 SpectrogramLayer::getMaxFrequency() const |
758 } | 747 } |
759 | 748 |
760 void | 749 void |
761 SpectrogramLayer::setColourRotation(int r) | 750 SpectrogramLayer::setColourRotation(int r) |
762 { | 751 { |
763 m_mutex.lock(); | |
764 invalidatePixmapCaches(); | 752 invalidatePixmapCaches(); |
765 | 753 |
766 if (r < 0) r = 0; | 754 if (r < 0) r = 0; |
767 if (r > 256) r = 256; | 755 if (r > 256) r = 256; |
768 int distance = r - m_colourRotation; | 756 int distance = r - m_colourRotation; |
770 if (distance != 0) { | 758 if (distance != 0) { |
771 rotateColourmap(-distance); | 759 rotateColourmap(-distance); |
772 m_colourRotation = r; | 760 m_colourRotation = r; |
773 } | 761 } |
774 | 762 |
775 m_mutex.unlock(); | |
776 | |
777 emit layerParametersChanged(); | 763 emit layerParametersChanged(); |
778 } | 764 } |
779 | 765 |
780 void | 766 void |
781 SpectrogramLayer::setColourScale(ColourScale colourScale) | 767 SpectrogramLayer::setColourScale(ColourScale colourScale) |
782 { | 768 { |
783 if (m_colourScale == colourScale) return; | 769 if (m_colourScale == colourScale) return; |
784 | 770 |
785 m_mutex.lock(); | |
786 invalidatePixmapCaches(); | 771 invalidatePixmapCaches(); |
787 | 772 |
788 m_colourScale = colourScale; | 773 m_colourScale = colourScale; |
789 | 774 |
790 m_mutex.unlock(); | |
791 fillCache(); | |
792 | |
793 emit layerParametersChanged(); | 775 emit layerParametersChanged(); |
794 } | 776 } |
795 | 777 |
796 SpectrogramLayer::ColourScale | 778 SpectrogramLayer::ColourScale |
797 SpectrogramLayer::getColourScale() const | 779 SpectrogramLayer::getColourScale() const |
802 void | 784 void |
803 SpectrogramLayer::setColourScheme(ColourScheme scheme) | 785 SpectrogramLayer::setColourScheme(ColourScheme scheme) |
804 { | 786 { |
805 if (m_colourScheme == scheme) return; | 787 if (m_colourScheme == scheme) return; |
806 | 788 |
807 m_mutex.lock(); | |
808 invalidatePixmapCaches(); | 789 invalidatePixmapCaches(); |
809 | 790 |
810 m_colourScheme = scheme; | 791 m_colourScheme = scheme; |
811 setColourmap(); | 792 setColourmap(); |
812 | 793 |
813 m_mutex.unlock(); | |
814 | |
815 emit layerParametersChanged(); | 794 emit layerParametersChanged(); |
816 } | 795 } |
817 | 796 |
818 SpectrogramLayer::ColourScheme | 797 SpectrogramLayer::ColourScheme |
819 SpectrogramLayer::getColourScheme() const | 798 SpectrogramLayer::getColourScheme() const |
824 void | 803 void |
825 SpectrogramLayer::setFrequencyScale(FrequencyScale frequencyScale) | 804 SpectrogramLayer::setFrequencyScale(FrequencyScale frequencyScale) |
826 { | 805 { |
827 if (m_frequencyScale == frequencyScale) return; | 806 if (m_frequencyScale == frequencyScale) return; |
828 | 807 |
829 m_mutex.lock(); | |
830 | |
831 invalidatePixmapCaches(); | 808 invalidatePixmapCaches(); |
832 | |
833 m_frequencyScale = frequencyScale; | 809 m_frequencyScale = frequencyScale; |
834 | |
835 m_mutex.unlock(); | |
836 | 810 |
837 emit layerParametersChanged(); | 811 emit layerParametersChanged(); |
838 } | 812 } |
839 | 813 |
840 SpectrogramLayer::FrequencyScale | 814 SpectrogramLayer::FrequencyScale |
846 void | 820 void |
847 SpectrogramLayer::setBinDisplay(BinDisplay binDisplay) | 821 SpectrogramLayer::setBinDisplay(BinDisplay binDisplay) |
848 { | 822 { |
849 if (m_binDisplay == binDisplay) return; | 823 if (m_binDisplay == binDisplay) return; |
850 | 824 |
851 m_mutex.lock(); | |
852 | |
853 invalidatePixmapCaches(); | 825 invalidatePixmapCaches(); |
854 | |
855 m_binDisplay = binDisplay; | 826 m_binDisplay = binDisplay; |
856 | |
857 m_mutex.unlock(); | |
858 | |
859 fillCache(); | |
860 | 827 |
861 emit layerParametersChanged(); | 828 emit layerParametersChanged(); |
862 } | 829 } |
863 | 830 |
864 SpectrogramLayer::BinDisplay | 831 SpectrogramLayer::BinDisplay |
869 | 836 |
870 void | 837 void |
871 SpectrogramLayer::setNormalizeColumns(bool n) | 838 SpectrogramLayer::setNormalizeColumns(bool n) |
872 { | 839 { |
873 if (m_normalizeColumns == n) return; | 840 if (m_normalizeColumns == n) return; |
874 m_mutex.lock(); | |
875 | 841 |
876 invalidatePixmapCaches(); | 842 invalidatePixmapCaches(); |
877 m_normalizeColumns = n; | 843 m_normalizeColumns = n; |
878 m_mutex.unlock(); | 844 |
879 | |
880 fillCache(); | |
881 emit layerParametersChanged(); | 845 emit layerParametersChanged(); |
882 } | 846 } |
883 | 847 |
884 bool | 848 bool |
885 SpectrogramLayer::getNormalizeColumns() const | 849 SpectrogramLayer::getNormalizeColumns() const |
888 } | 852 } |
889 | 853 |
890 void | 854 void |
891 SpectrogramLayer::setLayerDormant(const View *v, bool dormant) | 855 SpectrogramLayer::setLayerDormant(const View *v, bool dormant) |
892 { | 856 { |
893 QMutexLocker locker(&m_mutex); | |
894 | |
895 if (dormant == m_dormancy[v]) return; | 857 if (dormant == m_dormancy[v]) return; |
896 | 858 |
897 if (dormant) { | 859 if (dormant) { |
898 | 860 |
899 m_dormancy[v] = true; | 861 m_dormancy[v] = true; |
900 | 862 |
901 // delete m_cache; | |
902 // m_cache = 0; | |
903 | |
904 m_cacheInvalid = true; | |
905 invalidatePixmapCaches(); | 863 invalidatePixmapCaches(); |
906 m_pixmapCaches.erase(v); | 864 m_pixmapCaches.erase(v); |
907 | 865 |
908 } else { | 866 } else { |
909 | 867 |
912 } | 870 } |
913 | 871 |
914 void | 872 void |
915 SpectrogramLayer::cacheInvalid() | 873 SpectrogramLayer::cacheInvalid() |
916 { | 874 { |
917 m_cacheInvalid = true; | |
918 invalidatePixmapCaches(); | 875 invalidatePixmapCaches(); |
919 fillCache(); | |
920 } | 876 } |
921 | 877 |
922 void | 878 void |
923 SpectrogramLayer::cacheInvalid(size_t, size_t) | 879 SpectrogramLayer::cacheInvalid(size_t, size_t) |
924 { | 880 { |
925 // for now (or forever?) | 881 // for now (or forever?) |
926 cacheInvalid(); | 882 cacheInvalid(); |
927 } | 883 } |
928 | 884 |
929 void | 885 void |
930 SpectrogramLayer::fillCache() | |
931 { | |
932 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
933 std::cerr << "SpectrogramLayer::fillCache" << std::endl; | |
934 #endif | |
935 QMutexLocker locker(&m_mutex); | |
936 | |
937 m_lastFillExtent = 0; | |
938 | |
939 delete m_updateTimer; | |
940 m_updateTimer = new QTimer(this); | |
941 connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(fillTimerTimedOut())); | |
942 m_updateTimer->start(200); | |
943 | |
944 if (!m_fillThread) { | |
945 std::cerr << "SpectrogramLayer::fillCache creating thread" << std::endl; | |
946 m_fillThread = new CacheFillThread(*this); | |
947 m_fillThread->start(); | |
948 } | |
949 | |
950 m_condition.wakeAll(); | |
951 } | |
952 | |
953 void | |
954 SpectrogramLayer::fillTimerTimedOut() | 886 SpectrogramLayer::fillTimerTimedOut() |
955 { | 887 { |
956 if (m_fillThread && m_model) { | 888 if (m_fftServer && m_model) { |
957 size_t fillExtent = m_fillThread->getFillExtent(); | 889 |
890 size_t fillExtent = m_fftServer->getFillExtent(); | |
958 #ifdef DEBUG_SPECTROGRAM_REPAINT | 891 #ifdef DEBUG_SPECTROGRAM_REPAINT |
959 std::cerr << "SpectrogramLayer::fillTimerTimedOut: extent " << fillExtent << ", last " << m_lastFillExtent << ", total " << m_model->getEndFrame() << std::endl; | 892 std::cerr << "SpectrogramLayer::fillTimerTimedOut: extent " << fillExtent << ", last " << m_lastFillExtent << ", total " << m_model->getEndFrame() << std::endl; |
960 #endif | 893 #endif |
961 if (fillExtent >= m_lastFillExtent) { | 894 if (fillExtent >= m_lastFillExtent) { |
962 if (fillExtent >= m_model->getEndFrame() && m_lastFillExtent > 0) { | 895 if (fillExtent >= m_model->getEndFrame() && m_lastFillExtent > 0) { |
976 invalidatePixmapCaches(m_lastFillExtent, fillExtent); | 909 invalidatePixmapCaches(m_lastFillExtent, fillExtent); |
977 emit modelChanged(m_lastFillExtent, fillExtent); | 910 emit modelChanged(m_lastFillExtent, fillExtent); |
978 m_lastFillExtent = fillExtent; | 911 m_lastFillExtent = fillExtent; |
979 } | 912 } |
980 } else { | 913 } else { |
981 // if (v) { | |
982 size_t sf = 0; | |
983 //!!! if (v->getStartFrame() > 0) sf = v->getStartFrame(); | |
984 #ifdef DEBUG_SPECTROGRAM_REPAINT | 914 #ifdef DEBUG_SPECTROGRAM_REPAINT |
985 std::cerr << "SpectrogramLayer: going backwards, emitting modelChanged(" | 915 std::cerr << "SpectrogramLayer: going backwards, emitting modelChanged(" |
986 << sf << "," << m_model->getEndFrame() << ")" << std::endl; | 916 << m_model->getStartFrame() << "," << m_model->getEndFrame() << ")" << std::endl; |
987 #endif | 917 #endif |
988 invalidatePixmapCaches(); | 918 invalidatePixmapCaches(); |
989 emit modelChanged(sf, m_model->getEndFrame()); | 919 emit modelChanged(m_model->getStartFrame(), m_model->getEndFrame()); |
990 // } | |
991 m_lastFillExtent = fillExtent; | 920 m_lastFillExtent = fillExtent; |
992 } | 921 } |
993 } | 922 } |
994 } | 923 } |
995 | 924 |
1070 } | 999 } |
1071 | 1000 |
1072 void | 1001 void |
1073 SpectrogramLayer::rotateColourmap(int distance) | 1002 SpectrogramLayer::rotateColourmap(int distance) |
1074 { | 1003 { |
1075 if (!m_cache) return; | 1004 if (!m_fftServer) return; |
1076 | 1005 |
1077 QColor newPixels[256]; | 1006 QColor newPixels[256]; |
1078 | 1007 |
1079 newPixels[NO_VALUE] = m_colourMap.getColour(NO_VALUE); | 1008 newPixels[NO_VALUE] = m_colourMap.getColour(NO_VALUE); |
1080 | 1009 |
1128 return newFrequency; | 1057 return newFrequency; |
1129 } | 1058 } |
1130 | 1059 |
1131 steadyState = false; | 1060 steadyState = false; |
1132 return frequency; | 1061 return frequency; |
1133 } | |
1134 | |
1135 void | |
1136 SpectrogramLayer::fillCacheColumn(int column, | |
1137 fftsample *input, | |
1138 fftwf_complex *output, | |
1139 fftwf_plan plan, | |
1140 size_t windowSize, | |
1141 size_t fftSize, | |
1142 size_t increment, | |
1143 float *workbuffer, | |
1144 const Window<fftsample> &windower) const | |
1145 { | |
1146 //!!! we _do_ need a lock for these references to the model | |
1147 // though, don't we? | |
1148 | |
1149 int startFrame = increment * column; | |
1150 int endFrame = startFrame + windowSize; | |
1151 | |
1152 startFrame -= int(windowSize - increment) / 2; | |
1153 endFrame -= int(windowSize - increment) / 2; | |
1154 size_t pfx = 0; | |
1155 | |
1156 size_t off = (m_fftSize - m_windowSize) / 2; | |
1157 | |
1158 for (size_t i = 0; i < off; ++i) { | |
1159 input[i] = 0.0; | |
1160 input[m_fftSize - i - 1] = 0.0; | |
1161 } | |
1162 | |
1163 if (startFrame < 0) { | |
1164 pfx = size_t(-startFrame); | |
1165 for (size_t i = 0; i < pfx; ++i) { | |
1166 input[off + i] = 0.0; | |
1167 } | |
1168 } | |
1169 | |
1170 size_t got = m_model->getValues(m_channel, startFrame + pfx, | |
1171 endFrame, input + off + pfx); | |
1172 | |
1173 while (got + pfx < windowSize) { | |
1174 input[off + got + pfx] = 0.0; | |
1175 ++got; | |
1176 } | |
1177 | |
1178 if (m_channel == -1) { | |
1179 int channels = m_model->getChannelCount(); | |
1180 if (channels > 1) { | |
1181 for (size_t i = 0; i < windowSize; ++i) { | |
1182 input[off + i] /= channels; | |
1183 } | |
1184 } | |
1185 } | |
1186 | |
1187 windower.cut(input + off); | |
1188 | |
1189 for (size_t i = 0; i < fftSize/2; ++i) { | |
1190 fftsample temp = input[i]; | |
1191 input[i] = input[i + fftSize/2]; | |
1192 input[i + fftSize/2] = temp; | |
1193 } | |
1194 | |
1195 fftwf_execute(plan); | |
1196 | |
1197 fftsample factor = 0.0; | |
1198 | |
1199 for (size_t i = 0; i < fftSize/2; ++i) { | |
1200 | |
1201 fftsample mag = sqrtf(output[i][0] * output[i][0] + | |
1202 output[i][1] * output[i][1]); | |
1203 mag /= windowSize / 2; | |
1204 | |
1205 if (mag > factor) factor = mag; | |
1206 | |
1207 fftsample phase = atan2f(output[i][1], output[i][0]); | |
1208 phase = princargf(phase); | |
1209 | |
1210 workbuffer[i] = mag; | |
1211 workbuffer[i + fftSize/2] = phase; | |
1212 } | |
1213 | |
1214 m_writeCache->setColumnAt(column, workbuffer, | |
1215 workbuffer + fftSize/2, factor); | |
1216 } | 1062 } |
1217 | 1063 |
1218 unsigned char | 1064 unsigned char |
1219 SpectrogramLayer::getDisplayValue(float input) const | 1065 SpectrogramLayer::getDisplayValue(float input) const |
1220 { | 1066 { |
1282 } | 1128 } |
1283 | 1129 |
1284 return input; | 1130 return input; |
1285 } | 1131 } |
1286 | 1132 |
1287 void | |
1288 SpectrogramLayer::CacheFillThread::run() | |
1289 { | |
1290 // std::cerr << "SpectrogramLayer::CacheFillThread::run" << std::endl; | |
1291 | |
1292 m_layer.m_mutex.lock(); | |
1293 | |
1294 while (!m_layer.m_exiting) { | |
1295 | |
1296 bool interrupted = false; | |
1297 | |
1298 // std::cerr << "SpectrogramLayer::CacheFillThread::run in loop" << std::endl; | |
1299 | |
1300 bool haveUndormantViews = false; | |
1301 | |
1302 for (std::map<const void *, bool>::iterator i = | |
1303 m_layer.m_dormancy.begin(); | |
1304 i != m_layer.m_dormancy.end(); ++i) { | |
1305 | |
1306 if (!i->second) { | |
1307 haveUndormantViews = true; | |
1308 break; | |
1309 } | |
1310 } | |
1311 | |
1312 if (!haveUndormantViews) { | |
1313 | |
1314 if (m_layer.m_cacheInvalid && m_layer.m_cache) { | |
1315 std::cerr << "All views dormant, freeing spectrogram cache" | |
1316 << std::endl; | |
1317 | |
1318 delete m_layer.m_cache; | |
1319 m_layer.m_cache = 0; | |
1320 } | |
1321 | |
1322 } else if (m_layer.m_model && m_layer.m_cacheInvalid) { | |
1323 | |
1324 // std::cerr << "SpectrogramLayer::CacheFillThread::run: something to do" << std::endl; | |
1325 | |
1326 while (!m_layer.m_model->isReady()) { | |
1327 m_layer.m_condition.wait(&m_layer.m_mutex, 100); | |
1328 if (m_layer.m_exiting) break; | |
1329 } | |
1330 | |
1331 if (m_layer.m_exiting) break; | |
1332 | |
1333 m_layer.m_cacheInvalid = false; | |
1334 m_fillExtent = 0; | |
1335 m_fillCompletion = 0; | |
1336 | |
1337 // std::cerr << "SpectrogramLayer::CacheFillThread::run: model is ready" << std::endl; | |
1338 | |
1339 size_t start = m_layer.m_model->getStartFrame(); | |
1340 size_t end = m_layer.m_model->getEndFrame(); | |
1341 | |
1342 // std::cerr << "start = " << start << ", end = " << end << std::endl; | |
1343 | |
1344 WindowType windowType = m_layer.m_windowType; | |
1345 size_t windowSize = m_layer.m_windowSize; | |
1346 size_t windowIncrement = m_layer.getWindowIncrement(); | |
1347 size_t fftSize = m_layer.m_fftSize; | |
1348 | |
1349 // std::cerr << "\nWINDOW INCREMENT: " << windowIncrement << " (for hop level " << m_layer.m_windowHopLevel << ")\n" << std::endl; | |
1350 | |
1351 size_t visibleStart = m_layer.m_candidateFillStartFrame; | |
1352 visibleStart = (visibleStart / windowIncrement) * windowIncrement; | |
1353 | |
1354 size_t width = (end - start) / windowIncrement + 1; | |
1355 size_t height = fftSize / 2; | |
1356 | |
1357 //!!! if (!m_layer.m_cache) { | |
1358 // m_layer.m_cache = new FFTMemoryCache; | |
1359 // } | |
1360 if (!m_layer.m_writeCache) { | |
1361 m_layer.m_writeCache = new FFTFileCache | |
1362 (QString("%1").arg(getObjectExportId(&m_layer)), | |
1363 MatrixFile::ReadWrite, true); | |
1364 } | |
1365 m_layer.m_writeCache->resize(width, height); | |
1366 if (m_layer.m_cache) delete m_layer.m_cache; | |
1367 m_layer.m_cache = new FFTFileCache | |
1368 (QString("%1").arg(getObjectExportId(&m_layer)), | |
1369 MatrixFile::ReadOnly, true); | |
1370 | |
1371 m_layer.setColourmap(); | |
1372 //!!! m_layer.m_writeCache->reset(); | |
1373 | |
1374 fftsample *input = (fftsample *) | |
1375 fftwf_malloc(fftSize * sizeof(fftsample)); | |
1376 | |
1377 fftwf_complex *output = (fftwf_complex *) | |
1378 fftwf_malloc(fftSize * sizeof(fftwf_complex)); | |
1379 | |
1380 float *workbuffer = (float *) | |
1381 fftwf_malloc(fftSize * sizeof(float)); | |
1382 | |
1383 fftwf_plan plan = fftwf_plan_dft_r2c_1d(fftSize, input, | |
1384 output, FFTW_ESTIMATE); | |
1385 | |
1386 if (!plan) { | |
1387 std::cerr << "WARNING: fftwf_plan_dft_r2c_1d(" << windowSize << ") failed!" << std::endl; | |
1388 fftwf_free(input); | |
1389 fftwf_free(output); | |
1390 fftwf_free(workbuffer); | |
1391 continue; | |
1392 } | |
1393 | |
1394 // We don't need a lock when writing to or reading from | |
1395 // the pixels in the cache. We do need to ensure we have | |
1396 // the width and height of the cache and the FFT | |
1397 // parameters known before we unlock, in case they change | |
1398 // in the model while we aren't holding a lock. It's safe | |
1399 // for us to continue to use the "old" values if that | |
1400 // happens, because they will continue to match the | |
1401 // dimensions of the actual cache (which this thread | |
1402 // manages, not the layer's). | |
1403 m_layer.m_mutex.unlock(); | |
1404 | |
1405 Window<fftsample> windower(windowType, windowSize); | |
1406 | |
1407 int counter = 0; | |
1408 int updateAt = (end / windowIncrement) / 20; | |
1409 if (updateAt < 100) updateAt = 100; | |
1410 | |
1411 bool doVisibleFirst = (visibleStart != start); | |
1412 | |
1413 if (doVisibleFirst) { | |
1414 | |
1415 for (size_t f = visibleStart; f < end; f += windowIncrement) { | |
1416 | |
1417 m_layer.fillCacheColumn(int((f - start) / windowIncrement), | |
1418 input, output, plan, | |
1419 windowSize, fftSize, | |
1420 windowIncrement, | |
1421 workbuffer, windower); | |
1422 | |
1423 if (m_layer.m_cacheInvalid || m_layer.m_exiting) { | |
1424 interrupted = true; | |
1425 m_fillExtent = 0; | |
1426 break; | |
1427 } | |
1428 | |
1429 if (++counter == updateAt) { | |
1430 m_fillExtent = f; | |
1431 m_fillCompletion = size_t(100 * fabsf(float(f - visibleStart) / | |
1432 float(end - start))); | |
1433 counter = 0; | |
1434 } | |
1435 } | |
1436 } | |
1437 | |
1438 if (!interrupted) { | |
1439 | |
1440 size_t remainingEnd = end; | |
1441 if (doVisibleFirst) { | |
1442 remainingEnd = visibleStart; | |
1443 if (remainingEnd > start) --remainingEnd; | |
1444 else remainingEnd = start; | |
1445 } | |
1446 size_t baseCompletion = m_fillCompletion; | |
1447 | |
1448 for (size_t f = start; f < remainingEnd; f += windowIncrement) { | |
1449 | |
1450 m_layer.fillCacheColumn(int((f - start) / windowIncrement), | |
1451 input, output, plan, | |
1452 windowSize, fftSize, | |
1453 windowIncrement, | |
1454 workbuffer, windower); | |
1455 | |
1456 if (m_layer.m_cacheInvalid || m_layer.m_exiting) { | |
1457 interrupted = true; | |
1458 m_fillExtent = 0; | |
1459 break; | |
1460 } | |
1461 | |
1462 if (++counter == updateAt) { | |
1463 m_fillExtent = f; | |
1464 m_fillCompletion = baseCompletion + | |
1465 size_t(100 * fabsf(float(f - start) / | |
1466 float(end - start))); | |
1467 counter = 0; | |
1468 } | |
1469 } | |
1470 } | |
1471 | |
1472 fftwf_destroy_plan(plan); | |
1473 fftwf_free(output); | |
1474 fftwf_free(input); | |
1475 fftwf_free(workbuffer); | |
1476 | |
1477 if (!interrupted) { | |
1478 m_fillExtent = end; | |
1479 m_fillCompletion = 100; | |
1480 } | |
1481 | |
1482 m_layer.m_mutex.lock(); | |
1483 } | |
1484 | |
1485 if (!interrupted) m_layer.m_condition.wait(&m_layer.m_mutex, 2000); | |
1486 } | |
1487 } | |
1488 | |
1489 float | 1133 float |
1490 SpectrogramLayer::getEffectiveMinFrequency() const | 1134 SpectrogramLayer::getEffectiveMinFrequency() const |
1491 { | 1135 { |
1492 int sr = m_model->getSampleRate(); | 1136 int sr = m_model->getSampleRate(); |
1493 float minf = float(sr) / m_fftSize; | 1137 float minf = float(sr) / m_fftSize; |
1613 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y, | 1257 SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y, |
1614 float &freqMin, float &freqMax, | 1258 float &freqMin, float &freqMax, |
1615 float &adjFreqMin, float &adjFreqMax) | 1259 float &adjFreqMin, float &adjFreqMax) |
1616 const | 1260 const |
1617 { | 1261 { |
1262 if (!m_fftServer) return false; | |
1263 | |
1618 float s0 = 0, s1 = 0; | 1264 float s0 = 0, s1 = 0; |
1619 if (!getXBinRange(v, x, s0, s1)) return false; | 1265 if (!getXBinRange(v, x, s0, s1)) return false; |
1620 | 1266 |
1621 float q0 = 0, q1 = 0; | 1267 float q0 = 0, q1 = 0; |
1622 if (!getYBinRange(v, y, q0, q1)) return false; | 1268 if (!getYBinRange(v, y, q0, q1)) return false; |
1643 | 1289 |
1644 float binfreq = (sr * q) / m_windowSize; | 1290 float binfreq = (sr * q) / m_windowSize; |
1645 if (q == q0i) freqMin = binfreq; | 1291 if (q == q0i) freqMin = binfreq; |
1646 if (q == q1i) freqMax = binfreq; | 1292 if (q == q1i) freqMax = binfreq; |
1647 | 1293 |
1648 if (!m_cache || m_cacheInvalid) break; //!!! lock? | 1294 if (peaksOnly && !m_fftServer->isLocalPeak(s, q)) continue; |
1649 | 1295 |
1650 if (peaksOnly && !m_cache->isLocalPeak(s, q)) continue; | 1296 if (!m_fftServer->isOverThreshold(s, q, m_threshold)) continue; |
1651 | |
1652 if (!m_cache->isOverThreshold(s, q, m_threshold)) continue; | |
1653 | 1297 |
1654 float freq = binfreq; | 1298 float freq = binfreq; |
1655 bool steady = false; | 1299 bool steady = false; |
1656 | 1300 |
1657 if (s < int(m_cache->getWidth()) - 1) { | 1301 if (s < int(m_fftServer->getWidth()) - 1) { |
1658 | 1302 |
1659 freq = calculateFrequency(q, | 1303 freq = calculateFrequency(q, |
1660 windowSize, | 1304 windowSize, |
1661 windowIncrement, | 1305 windowIncrement, |
1662 sr, | 1306 sr, |
1663 m_cache->getPhaseAt(s, q), | 1307 m_fftServer->getPhaseAt(s, q), |
1664 m_cache->getPhaseAt(s+1, q), | 1308 m_fftServer->getPhaseAt(s+1, q), |
1665 steady); | 1309 steady); |
1666 | 1310 |
1667 if (!haveAdj || freq < adjFreqMin) adjFreqMin = freq; | 1311 if (!haveAdj || freq < adjFreqMin) adjFreqMin = freq; |
1668 if (!haveAdj || freq > adjFreqMax) adjFreqMax = freq; | 1312 if (!haveAdj || freq > adjFreqMax) adjFreqMax = freq; |
1669 | 1313 |
1696 int s0i = int(s0 + 0.001); | 1340 int s0i = int(s0 + 0.001); |
1697 int s1i = int(s1); | 1341 int s1i = int(s1); |
1698 | 1342 |
1699 bool rv = false; | 1343 bool rv = false; |
1700 | 1344 |
1701 if (m_mutex.tryLock()) { | 1345 if (m_fftServer) { |
1702 if (m_cache && !m_cacheInvalid) { | 1346 |
1703 | 1347 int cw = m_fftServer->getWidth(); |
1704 int cw = m_cache->getWidth(); | 1348 int ch = m_fftServer->getHeight(); |
1705 int ch = m_cache->getHeight(); | 1349 |
1706 | 1350 min = 0.0; |
1707 min = 0.0; | 1351 max = 0.0; |
1708 max = 0.0; | 1352 phaseMin = 0.0; |
1709 phaseMin = 0.0; | 1353 phaseMax = 0.0; |
1710 phaseMax = 0.0; | 1354 bool have = false; |
1711 bool have = false; | 1355 |
1712 | 1356 for (int q = q0i; q <= q1i; ++q) { |
1713 for (int q = q0i; q <= q1i; ++q) { | 1357 for (int s = s0i; s <= s1i; ++s) { |
1714 for (int s = s0i; s <= s1i; ++s) { | 1358 if (s >= 0 && q >= 0 && s < cw && q < ch) { |
1715 if (s >= 0 && q >= 0 && s < cw && q < ch) { | 1359 |
1716 | 1360 float value; |
1717 if (!m_cache->haveSetColumnAt(s)) continue; | 1361 |
1718 | 1362 value = m_fftServer->getPhaseAt(s, q); |
1719 float value; | 1363 if (!have || value < phaseMin) { phaseMin = value; } |
1720 | 1364 if (!have || value > phaseMax) { phaseMax = value; } |
1721 value = m_cache->getPhaseAt(s, q); | 1365 |
1722 if (!have || value < phaseMin) { phaseMin = value; } | 1366 value = m_fftServer->getMagnitudeAt(s, q); |
1723 if (!have || value > phaseMax) { phaseMax = value; } | 1367 if (!have || value < min) { min = value; } |
1724 | 1368 if (!have || value > max) { max = value; } |
1725 value = m_cache->getMagnitudeAt(s, q); | 1369 |
1726 if (!have || value < min) { min = value; } | 1370 have = true; |
1727 if (!have || value > max) { max = value; } | 1371 } |
1728 | 1372 } |
1729 have = true; | 1373 } |
1730 } | 1374 |
1731 } | 1375 if (have) { |
1732 } | 1376 rv = true; |
1733 | 1377 } |
1734 if (have) { | |
1735 rv = true; | |
1736 } | |
1737 } | |
1738 | |
1739 m_mutex.unlock(); | |
1740 } | 1378 } |
1741 | 1379 |
1742 return rv; | 1380 return rv; |
1743 } | 1381 } |
1744 | 1382 |
1774 // is not in the dormancy map at all -- we need it to be present | 1412 // is not in the dormancy map at all -- we need it to be present |
1775 // and accountable for when determining whether we need the cache | 1413 // and accountable for when determining whether we need the cache |
1776 // in the cache-fill thread above. | 1414 // in the cache-fill thread above. |
1777 m_dormancy[v] = false; | 1415 m_dormancy[v] = false; |
1778 | 1416 |
1417 if (!m_fftServer) { // lock the mutex before checking this | |
1779 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1418 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1780 // std::cerr << "SpectrogramLayer::paint(): About to lock" << std::endl; | 1419 std::cerr << "SpectrogramLayer::paint(): No FFT server, returning" << std::endl; |
1781 #endif | |
1782 | |
1783 m_mutex.lock(); | |
1784 | |
1785 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1786 // std::cerr << "SpectrogramLayer::paint(): locked" << std::endl; | |
1787 #endif | |
1788 | |
1789 if (m_cacheInvalid) { // lock the mutex before checking this | |
1790 m_mutex.unlock(); | |
1791 #ifdef DEBUG_SPECTROGRAM_REPAINT | |
1792 std::cerr << "SpectrogramLayer::paint(): Cache invalid, returning" << std::endl; | |
1793 #endif | 1420 #endif |
1794 return; | 1421 return; |
1795 } | 1422 } |
1796 | 1423 |
1797 PixmapCache &cache = m_pixmapCaches[v]; | 1424 PixmapCache &cache = m_pixmapCaches[v]; |
1834 | 1461 |
1835 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1462 #ifdef DEBUG_SPECTROGRAM_REPAINT |
1836 std::cerr << "SpectrogramLayer: pixmap cache good" << std::endl; | 1463 std::cerr << "SpectrogramLayer: pixmap cache good" << std::endl; |
1837 #endif | 1464 #endif |
1838 | 1465 |
1839 m_mutex.unlock(); | |
1840 paint.drawPixmap(rect, cache.pixmap, rect); | 1466 paint.drawPixmap(rect, cache.pixmap, rect); |
1841 return; | 1467 return; |
1842 | 1468 |
1843 } else { | 1469 } else { |
1844 | 1470 |
2022 | 1648 |
2023 size_t increment = getWindowIncrement(); | 1649 size_t increment = getWindowIncrement(); |
2024 | 1650 |
2025 bool logarithmic = (m_frequencyScale == LogFrequencyScale); | 1651 bool logarithmic = (m_frequencyScale == LogFrequencyScale); |
2026 | 1652 |
2027 m_mutex.unlock(); | |
2028 | |
2029 for (size_t q = minbin; q <= bins; ++q) { | 1653 for (size_t q = minbin; q <= bins; ++q) { |
2030 float f0 = (float(q) * sr) / m_fftSize; | 1654 float f0 = (float(q) * sr) / m_fftSize; |
2031 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic); | 1655 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic); |
2032 } | 1656 } |
2033 | 1657 |
2034 m_mutex.lock(); | |
2035 | |
2036 for (int x = 0; x < w; ++x) { | 1658 for (int x = 0; x < w; ++x) { |
2037 | |
2038 if (x % 10 == 0) { | |
2039 m_mutex.unlock(); | |
2040 m_mutex.lock(); | |
2041 if (m_cacheInvalid) { | |
2042 break; | |
2043 } | |
2044 } | |
2045 | 1659 |
2046 for (int y = 0; y < h; ++y) { | 1660 for (int y = 0; y < h; ++y) { |
2047 ymag[y] = 0.0; | 1661 ymag[y] = 0.0; |
2048 ydiv[y] = 0.0; | 1662 ydiv[y] = 0.0; |
2049 } | 1663 } |
2056 } | 1670 } |
2057 | 1671 |
2058 int s0i = int(s0 + 0.001); | 1672 int s0i = int(s0 + 0.001); |
2059 int s1i = int(s1); | 1673 int s1i = int(s1); |
2060 | 1674 |
2061 if (s1i >= m_cache->getWidth()) { | 1675 if (s1i >= m_fftServer->getWidth()) { |
2062 if (s0i >= m_cache->getWidth()) { | 1676 if (s0i >= m_fftServer->getWidth()) { |
2063 continue; | 1677 continue; |
2064 } else { | 1678 } else { |
2065 s1i = s0i; | 1679 s1i = s0i; |
2066 } | 1680 } |
2067 } | 1681 } |
2068 | 1682 |
2069 for (int s = s0i; s <= s1i; ++s) { | 1683 for (int s = s0i; s <= s1i; ++s) { |
2070 | 1684 |
2071 if (!m_cache->haveSetColumnAt(s)) continue; | 1685 // if (!m_fftServer->haveSetColumnAt(s)) continue; |
2072 | 1686 |
2073 for (size_t q = minbin; q < bins; ++q) { | 1687 for (size_t q = minbin; q < bins; ++q) { |
2074 | 1688 |
2075 float y0 = yval[q + 1]; | 1689 float y0 = yval[q + 1]; |
2076 float y1 = yval[q]; | 1690 float y1 = yval[q]; |
2077 | 1691 |
2078 if (m_binDisplay == PeakBins || | 1692 if (m_binDisplay == PeakBins || |
2079 m_binDisplay == PeakFrequencies) { | 1693 m_binDisplay == PeakFrequencies) { |
2080 if (!m_cache->isLocalPeak(s, q)) continue; | 1694 if (!m_fftServer->isLocalPeak(s, q)) continue; |
2081 } | 1695 } |
2082 | 1696 |
2083 if (!m_cache->isOverThreshold(s, q, m_threshold)) continue; | 1697 if (!m_fftServer->isOverThreshold(s, q, m_threshold)) continue; |
2084 | 1698 |
2085 float sprop = 1.0; | 1699 float sprop = 1.0; |
2086 if (s == s0i) sprop *= (s + 1) - s0; | 1700 if (s == s0i) sprop *= (s + 1) - s0; |
2087 if (s == s1i) sprop *= s1 - s; | 1701 if (s == s1i) sprop *= s1 - s; |
2088 | 1702 |
2089 if (m_binDisplay == PeakFrequencies && | 1703 if (m_binDisplay == PeakFrequencies && |
2090 s < int(m_cache->getWidth()) - 1) { | 1704 s < int(m_fftServer->getWidth()) - 1) { |
2091 | 1705 |
2092 bool steady = false; | 1706 bool steady = false; |
2093 float f = calculateFrequency(q, | 1707 float f = calculateFrequency(q, |
2094 m_windowSize, | 1708 m_windowSize, |
2095 increment, | 1709 increment, |
2096 sr, | 1710 sr, |
2097 m_cache->getPhaseAt(s, q), | 1711 m_fftServer->getPhaseAt(s, q), |
2098 m_cache->getPhaseAt(s+1, q), | 1712 m_fftServer->getPhaseAt(s+1, q), |
2099 steady); | 1713 steady); |
2100 | 1714 |
2101 y0 = y1 = v->getYForFrequency | 1715 y0 = y1 = v->getYForFrequency |
2102 (f, minFreq, maxFreq, logarithmic); | 1716 (f, minFreq, maxFreq, logarithmic); |
2103 } | 1717 } |
2106 int y1i = int(y1); | 1720 int y1i = int(y1); |
2107 | 1721 |
2108 float value; | 1722 float value; |
2109 | 1723 |
2110 if (m_colourScale == PhaseColourScale) { | 1724 if (m_colourScale == PhaseColourScale) { |
2111 value = m_cache->getPhaseAt(s, q); | 1725 value = m_fftServer->getPhaseAt(s, q); |
2112 } else if (m_normalizeColumns) { | 1726 } else if (m_normalizeColumns) { |
2113 value = m_cache->getNormalizedMagnitudeAt(s, q) * m_gain; | 1727 value = m_fftServer->getNormalizedMagnitudeAt(s, q) * m_gain; |
2114 } else { | 1728 } else { |
2115 value = m_cache->getMagnitudeAt(s, q) * m_gain; | 1729 value = m_fftServer->getMagnitudeAt(s, q) * m_gain; |
2116 } | 1730 } |
2117 | 1731 |
2118 for (int y = y0i; y <= y1i; ++y) { | 1732 for (int y = y0i; y <= y1i; ++y) { |
2119 | 1733 |
2120 if (y < 0 || y >= h) continue; | 1734 if (y < 0 || y >= h) continue; |
2143 qRgb(c.red(), c.green(), c.blue())); | 1757 qRgb(c.red(), c.green(), c.blue())); |
2144 } | 1758 } |
2145 } | 1759 } |
2146 } | 1760 } |
2147 | 1761 |
2148 m_mutex.unlock(); | |
2149 | |
2150 paint.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h); | 1762 paint.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h); |
2151 | 1763 |
2152 if (recreateWholePixmapCache) { | 1764 if (recreateWholePixmapCache) { |
2153 cache.pixmap = QPixmap(v->width(), v->height()); | 1765 cache.pixmap = QPixmap(v->width(), v->height()); |
2154 } | 1766 } |
2155 | 1767 |
2156 QPainter cachePainter(&cache.pixmap); | 1768 QPainter cachePainter(&cache.pixmap); |
2157 cachePainter.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h); | 1769 cachePainter.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h); |
2158 cachePainter.end(); | 1770 cachePainter.end(); |
2159 | 1771 |
2160 // m_pixmapCacheInvalid = false; | |
2161 cache.startFrame = startFrame; | 1772 cache.startFrame = startFrame; |
2162 cache.zoomLevel = zoomLevel; | 1773 cache.zoomLevel = zoomLevel; |
2163 | 1774 |
2164 if (cache.validArea.x() > 0) { | 1775 if (cache.validArea.x() > 0) { |
2165 #ifdef DEBUG_SPECTROGRAM_REPAINT | 1776 #ifdef DEBUG_SPECTROGRAM_REPAINT |
2209 } | 1820 } |
2210 | 1821 |
2211 int | 1822 int |
2212 SpectrogramLayer::getCompletion() const | 1823 SpectrogramLayer::getCompletion() const |
2213 { | 1824 { |
2214 if (m_updateTimer == 0) return 100; | 1825 if (m_updateTimer == 0 || !m_fftServer) return 100; |
2215 size_t completion = m_fillThread->getFillCompletion(); | 1826 size_t completion = m_fftServer->getFillCompletion(); |
2216 // std::cerr << "SpectrogramLayer::getCompletion: completion = " << completion << std::endl; | 1827 // std::cerr << "SpectrogramLayer::getCompletion: completion = " << completion << std::endl; |
2217 return completion; | 1828 return completion; |
2218 } | 1829 } |
2219 | 1830 |
2220 bool | 1831 bool |
2493 | 2104 |
2494 int py = -1; | 2105 int py = -1; |
2495 int textHeight = paint.fontMetrics().height(); | 2106 int textHeight = paint.fontMetrics().height(); |
2496 int toff = -textHeight + paint.fontMetrics().ascent() + 2; | 2107 int toff = -textHeight + paint.fontMetrics().ascent() + 2; |
2497 | 2108 |
2498 if (m_cache && !m_cacheInvalid && h > textHeight * 2 + 10) { //!!! lock? | 2109 if (m_fftServer && h > textHeight * 2 + 10) { |
2499 | 2110 |
2500 int ch = h - textHeight * 2 - 8; | 2111 int ch = h - textHeight * 2 - 8; |
2501 paint.drawRect(4, textHeight + 4, cw - 1, ch + 1); | 2112 paint.drawRect(4, textHeight + 4, cw - 1, ch + 1); |
2502 | 2113 |
2503 QString top, bottom; | 2114 QString top, bottom; |
2586 | 2197 |
2587 if (m_frequencyScale == LogFrequencyScale) { | 2198 if (m_frequencyScale == LogFrequencyScale) { |
2588 | 2199 |
2589 paint.drawLine(w - pkw - 1, 0, w - pkw - 1, h); | 2200 paint.drawLine(w - pkw - 1, 0, w - pkw - 1, h); |
2590 | 2201 |
2591 int sr = m_model->getSampleRate();//!!! lock? | 2202 int sr = m_model->getSampleRate(); |
2592 float minf = getEffectiveMinFrequency(); | 2203 float minf = getEffectiveMinFrequency(); |
2593 float maxf = getEffectiveMaxFrequency(); | 2204 float maxf = getEffectiveMaxFrequency(); |
2594 | 2205 |
2595 int py = h; | 2206 int py = h; |
2596 paint.setBrush(paint.pen().color()); | 2207 paint.setBrush(paint.pen().color()); |