annotate layer/SpectrogramLayer.h @ 299:5c59c433b358

* Show colour swatch next to layer name in pane (if available) * Fix for incorrect layer name prefix handling (was making some layers appear to have the same model name in cases where the model names differed by the final character only)
author Chris Cannam
date Wed, 05 Sep 2007 15:17:15 +0000
parents cd2492c5fe45
children c0b9eec70639
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@59 9 This program is free software; you can redistribute it and/or
Chris@59 10 modify it under the terms of the GNU General Public License as
Chris@59 11 published by the Free Software Foundation; either version 2 of the
Chris@59 12 License, or (at your option) any later version. See the file
Chris@59 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@30 16 #ifndef _SPECTROGRAM_LAYER_H_
Chris@30 17 #define _SPECTROGRAM_LAYER_H_
Chris@0 18
Chris@193 19 #include "SliceableLayer.h"
Chris@0 20 #include "base/Window.h"
Chris@71 21 #include "base/RealTime.h"
Chris@92 22 #include "base/Thread.h"
Chris@122 23 #include "base/PropertyContainer.h"
Chris@128 24 #include "data/model/PowerOfSqrtTwoZoomConstraint.h"
Chris@128 25 #include "data/model/DenseTimeValueModel.h"
Chris@130 26 #include "data/model/FFTModel.h"
Chris@0 27
Chris@0 28 #include <QMutex>
Chris@0 29 #include <QWaitCondition>
Chris@95 30 #include <QImage>
Chris@95 31 #include <QPixmap>
Chris@0 32
Chris@0 33 class View;
Chris@0 34 class QPainter;
Chris@0 35 class QImage;
Chris@0 36 class QPixmap;
Chris@0 37 class QTimer;
Chris@130 38 class FFTModel;
Chris@114 39
Chris@0 40
Chris@0 41 /**
Chris@0 42 * SpectrogramLayer represents waveform data (obtained from a
Chris@0 43 * DenseTimeValueModel) in spectrogram form.
Chris@0 44 */
Chris@0 45
Chris@193 46 class SpectrogramLayer : public SliceableLayer,
Chris@31 47 public PowerOfSqrtTwoZoomConstraint
Chris@0 48 {
Chris@0 49 Q_OBJECT
Chris@0 50
Chris@0 51 public:
Chris@37 52 enum Configuration { FullRangeDb, MelodicRange, MelodicPeaks };
Chris@0 53
Chris@44 54 SpectrogramLayer(Configuration = FullRangeDb);
Chris@0 55 ~SpectrogramLayer();
Chris@0 56
Chris@0 57 virtual const ZoomConstraint *getZoomConstraint() const { return this; }
Chris@0 58 virtual const Model *getModel() const { return m_model; }
Chris@44 59 virtual void paint(View *v, QPainter &paint, QRect rect) const;
Chris@0 60
Chris@44 61 virtual int getVerticalScaleWidth(View *v, QPainter &) const;
Chris@44 62 virtual void paintVerticalScale(View *v, QPainter &paint, QRect rect) const;
Chris@0 63
Chris@77 64 virtual bool getCrosshairExtents(View *, QPainter &, QPoint cursorPos,
Chris@77 65 std::vector<QRect> &extents) const;
Chris@77 66 virtual void paintCrosshairs(View *, QPainter &, QPoint) const;
Chris@77 67
Chris@44 68 virtual QString getFeatureDescription(View *v, QPoint &) const;
Chris@0 69
Chris@44 70 virtual bool snapToFeatureFrame(View *v, int &frame,
Chris@28 71 size_t &resolution,
Chris@28 72 SnapType snap) const;
Chris@13 73
Chris@283 74 virtual void measureDoubleClick(View *, QMouseEvent *);
Chris@283 75
Chris@224 76 virtual bool hasLightBackground() const;
Chris@224 77
Chris@0 78 void setModel(const DenseTimeValueModel *model);
Chris@0 79
Chris@0 80 virtual PropertyList getProperties() const;
Chris@87 81 virtual QString getPropertyLabel(const PropertyName &) const;
Chris@0 82 virtual PropertyType getPropertyType(const PropertyName &) const;
Chris@0 83 virtual QString getPropertyGroupName(const PropertyName &) const;
Chris@0 84 virtual int getPropertyRangeAndValue(const PropertyName &,
Chris@216 85 int *min, int *max, int *deflt) const;
Chris@0 86 virtual QString getPropertyValueLabel(const PropertyName &,
Chris@0 87 int value) const;
Chris@167 88 virtual RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const;
Chris@0 89 virtual void setProperty(const PropertyName &, int value);
Chris@0 90
Chris@0 91 /**
Chris@0 92 * Specify the channel to use from the source model.
Chris@0 93 * A value of -1 means to mix all available channels.
Chris@0 94 * The default is channel 0.
Chris@0 95 */
Chris@0 96 void setChannel(int);
Chris@0 97 int getChannel() const;
Chris@0 98
Chris@0 99 void setWindowSize(size_t);
Chris@0 100 size_t getWindowSize() const;
Chris@0 101
Chris@109 102 void setWindowHopLevel(size_t level);
Chris@97 103 size_t getWindowHopLevel() const;
Chris@0 104
Chris@0 105 void setWindowType(WindowType type);
Chris@0 106 WindowType getWindowType() const;
Chris@0 107
Chris@109 108 void setZeroPadLevel(size_t level);
Chris@109 109 size_t getZeroPadLevel() const;
Chris@109 110
Chris@0 111 /**
Chris@110 112 * Set the gain multiplier for sample values in this view.
Chris@0 113 * The default is 1.0.
Chris@0 114 */
Chris@0 115 void setGain(float gain);
Chris@0 116 float getGain() const;
Chris@0 117
Chris@37 118 /**
Chris@110 119 * Set the threshold for sample values to qualify for being shown
Chris@110 120 * in the FFT, in voltage units.
Chris@37 121 *
Chris@37 122 * The default is 0.0.
Chris@37 123 */
Chris@37 124 void setThreshold(float threshold);
Chris@37 125 float getThreshold() const;
Chris@37 126
Chris@37 127 void setMinFrequency(size_t);
Chris@37 128 size_t getMinFrequency() const;
Chris@37 129
Chris@0 130 void setMaxFrequency(size_t); // 0 -> no maximum
Chris@0 131 size_t getMaxFrequency() const;
Chris@0 132
Chris@37 133 enum ColourScale {
Chris@37 134 LinearColourScale,
Chris@37 135 MeterColourScale,
Chris@215 136 dBSquaredColourScale,
Chris@37 137 dBColourScale,
Chris@37 138 PhaseColourScale
Chris@37 139 };
Chris@0 140
Chris@0 141 /**
Chris@0 142 * Specify the scale for sample levels. See WaveformLayer for
Chris@0 143 * details of meter and dB scaling. The default is dBColourScale.
Chris@0 144 */
Chris@0 145 void setColourScale(ColourScale);
Chris@0 146 ColourScale getColourScale() const;
Chris@0 147
Chris@35 148 enum FrequencyScale {
Chris@35 149 LinearFrequencyScale,
Chris@35 150 LogFrequencyScale
Chris@35 151 };
Chris@0 152
Chris@0 153 /**
Chris@0 154 * Specify the scale for the y axis.
Chris@0 155 */
Chris@0 156 void setFrequencyScale(FrequencyScale);
Chris@0 157 FrequencyScale getFrequencyScale() const;
Chris@0 158
Chris@37 159 enum BinDisplay {
Chris@37 160 AllBins,
Chris@37 161 PeakBins,
Chris@37 162 PeakFrequencies
Chris@35 163 };
Chris@35 164
Chris@35 165 /**
Chris@35 166 * Specify the processing of frequency bins for the y axis.
Chris@35 167 */
Chris@37 168 void setBinDisplay(BinDisplay);
Chris@37 169 BinDisplay getBinDisplay() const;
Chris@35 170
Chris@36 171 void setNormalizeColumns(bool n);
Chris@36 172 bool getNormalizeColumns() const;
Chris@36 173
Chris@120 174 void setNormalizeVisibleArea(bool n);
Chris@120 175 bool getNormalizeVisibleArea() const;
Chris@120 176
Chris@197 177 void setColourMap(int map);
Chris@197 178 int getColourMap() const;
Chris@0 179
Chris@9 180 /**
Chris@9 181 * Specify the colourmap rotation for the colour scale.
Chris@9 182 */
Chris@9 183 void setColourRotation(int);
Chris@9 184 int getColourRotation() const;
Chris@9 185
Chris@0 186 virtual VerticalPosition getPreferredFrameCountPosition() const {
Chris@0 187 return PositionTop;
Chris@0 188 }
Chris@0 189
Chris@15 190 virtual bool isLayerOpaque() const { return true; }
Chris@287 191
Chris@287 192 virtual ColourSignificance getLayerColourSignificance() const {
Chris@287 193 return ColourHasMeaningfulValue;
Chris@287 194 }
Chris@15 195
Chris@267 196 float getYForFrequency(const View *v, float frequency) const;
Chris@267 197 float getFrequencyForY(const View *v, int y) const;
Chris@42 198
Chris@115 199 virtual int getCompletion(View *v) const;
Chris@0 200
Chris@101 201 virtual bool getValueExtents(float &min, float &max,
Chris@101 202 bool &logarithmic, QString &unit) const;
Chris@101 203
Chris@101 204 virtual bool getDisplayExtents(float &min, float &max) const;
Chris@79 205
Chris@120 206 virtual bool setDisplayExtents(float min, float max);
Chris@120 207
Chris@267 208 virtual bool getYScaleValue(const View *, int, float &, QString &) const;
Chris@261 209
Chris@6 210 virtual QString toXmlString(QString indent = "",
Chris@6 211 QString extraAttributes = "") const;
Chris@6 212
Chris@11 213 void setProperties(const QXmlAttributes &attributes);
Chris@11 214
Chris@47 215 virtual void setLayerDormant(const View *v, bool dormant);
Chris@29 216
Chris@248 217 virtual bool isLayerScrollable(const View *) const { return false; }
Chris@94 218
Chris@133 219 virtual int getVerticalZoomSteps(int &defaultStep) const;
Chris@133 220 virtual int getCurrentVerticalZoomStep() const;
Chris@133 221 virtual void setVerticalZoomStep(int);
Chris@187 222 virtual RangeMapper *getNewVerticalZoomRangeMapper() const;
Chris@133 223
Chris@193 224 virtual const Model *getSliceableModel() const;
Chris@193 225
Chris@0 226 protected slots:
Chris@0 227 void cacheInvalid();
Chris@0 228 void cacheInvalid(size_t startFrame, size_t endFrame);
Chris@122 229
Chris@122 230 void preferenceChanged(PropertyContainer::PropertyName name);
Chris@0 231
Chris@0 232 void fillTimerTimedOut();
Chris@0 233
Chris@0 234 protected:
Chris@0 235 const DenseTimeValueModel *m_model; // I do not own this
Chris@0 236
Chris@35 237 int m_channel;
Chris@35 238 size_t m_windowSize;
Chris@35 239 WindowType m_windowType;
Chris@97 240 size_t m_windowHopLevel;
Chris@109 241 size_t m_zeroPadLevel;
Chris@107 242 size_t m_fftSize;
Chris@35 243 float m_gain;
Chris@215 244 float m_initialGain;
Chris@37 245 float m_threshold;
Chris@215 246 float m_initialThreshold;
Chris@35 247 int m_colourRotation;
Chris@215 248 int m_initialRotation;
Chris@37 249 size_t m_minFrequency;
Chris@35 250 size_t m_maxFrequency;
Chris@135 251 size_t m_initialMaxFrequency;
Chris@35 252 ColourScale m_colourScale;
Chris@197 253 int m_colourMap;
Chris@77 254 QColor m_crosshairColour;
Chris@35 255 FrequencyScale m_frequencyScale;
Chris@37 256 BinDisplay m_binDisplay;
Chris@36 257 bool m_normalizeColumns;
Chris@120 258 bool m_normalizeVisibleArea;
Chris@133 259 int m_lastEmittedZoomStep;
Chris@0 260
Chris@215 261 mutable int m_lastPaintBlockWidth;
Chris@215 262 mutable RealTime m_lastPaintTime;
Chris@215 263
Chris@38 264 enum { NO_VALUE = 0 }; // colour index for unused pixels
Chris@38 265
Chris@197 266 class Palette
Chris@86 267 {
Chris@86 268 public:
Chris@86 269 QColor getColour(unsigned char index) const {
Chris@86 270 return m_colours[index];
Chris@86 271 }
Chris@86 272
Chris@86 273 void setColour(unsigned char index, QColor colour) {
Chris@86 274 m_colours[index] = colour;
Chris@86 275 }
Chris@86 276
Chris@86 277 private:
Chris@86 278 QColor m_colours[256];
Chris@86 279 };
Chris@86 280
Chris@197 281 Palette m_palette;
Chris@31 282
Chris@95 283 struct PixmapCache
Chris@95 284 {
Chris@95 285 QPixmap pixmap;
Chris@95 286 QRect validArea;
Chris@95 287 long startFrame;
Chris@95 288 size_t zoomLevel;
Chris@95 289 };
Chris@95 290 typedef std::map<const View *, PixmapCache> ViewPixmapCache;
Chris@95 291 void invalidatePixmapCaches();
Chris@95 292 void invalidatePixmapCaches(size_t startFrame, size_t endFrame);
Chris@95 293 mutable ViewPixmapCache m_pixmapCaches;
Chris@95 294 mutable QImage m_drawBuffer;
Chris@0 295
Chris@114 296 mutable QTimer *m_updateTimer;
Chris@110 297
Chris@44 298 mutable size_t m_candidateFillStartFrame;
Chris@0 299 bool m_exiting;
Chris@0 300
Chris@197 301 void initialisePalette();
Chris@197 302 void rotatePalette(int distance);
Chris@0 303
Chris@119 304 unsigned char getDisplayValue(View *v, float input) const;
Chris@40 305 float getInputForDisplayValue(unsigned char uc) const;
Chris@40 306
Chris@40 307 int getColourScaleWidth(QPainter &) const;
Chris@40 308
Chris@121 309 void illuminateLocalFeatures(View *v, QPainter &painter) const;
Chris@121 310
Chris@40 311 float getEffectiveMinFrequency() const;
Chris@40 312 float getEffectiveMaxFrequency() const;
Chris@38 313
Chris@0 314 struct LayerRange {
Chris@0 315 long startFrame;
Chris@0 316 int zoomLevel;
Chris@0 317 size_t modelStart;
Chris@0 318 size_t modelEnd;
Chris@0 319 };
Chris@44 320 bool getXBinRange(View *v, int x, float &windowMin, float &windowMax) const;
Chris@44 321 bool getYBinRange(View *v, int y, float &freqBinMin, float &freqBinMax) const;
Chris@0 322
Chris@44 323 bool getYBinSourceRange(View *v, int y, float &freqMin, float &freqMax) const;
Chris@44 324 bool getAdjustedYBinSourceRange(View *v, int x, int y,
Chris@35 325 float &freqMin, float &freqMax,
Chris@35 326 float &adjFreqMin, float &adjFreqMax) const;
Chris@44 327 bool getXBinSourceRange(View *v, int x, RealTime &timeMin, RealTime &timeMax) const;
Chris@44 328 bool getXYBinSourceRange(View *v, int x, int y, float &min, float &max,
Chris@38 329 float &phaseMin, float &phaseMax) const;
Chris@0 330
Chris@0 331 size_t getWindowIncrement() const {
Chris@97 332 if (m_windowHopLevel == 0) return m_windowSize;
Chris@97 333 else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4;
Chris@97 334 else return m_windowSize / (1 << (m_windowHopLevel - 1));
Chris@0 335 }
Chris@113 336
Chris@114 337 size_t getZeroPadLevel(const View *v) const;
Chris@114 338 size_t getFFTSize(const View *v) const;
Chris@130 339 FFTModel *getFFTModel(const View *v) const;
Chris@130 340 void invalidateFFTModels();
Chris@115 341
Chris@130 342 typedef std::pair<FFTModel *, int> FFTFillPair; // model, last fill
Chris@115 343 typedef std::map<const View *, FFTFillPair> ViewFFTMap;
Chris@119 344 typedef std::vector<float> FloatVector;
Chris@130 345 mutable ViewFFTMap m_fftModels;
Chris@193 346 mutable Model *m_sliceableModel;
Chris@119 347
Chris@119 348 class MagnitudeRange {
Chris@119 349 public:
Chris@119 350 MagnitudeRange() : m_min(0), m_max(0) { }
Chris@119 351 bool operator==(const MagnitudeRange &r) {
Chris@119 352 return r.m_min == m_min && r.m_max == m_max;
Chris@119 353 }
Chris@119 354 bool isSet() const { return (m_min != 0 || m_max != 0); }
Chris@119 355 void set(float min, float max) {
Chris@119 356 m_min = convert(min);
Chris@119 357 m_max = convert(max);
Chris@119 358 if (m_max < m_min) m_max = m_min;
Chris@119 359 }
Chris@119 360 bool sample(float f) {
Chris@119 361 unsigned int ui = convert(f);
Chris@119 362 bool changed = false;
Chris@119 363 if (isSet()) {
Chris@119 364 if (ui < m_min) { m_min = ui; changed = true; }
Chris@119 365 if (ui > m_max) { m_max = ui; changed = true; }
Chris@119 366 } else {
Chris@119 367 m_max = m_min = ui;
Chris@119 368 changed = true;
Chris@119 369 }
Chris@119 370 return changed;
Chris@119 371 }
Chris@119 372 bool sample(const MagnitudeRange &r) {
Chris@119 373 bool changed = false;
Chris@119 374 if (isSet()) {
Chris@119 375 if (r.m_min < m_min) { m_min = r.m_min; changed = true; }
Chris@119 376 if (r.m_max > m_max) { m_max = r.m_max; changed = true; }
Chris@119 377 } else {
Chris@119 378 m_min = r.m_min;
Chris@119 379 m_max = r.m_max;
Chris@119 380 changed = true;
Chris@119 381 }
Chris@119 382 return changed;
Chris@119 383 }
Chris@119 384 float getMin() const { return float(m_min) / UINT_MAX; }
Chris@119 385 float getMax() const { return float(m_max) / UINT_MAX; }
Chris@119 386 private:
Chris@119 387 unsigned int m_min;
Chris@119 388 unsigned int m_max;
Chris@119 389 unsigned int convert(float f) {
Chris@119 390 if (f < 0.f) f = 0.f;
Chris@119 391 if (f > 1.f) f = 1.f;
Chris@119 392 return (unsigned int)(f * UINT_MAX);
Chris@119 393 }
Chris@119 394 };
Chris@119 395
Chris@119 396 typedef std::map<const View *, MagnitudeRange> ViewMagMap;
Chris@119 397 mutable ViewMagMap m_viewMags;
Chris@119 398 mutable std::vector<MagnitudeRange> m_columnMags;
Chris@119 399 void invalidateMagnitudes();
Chris@119 400 bool updateViewMagnitudes(View *v) const;
Chris@273 401
Chris@273 402 virtual void updateMeasureRectYCoords(View *v, const MeasureRect &r) const;
Chris@273 403 virtual void setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const;
Chris@0 404 };
Chris@0 405
Chris@0 406 #endif