comparison layer/SpectrogramLayer.cpp @ 187:e7cf6044c2a0

* better icon * support range mappers in thumbwheel * supply range mapper for vertical zoom from spectrogram * fix bug in fftmodel for scaled ffts * make the various widgets all respond to double-click for edit, middle-click for reset, ctrl-left-click for reset
author Chris Cannam
date Fri, 12 Jan 2007 14:49:18 +0000
parents 3a6fea0abf56
children dd573e090eed
comparison
equal deleted inserted replaced
186:8dd247c4c5f1 187:e7cf6044c2a0
723 void 723 void
724 SpectrogramLayer::setMinFrequency(size_t mf) 724 SpectrogramLayer::setMinFrequency(size_t mf)
725 { 725 {
726 if (m_minFrequency == mf) return; 726 if (m_minFrequency == mf) return;
727 727
728 std::cerr << "SpectrogramLayer::setMinFrequency: " << mf << std::endl;
729
728 invalidatePixmapCaches(); 730 invalidatePixmapCaches();
729 invalidateMagnitudes(); 731 invalidateMagnitudes();
730 732
731 m_minFrequency = mf; 733 m_minFrequency = mf;
732 734
741 743
742 void 744 void
743 SpectrogramLayer::setMaxFrequency(size_t mf) 745 SpectrogramLayer::setMaxFrequency(size_t mf)
744 { 746 {
745 if (m_maxFrequency == mf) return; 747 if (m_maxFrequency == mf) return;
748
749 std::cerr << "SpectrogramLayer::setMaxFrequency: " << mf << std::endl;
746 750
747 invalidatePixmapCaches(); 751 invalidatePixmapCaches();
748 invalidateMagnitudes(); 752 invalidateMagnitudes();
749 753
750 m_maxFrequency = mf; 754 m_maxFrequency = mf;
1593 #endif 1597 #endif
1594 delete m_fftModels[v].first; 1598 delete m_fftModels[v].first;
1595 m_fftModels.erase(v); 1599 m_fftModels.erase(v);
1596 } else { 1600 } else {
1597 #ifdef DEBUG_SPECTROGRAM_REPAINT 1601 #ifdef DEBUG_SPECTROGRAM_REPAINT
1598 std::cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a good model" << std::endl; 1602 std::cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a good model of height " << m_fftModels[v].first->getHeight() << std::endl;
1599 #endif 1603 #endif
1600 return m_fftModels[v].first; 1604 return m_fftModels[v].first;
1601 } 1605 }
1602 } 1606 }
1603 1607
2291 bool 2295 bool
2292 SpectrogramLayer::getDisplayExtents(float &min, float &max) const 2296 SpectrogramLayer::getDisplayExtents(float &min, float &max) const
2293 { 2297 {
2294 min = getEffectiveMinFrequency(); 2298 min = getEffectiveMinFrequency();
2295 max = getEffectiveMaxFrequency(); 2299 max = getEffectiveMaxFrequency();
2300 std::cerr << "SpectrogramLayer::getDisplayExtents: " << min << "->" << max << std::endl;
2296 return true; 2301 return true;
2297 } 2302 }
2298 2303
2299 bool 2304 bool
2300 SpectrogramLayer::setDisplayExtents(float min, float max) 2305 SpectrogramLayer::setDisplayExtents(float min, float max)
2301 { 2306 {
2302 if (!m_model) return false; 2307 if (!m_model) return false;
2308
2309 std::cerr << "SpectrogramLayer::setDisplayExtents: " << min << "->" << max << std::endl;
2310
2303 if (min < 0) min = 0; 2311 if (min < 0) min = 0;
2304 if (max > m_model->getSampleRate()/2) max = m_model->getSampleRate()/2; 2312 if (max > m_model->getSampleRate()/2) max = m_model->getSampleRate()/2;
2305 2313
2306 size_t minf = lrintf(min); 2314 size_t minf = lrintf(min);
2307 size_t maxf = lrintf(max); 2315 size_t maxf = lrintf(max);
2804 py = y; 2812 py = y;
2805 } 2813 }
2806 } 2814 }
2807 } 2815 }
2808 2816
2817 class SpectrogramRangeMapper : public RangeMapper
2818 {
2819 public:
2820 SpectrogramRangeMapper(int sr, int fftsize) :
2821 // m_dist((float(sr) / 2) - (float(sr) / fftsize)),
2822 m_dist(float(sr) / 2),
2823 m_s2(sqrtf(sqrtf(2))) { }
2824 ~SpectrogramRangeMapper() { }
2825
2826 virtual int getPositionForValue(float value) const {
2827
2828 float dist = m_dist;
2829
2830 int n = 0;
2831 int discard = 0;
2832
2833 while (dist > (value + 0.00001) && dist > 0.1f) {
2834 dist /= m_s2;
2835 ++n;
2836 }
2837
2838 return n;
2839 }
2840
2841 virtual float getValueForPosition(int position) const {
2842
2843 // Vertical zoom step 0 shows the entire range from DC ->
2844 // Nyquist frequency. Step 1 shows 2^(1/4) of the range of
2845 // step 0, and so on until the visible range is smaller than
2846 // the frequency step between bins at the current fft size.
2847
2848 float dist = m_dist;
2849
2850 int n = 0;
2851 while (n < position) {
2852 dist /= m_s2;
2853 ++n;
2854 }
2855
2856 return dist;
2857 }
2858
2859 virtual QString getUnit() const { return "Hz"; }
2860
2861 protected:
2862 float m_dist;
2863 float m_s2;
2864 };
2865
2809 int 2866 int
2810 SpectrogramLayer::getVerticalZoomSteps(int &defaultStep) const 2867 SpectrogramLayer::getVerticalZoomSteps(int &defaultStep) const
2811 { 2868 {
2812 // Vertical zoom step 0 shows the entire range from DC -> Nyquist
2813 // frequency. Step 1 shows 2^(1/4) of the range of step 0, and so
2814 // on until the visible range is smaller than the frequency step
2815 // between bins at the current fft size.
2816
2817 if (!m_model) return 0; 2869 if (!m_model) return 0;
2818 2870
2819 float min, max;
2820 int sr = m_model->getSampleRate(); 2871 int sr = m_model->getSampleRate();
2821 min = float(sr) / m_fftSize; 2872
2822 max = float(sr) / 2; 2873 SpectrogramRangeMapper mapper(sr, m_fftSize);
2823 2874
2824 float dist = max - min; 2875 // int maxStep = mapper.getPositionForValue((float(sr) / m_fftSize) + 0.001);
2825 2876 int maxStep = mapper.getPositionForValue(0);
2826 int n = 0; 2877 int minStep = mapper.getPositionForValue(float(sr) / 2);
2827 defaultStep = 0; 2878
2828 bool haveDefault = false; 2879 defaultStep = mapper.getPositionForValue(m_initialMaxFrequency) - minStep;
2829 float s2 = sqrtf(sqrtf(2)); 2880
2830 while (dist > min) { 2881 std::cerr << "SpectrogramLayer::getVerticalZoomSteps: " << maxStep - minStep << " (" << maxStep <<"-" << minStep << "), default is " << defaultStep << " (from initial max freq " << m_initialMaxFrequency << ")" << std::endl;
2831 if (!haveDefault && max <= m_initialMaxFrequency) { 2882
2832 defaultStep = n; 2883 return maxStep - minStep;
2833 haveDefault = true;
2834 }
2835 ++n;
2836 dist /= s2;
2837 max = min + dist;
2838 }
2839
2840 return n;
2841 } 2884 }
2842 2885
2843 int 2886 int
2844 SpectrogramLayer::getCurrentVerticalZoomStep() const 2887 SpectrogramLayer::getCurrentVerticalZoomStep() const
2845 { 2888 {
2846 if (!m_model) return 0; 2889 if (!m_model) return 0;
2847 2890
2848 float dmin, dmax; 2891 float dmin, dmax;
2849 getDisplayExtents(dmin, dmax); 2892 getDisplayExtents(dmin, dmax);
2850 2893
2851 float mmin, mmax; 2894 SpectrogramRangeMapper mapper(m_model->getSampleRate(), m_fftSize);
2852 int sr = m_model->getSampleRate(); 2895 int n = mapper.getPositionForValue(dmax - dmin);
2853 mmin = float(sr) / m_fftSize; 2896 std::cerr << "SpectrogramLayer::getCurrentVerticalZoomStep: " << n << std::endl;
2854 mmax = float(sr) / 2;
2855
2856 float mdist = mmax - mmin;
2857 float ddist = dmax - dmin;
2858
2859 int n = 0;
2860 int discard = 0;
2861 int m = getVerticalZoomSteps(discard);
2862 float s2 = sqrtf(sqrtf(2));
2863 while (mdist > ddist) {
2864 if (++n > m) break;
2865 mdist /= s2;
2866 }
2867
2868 return n; 2897 return n;
2869 } 2898 }
2870 2899
2871 void 2900 void
2872 SpectrogramLayer::setVerticalZoomStep(int step) 2901 SpectrogramLayer::setVerticalZoomStep(int step)
2873 { 2902 {
2874 //!!! does not do the right thing for log scale 2903 //!!! does not do the right thing for log scale
2904
2905 if (!m_model) return;
2875 2906
2876 float dmin, dmax; 2907 float dmin, dmax;
2877 getDisplayExtents(dmin, dmax); 2908 getDisplayExtents(dmin, dmax);
2878 2909
2879 float mmin, mmax;
2880 int sr = m_model->getSampleRate(); 2910 int sr = m_model->getSampleRate();
2881 mmin = float(sr) / m_fftSize; 2911 SpectrogramRangeMapper mapper(sr, m_fftSize);
2882 mmax = float(sr) / 2; 2912 float ddist = mapper.getValueForPosition(step);
2883
2884 float ddist = mmax - mmin;
2885
2886 int n = 0;
2887 float s2 = sqrtf(sqrtf(2));
2888 while (n < step) {
2889 ddist /= s2;
2890 ++n;
2891 }
2892 2913
2893 float dmid = (dmax + dmin) / 2; 2914 float dmid = (dmax + dmin) / 2;
2894 float newmin = dmid - ddist / 2; 2915 float newmin = dmid - ddist / 2;
2895 float newmax = dmid + ddist / 2; 2916 float newmax = dmid + ddist / 2;
2896 2917
2897 if (newmin < mmin) newmin = mmin; 2918 float mmin, mmax;
2898 if (newmax > mmax) newmax = mmax; 2919 mmin = 0;
2899 2920 mmax = float(sr) / 2;
2900 setMinFrequency(newmin); 2921
2901 setMaxFrequency(newmax); 2922 if (newmin < mmin) {
2923 newmax += (mmin - newmin);
2924 newmin = mmin;
2925 }
2926 if (newmax > mmax) {
2927 newmax = mmax;
2928 }
2929
2930 std::cerr << "SpectrogramLayer::setVerticalZoomStep: " << step << ": " << newmin << " -> " << newmax << " (range " << ddist << ")" << std::endl;
2931
2932 setMinFrequency(int(newmin));
2933 setMaxFrequency(int(newmax));
2934 }
2935
2936 RangeMapper *
2937 SpectrogramLayer::getNewVerticalZoomRangeMapper() const
2938 {
2939 if (!m_model) return 0;
2940 return new SpectrogramRangeMapper(m_model->getSampleRate(), m_fftSize);
2902 } 2941 }
2903 2942
2904 QString 2943 QString
2905 SpectrogramLayer::toXmlString(QString indent, QString extraAttributes) const 2944 SpectrogramLayer::toXmlString(QString indent, QString extraAttributes) const
2906 { 2945 {
2969 3008
2970 float threshold = attributes.value("threshold").toFloat(&ok); 3009 float threshold = attributes.value("threshold").toFloat(&ok);
2971 if (ok) setThreshold(threshold); 3010 if (ok) setThreshold(threshold);
2972 3011
2973 size_t minFrequency = attributes.value("minFrequency").toUInt(&ok); 3012 size_t minFrequency = attributes.value("minFrequency").toUInt(&ok);
2974 if (ok) setMinFrequency(minFrequency); 3013 if (ok) {
3014 std::cerr << "SpectrogramLayer::setProperties: setting min freq to " << minFrequency << std::endl;
3015 setMinFrequency(minFrequency);
3016 }
2975 3017
2976 size_t maxFrequency = attributes.value("maxFrequency").toUInt(&ok); 3018 size_t maxFrequency = attributes.value("maxFrequency").toUInt(&ok);
2977 if (ok) setMaxFrequency(maxFrequency); 3019 if (ok) {
3020 std::cerr << "SpectrogramLayer::setProperties: setting max freq to " << maxFrequency << std::endl;
3021 setMaxFrequency(maxFrequency);
3022 }
2978 3023
2979 ColourScale colourScale = (ColourScale) 3024 ColourScale colourScale = (ColourScale)
2980 attributes.value("colourScale").toInt(&ok); 3025 attributes.value("colourScale").toInt(&ok);
2981 if (ok) setColourScale(colourScale); 3026 if (ok) setColourScale(colourScale);
2982 3027