svgui
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam and QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #ifndef _SPECTROGRAM_LAYER_H_ 00017 #define _SPECTROGRAM_LAYER_H_ 00018 00019 #include "SliceableLayer.h" 00020 #include "base/Window.h" 00021 #include "base/RealTime.h" 00022 #include "base/Thread.h" 00023 #include "base/PropertyContainer.h" 00024 #include "data/model/PowerOfSqrtTwoZoomConstraint.h" 00025 #include "data/model/DenseTimeValueModel.h" 00026 #include "data/model/FFTModel.h" 00027 00028 #include <QMutex> 00029 #include <QWaitCondition> 00030 #include <QImage> 00031 #include <QPixmap> 00032 00033 class View; 00034 class QPainter; 00035 class QImage; 00036 class QPixmap; 00037 class QTimer; 00038 class FFTModel; 00039 class Dense3DModelPeakCache; 00040 00041 00047 class SpectrogramLayer : public SliceableLayer, 00048 public PowerOfSqrtTwoZoomConstraint 00049 { 00050 Q_OBJECT 00051 00052 public: 00053 enum Configuration { FullRangeDb, MelodicRange, MelodicPeaks }; 00054 00055 SpectrogramLayer(Configuration = FullRangeDb); 00056 ~SpectrogramLayer(); 00057 00058 virtual const ZoomConstraint *getZoomConstraint() const { return this; } 00059 virtual const Model *getModel() const { return m_model; } 00060 virtual void paint(View *v, QPainter &paint, QRect rect) const; 00061 virtual void setSynchronousPainting(bool synchronous); 00062 00063 virtual int getVerticalScaleWidth(View *v, bool detailed, QPainter &) const; 00064 virtual void paintVerticalScale(View *v, bool detailed, QPainter &paint, QRect rect) const; 00065 00066 virtual bool getCrosshairExtents(View *, QPainter &, QPoint cursorPos, 00067 std::vector<QRect> &extents) const; 00068 virtual void paintCrosshairs(View *, QPainter &, QPoint) const; 00069 00070 virtual QString getFeatureDescription(View *v, QPoint &) const; 00071 00072 virtual bool snapToFeatureFrame(View *v, int &frame, 00073 int &resolution, 00074 SnapType snap) const; 00075 00076 virtual void measureDoubleClick(View *, QMouseEvent *); 00077 00078 virtual bool hasLightBackground() const; 00079 00080 void setModel(const DenseTimeValueModel *model); 00081 00082 virtual PropertyList getProperties() const; 00083 virtual QString getPropertyLabel(const PropertyName &) const; 00084 virtual QString getPropertyIconName(const PropertyName &) const; 00085 virtual PropertyType getPropertyType(const PropertyName &) const; 00086 virtual QString getPropertyGroupName(const PropertyName &) const; 00087 virtual int getPropertyRangeAndValue(const PropertyName &, 00088 int *min, int *max, int *deflt) const; 00089 virtual QString getPropertyValueLabel(const PropertyName &, 00090 int value) const; 00091 virtual RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const; 00092 virtual void setProperty(const PropertyName &, int value); 00093 00099 void setChannel(int); 00100 int getChannel() const; 00101 00102 void setWindowSize(int); 00103 int getWindowSize() const; 00104 00105 void setWindowHopLevel(int level); 00106 int getWindowHopLevel() const; 00107 00108 void setWindowType(WindowType type); 00109 WindowType getWindowType() const; 00110 00111 void setZeroPadLevel(int level); 00112 int getZeroPadLevel() const; 00113 00118 void setGain(float gain); 00119 float getGain() const; 00120 00127 void setThreshold(float threshold); 00128 float getThreshold() const; 00129 00130 void setMinFrequency(int); 00131 int getMinFrequency() const; 00132 00133 void setMaxFrequency(int); // 0 -> no maximum 00134 int getMaxFrequency() const; 00135 00136 enum ColourScale { 00137 LinearColourScale, 00138 MeterColourScale, 00139 dBSquaredColourScale, 00140 dBColourScale, 00141 PhaseColourScale 00142 }; 00143 00148 void setColourScale(ColourScale); 00149 ColourScale getColourScale() const; 00150 00151 enum FrequencyScale { 00152 LinearFrequencyScale, 00153 LogFrequencyScale 00154 }; 00155 00159 void setFrequencyScale(FrequencyScale); 00160 FrequencyScale getFrequencyScale() const; 00161 00162 enum BinDisplay { 00163 AllBins, 00164 PeakBins, 00165 PeakFrequencies 00166 }; 00167 00171 void setBinDisplay(BinDisplay); 00172 BinDisplay getBinDisplay() const; 00173 00178 void setNormalizeColumns(bool n); 00179 bool getNormalizeColumns() const; 00180 00184 void setNormalizeVisibleArea(bool n); 00185 bool getNormalizeVisibleArea() const; 00186 00191 void setNormalizeHybrid(bool n); 00192 bool getNormalizeHybrid() const; 00193 00194 void setColourMap(int map); 00195 int getColourMap() const; 00196 00200 void setColourRotation(int); 00201 int getColourRotation() const; 00202 00203 virtual VerticalPosition getPreferredFrameCountPosition() const { 00204 return PositionTop; 00205 } 00206 00207 virtual bool isLayerOpaque() const { return true; } 00208 00209 virtual ColourSignificance getLayerColourSignificance() const { 00210 return ColourHasMeaningfulValue; 00211 } 00212 00213 float getYForFrequency(const View *v, float frequency) const; 00214 float getFrequencyForY(const View *v, int y) const; 00215 00216 virtual int getCompletion(View *v) const; 00217 virtual QString getError(View *v) const; 00218 00219 virtual bool getValueExtents(float &min, float &max, 00220 bool &logarithmic, QString &unit) const; 00221 00222 virtual bool getDisplayExtents(float &min, float &max) const; 00223 00224 virtual bool setDisplayExtents(float min, float max); 00225 00226 virtual bool getYScaleValue(const View *, int, float &, QString &) const; 00227 00228 virtual void toXml(QTextStream &stream, QString indent = "", 00229 QString extraAttributes = "") const; 00230 00231 void setProperties(const QXmlAttributes &attributes); 00232 00233 virtual void setLayerDormant(const View *v, bool dormant); 00234 00235 virtual bool isLayerScrollable(const View *) const { return false; } 00236 00237 virtual int getVerticalZoomSteps(int &defaultStep) const; 00238 virtual int getCurrentVerticalZoomStep() const; 00239 virtual void setVerticalZoomStep(int); 00240 virtual RangeMapper *getNewVerticalZoomRangeMapper() const; 00241 00242 virtual const Model *getSliceableModel() const; 00243 00244 protected slots: 00245 void cacheInvalid(); 00246 void cacheInvalid(int startFrame, int endFrame); 00247 00248 void preferenceChanged(PropertyContainer::PropertyName name); 00249 00250 void fillTimerTimedOut(); 00251 00252 protected: 00253 const DenseTimeValueModel *m_model; // I do not own this 00254 00255 int m_channel; 00256 int m_windowSize; 00257 WindowType m_windowType; 00258 int m_windowHopLevel; 00259 int m_zeroPadLevel; 00260 int m_fftSize; 00261 float m_gain; 00262 float m_initialGain; 00263 float m_threshold; 00264 float m_initialThreshold; 00265 int m_colourRotation; 00266 int m_initialRotation; 00267 int m_minFrequency; 00268 int m_maxFrequency; 00269 int m_initialMaxFrequency; 00270 ColourScale m_colourScale; 00271 int m_colourMap; 00272 QColor m_crosshairColour; 00273 FrequencyScale m_frequencyScale; 00274 BinDisplay m_binDisplay; 00275 bool m_normalizeColumns; 00276 bool m_normalizeVisibleArea; 00277 bool m_normalizeHybrid; 00278 int m_lastEmittedZoomStep; 00279 bool m_synchronous; 00280 00281 mutable bool m_haveDetailedScale; 00282 mutable int m_lastPaintBlockWidth; 00283 mutable RealTime m_lastPaintTime; 00284 00285 enum { NO_VALUE = 0 }; // colour index for unused pixels 00286 00287 class Palette 00288 { 00289 public: 00290 QColor getColour(unsigned char index) const { 00291 return m_colours[index]; 00292 } 00293 00294 void setColour(unsigned char index, QColor colour) { 00295 m_colours[index] = colour; 00296 } 00297 00298 private: 00299 QColor m_colours[256]; 00300 }; 00301 00302 Palette m_palette; 00303 00309 struct ImageCache 00310 { 00311 QImage image; 00312 QRect validArea; 00313 int startFrame; 00314 int zoomLevel; 00315 }; 00316 typedef std::map<const View *, ImageCache> ViewImageCache; 00317 void invalidateImageCaches(); 00318 void invalidateImageCaches(int startFrame, int endFrame); 00319 mutable ViewImageCache m_imageCaches; 00320 00327 mutable QImage m_drawBuffer; 00328 00329 mutable QTimer *m_updateTimer; 00330 00331 mutable int m_candidateFillStartFrame; 00332 bool m_exiting; 00333 00334 void initialisePalette(); 00335 void rotatePalette(int distance); 00336 00337 unsigned char getDisplayValue(View *v, float input) const; 00338 00339 int getColourScaleWidth(QPainter &) const; 00340 00341 void illuminateLocalFeatures(View *v, QPainter &painter) const; 00342 00343 float getEffectiveMinFrequency() const; 00344 float getEffectiveMaxFrequency() const; 00345 00346 struct LayerRange { 00347 int startFrame; 00348 int zoomLevel; 00349 int modelStart; 00350 int modelEnd; 00351 }; 00352 00353 // Note that the getYBin... methods return the nominal bin in the 00354 // un-smoothed spectrogram. This is not necessarily the same bin 00355 // as is pulled from the spectrogram and drawn at the given 00356 // position, if the spectrogram has oversampling smoothing. Use 00357 // getSmoothedYBinRange to obtain that. 00358 00359 bool getXBinRange(View *v, int x, float &windowMin, float &windowMax) const; 00360 bool getYBinRange(View *v, int y, float &freqBinMin, float &freqBinMax) const; 00361 bool getSmoothedYBinRange(View *v, int y, float &freqBinMin, float &freqBinMax) const; 00362 00363 bool getYBinSourceRange(View *v, int y, float &freqMin, float &freqMax) const; 00364 bool getAdjustedYBinSourceRange(View *v, int x, int y, 00365 float &freqMin, float &freqMax, 00366 float &adjFreqMin, float &adjFreqMax) const; 00367 bool getXBinSourceRange(View *v, int x, RealTime &timeMin, RealTime &timeMax) const; 00368 bool getXYBinSourceRange(View *v, int x, int y, float &min, float &max, 00369 float &phaseMin, float &phaseMax) const; 00370 00371 int getWindowIncrement() const { 00372 if (m_windowHopLevel == 0) return m_windowSize; 00373 else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4; 00374 else return m_windowSize / (1 << (m_windowHopLevel - 1)); 00375 } 00376 00377 int getZeroPadLevel(const View *v) const; 00378 int getFFTSize(const View *v) const; 00379 FFTModel *getFFTModel(const View *v) const; 00380 Dense3DModelPeakCache *getPeakCache(const View *v) const; 00381 void invalidateFFTModels(); 00382 00383 typedef std::pair<FFTModel *, int> FFTFillPair; // model, last fill 00384 typedef std::map<const View *, FFTFillPair> ViewFFTMap; 00385 typedef std::map<const View *, Dense3DModelPeakCache *> PeakCacheMap; 00386 mutable ViewFFTMap m_fftModels; 00387 mutable PeakCacheMap m_peakCaches; 00388 mutable Model *m_sliceableModel; 00389 00390 class MagnitudeRange { 00391 public: 00392 MagnitudeRange() : m_min(0), m_max(0) { } 00393 bool operator==(const MagnitudeRange &r) { 00394 return r.m_min == m_min && r.m_max == m_max; 00395 } 00396 bool isSet() const { return (m_min != 0 || m_max != 0); } 00397 void set(float min, float max) { 00398 m_min = convert(min); 00399 m_max = convert(max); 00400 if (m_max < m_min) m_max = m_min; 00401 } 00402 bool sample(float f) { 00403 unsigned int ui = convert(f); 00404 bool changed = false; 00405 if (isSet()) { 00406 if (ui < m_min) { m_min = ui; changed = true; } 00407 if (ui > m_max) { m_max = ui; changed = true; } 00408 } else { 00409 m_max = m_min = ui; 00410 changed = true; 00411 } 00412 return changed; 00413 } 00414 bool sample(const MagnitudeRange &r) { 00415 bool changed = false; 00416 if (isSet()) { 00417 if (r.m_min < m_min) { m_min = r.m_min; changed = true; } 00418 if (r.m_max > m_max) { m_max = r.m_max; changed = true; } 00419 } else { 00420 m_min = r.m_min; 00421 m_max = r.m_max; 00422 changed = true; 00423 } 00424 return changed; 00425 } 00426 float getMin() const { return float(m_min) / UINT_MAX; } 00427 float getMax() const { return float(m_max) / UINT_MAX; } 00428 private: 00429 unsigned int m_min; 00430 unsigned int m_max; 00431 unsigned int convert(float f) { 00432 if (f < 0.f) f = 0.f; 00433 if (f > 1.f) f = 1.f; 00434 return (unsigned int)(f * UINT_MAX); 00435 } 00436 }; 00437 00438 typedef std::map<const View *, MagnitudeRange> ViewMagMap; 00439 mutable ViewMagMap m_viewMags; 00440 mutable std::vector<MagnitudeRange> m_columnMags; 00441 void invalidateMagnitudes(); 00442 bool updateViewMagnitudes(View *v) const; 00443 bool paintDrawBuffer(View *v, int w, int h, 00444 int *binforx, float *binfory, 00445 bool usePeaksCache, 00446 MagnitudeRange &overallMag, 00447 bool &overallMagChanged) const; 00448 bool paintDrawBufferPeakFrequencies(View *v, int w, int h, 00449 int *binforx, 00450 int minbin, 00451 int maxbin, 00452 float displayMinFreq, 00453 float displayMaxFreq, 00454 bool logarithmic, 00455 MagnitudeRange &overallMag, 00456 bool &overallMagChanged) const; 00457 00458 virtual void updateMeasureRectYCoords(View *v, const MeasureRect &r) const; 00459 virtual void setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const; 00460 }; 00461 00462 #endif