Mercurial > hg > svgui
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 |