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