svgui  1.9
SpectrogramLayer.h
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #ifndef _SPECTROGRAM_LAYER_H_
17 #define _SPECTROGRAM_LAYER_H_
18 
19 #include "SliceableLayer.h"
20 #include "base/Window.h"
21 #include "base/RealTime.h"
22 #include "base/Thread.h"
23 #include "base/PropertyContainer.h"
24 #include "data/model/PowerOfSqrtTwoZoomConstraint.h"
25 #include "data/model/DenseTimeValueModel.h"
26 #include "data/model/FFTModel.h"
27 
28 #include <QMutex>
29 #include <QWaitCondition>
30 #include <QImage>
31 #include <QPixmap>
32 
33 class View;
34 class QPainter;
35 class QImage;
36 class QPixmap;
37 class QTimer;
38 class FFTModel;
39 class Dense3DModelPeakCache;
40 
41 
48  public PowerOfSqrtTwoZoomConstraint
49 {
50  Q_OBJECT
51 
52 public:
54 
57 
58  virtual const ZoomConstraint *getZoomConstraint() const { return this; }
59  virtual const Model *getModel() const { return m_model; }
60  virtual void paint(View *v, QPainter &paint, QRect rect) const;
61  virtual void setSynchronousPainting(bool synchronous);
62 
63  virtual int getVerticalScaleWidth(View *v, bool detailed, QPainter &) const;
64  virtual void paintVerticalScale(View *v, bool detailed, QPainter &paint, QRect rect) const;
65 
66  virtual bool getCrosshairExtents(View *, QPainter &, QPoint cursorPos,
67  std::vector<QRect> &extents) const;
68  virtual void paintCrosshairs(View *, QPainter &, QPoint) const;
69 
70  virtual QString getFeatureDescription(View *v, QPoint &) const;
71 
72  virtual bool snapToFeatureFrame(View *v, int &frame,
73  int &resolution,
74  SnapType snap) const;
75 
76  virtual void measureDoubleClick(View *, QMouseEvent *);
77 
78  virtual bool hasLightBackground() const;
79 
80  void setModel(const DenseTimeValueModel *model);
81 
82  virtual PropertyList getProperties() const;
83  virtual QString getPropertyLabel(const PropertyName &) const;
84  virtual QString getPropertyIconName(const PropertyName &) const;
85  virtual PropertyType getPropertyType(const PropertyName &) const;
86  virtual QString getPropertyGroupName(const PropertyName &) const;
87  virtual int getPropertyRangeAndValue(const PropertyName &,
88  int *min, int *max, int *deflt) const;
89  virtual QString getPropertyValueLabel(const PropertyName &,
90  int value) const;
91  virtual RangeMapper *getNewPropertyRangeMapper(const PropertyName &) const;
92  virtual void setProperty(const PropertyName &, int value);
93 
99  void setChannel(int);
100  int getChannel() const;
101 
102  void setWindowSize(int);
103  int getWindowSize() const;
104 
105  void setWindowHopLevel(int level);
106  int getWindowHopLevel() const;
107 
108  void setWindowType(WindowType type);
109  WindowType getWindowType() const;
110 
111  void setZeroPadLevel(int level);
112  int getZeroPadLevel() const;
113 
118  void setGain(float gain);
119  float getGain() const;
120 
127  void setThreshold(float threshold);
128  float getThreshold() const;
129 
130  void setMinFrequency(int);
131  int getMinFrequency() const;
132 
133  void setMaxFrequency(int); // 0 -> no maximum
134  int getMaxFrequency() const;
135 
136  enum ColourScale {
142  };
143 
149  ColourScale getColourScale() const;
150 
154  };
155 
161 
162  enum BinDisplay {
166  };
167 
172  BinDisplay getBinDisplay() const;
173 
178  void setNormalizeColumns(bool n);
179  bool getNormalizeColumns() const;
180 
184  void setNormalizeVisibleArea(bool n);
185  bool getNormalizeVisibleArea() const;
186 
191  void setNormalizeHybrid(bool n);
192  bool getNormalizeHybrid() const;
193 
194  void setColourMap(int map);
195  int getColourMap() const;
196 
200  void setColourRotation(int);
201  int getColourRotation() const;
202 
204  return PositionTop;
205  }
206 
207  virtual bool isLayerOpaque() const { return true; }
208 
211  }
212 
213  float getYForFrequency(const View *v, float frequency) const;
214  float getFrequencyForY(const View *v, int y) const;
215 
216  virtual int getCompletion(View *v) const;
217  virtual QString getError(View *v) const;
218 
219  virtual bool getValueExtents(float &min, float &max,
220  bool &logarithmic, QString &unit) const;
221 
222  virtual bool getDisplayExtents(float &min, float &max) const;
223 
224  virtual bool setDisplayExtents(float min, float max);
225 
226  virtual bool getYScaleValue(const View *, int, float &, QString &) const;
227 
228  virtual void toXml(QTextStream &stream, QString indent = "",
229  QString extraAttributes = "") const;
230 
231  void setProperties(const QXmlAttributes &attributes);
232 
233  virtual void setLayerDormant(const View *v, bool dormant);
234 
235  virtual bool isLayerScrollable(const View *) const { return false; }
236 
237  virtual int getVerticalZoomSteps(int &defaultStep) const;
238  virtual int getCurrentVerticalZoomStep() const;
239  virtual void setVerticalZoomStep(int);
240  virtual RangeMapper *getNewVerticalZoomRangeMapper() const;
241 
242  virtual const Model *getSliceableModel() const;
243 
244 protected slots:
245  void cacheInvalid();
246  void cacheInvalid(int startFrame, int endFrame);
247 
248  void preferenceChanged(PropertyContainer::PropertyName name);
249 
250  void fillTimerTimedOut();
251 
252 protected:
253  const DenseTimeValueModel *m_model; // I do not own this
254 
257  WindowType m_windowType;
261  float m_gain;
263  float m_threshold;
280 
281  mutable bool m_haveDetailedScale;
283  mutable RealTime m_lastPaintTime;
284 
285  enum { NO_VALUE = 0 }; // colour index for unused pixels
286 
287  class Palette
288  {
289  public:
290  QColor getColour(unsigned char index) const {
291  return m_colours[index];
292  }
293 
294  void setColour(unsigned char index, QColor colour) {
295  m_colours[index] = colour;
296  }
297 
298  private:
299  QColor m_colours[256];
300  };
301 
303 
309  struct ImageCache
310  {
311  QImage image;
312  QRect validArea;
315  };
316  typedef std::map<const View *, ImageCache> ViewImageCache;
317  void invalidateImageCaches();
318  void invalidateImageCaches(int startFrame, int endFrame);
320 
327  mutable QImage m_drawBuffer;
328 
329  mutable QTimer *m_updateTimer;
330 
332  bool m_exiting;
333 
334  void initialisePalette();
335  void rotatePalette(int distance);
336 
337  unsigned char getDisplayValue(View *v, float input) const;
338 
339  int getColourScaleWidth(QPainter &) const;
340 
341  void illuminateLocalFeatures(View *v, QPainter &painter) const;
342 
343  float getEffectiveMinFrequency() const;
344  float getEffectiveMaxFrequency() const;
345 
346  struct LayerRange {
350  int modelEnd;
351  };
352 
353  // Note that the getYBin... methods return the nominal bin in the
354  // un-smoothed spectrogram. This is not necessarily the same bin
355  // as is pulled from the spectrogram and drawn at the given
356  // position, if the spectrogram has oversampling smoothing. Use
357  // getSmoothedYBinRange to obtain that.
358 
359  bool getXBinRange(View *v, int x, float &windowMin, float &windowMax) const;
360  bool getYBinRange(View *v, int y, float &freqBinMin, float &freqBinMax) const;
361  bool getSmoothedYBinRange(View *v, int y, float &freqBinMin, float &freqBinMax) const;
362 
363  bool getYBinSourceRange(View *v, int y, float &freqMin, float &freqMax) const;
364  bool getAdjustedYBinSourceRange(View *v, int x, int y,
365  float &freqMin, float &freqMax,
366  float &adjFreqMin, float &adjFreqMax) const;
367  bool getXBinSourceRange(View *v, int x, RealTime &timeMin, RealTime &timeMax) const;
368  bool getXYBinSourceRange(View *v, int x, int y, float &min, float &max,
369  float &phaseMin, float &phaseMax) const;
370 
371  int getWindowIncrement() const {
372  if (m_windowHopLevel == 0) return m_windowSize;
373  else if (m_windowHopLevel == 1) return (m_windowSize * 3) / 4;
374  else return m_windowSize / (1 << (m_windowHopLevel - 1));
375  }
376 
377  int getZeroPadLevel(const View *v) const;
378  int getFFTSize(const View *v) const;
379  FFTModel *getFFTModel(const View *v) const;
380  Dense3DModelPeakCache *getPeakCache(const View *v) const;
381  void invalidateFFTModels();
382 
383  typedef std::pair<FFTModel *, int> FFTFillPair; // model, last fill
384  typedef std::map<const View *, FFTFillPair> ViewFFTMap;
385  typedef std::map<const View *, Dense3DModelPeakCache *> PeakCacheMap;
388  mutable Model *m_sliceableModel;
389 
391  public:
392  MagnitudeRange() : m_min(0), m_max(0) { }
393  bool operator==(const MagnitudeRange &r) {
394  return r.m_min == m_min && r.m_max == m_max;
395  }
396  bool isSet() const { return (m_min != 0 || m_max != 0); }
397  void set(float min, float max) {
398  m_min = convert(min);
399  m_max = convert(max);
400  if (m_max < m_min) m_max = m_min;
401  }
402  bool sample(float f) {
403  unsigned int ui = convert(f);
404  bool changed = false;
405  if (isSet()) {
406  if (ui < m_min) { m_min = ui; changed = true; }
407  if (ui > m_max) { m_max = ui; changed = true; }
408  } else {
409  m_max = m_min = ui;
410  changed = true;
411  }
412  return changed;
413  }
414  bool sample(const MagnitudeRange &r) {
415  bool changed = false;
416  if (isSet()) {
417  if (r.m_min < m_min) { m_min = r.m_min; changed = true; }
418  if (r.m_max > m_max) { m_max = r.m_max; changed = true; }
419  } else {
420  m_min = r.m_min;
421  m_max = r.m_max;
422  changed = true;
423  }
424  return changed;
425  }
426  float getMin() const { return float(m_min) / UINT_MAX; }
427  float getMax() const { return float(m_max) / UINT_MAX; }
428  private:
429  unsigned int m_min;
430  unsigned int m_max;
431  unsigned int convert(float f) {
432  if (f < 0.f) f = 0.f;
433  if (f > 1.f) f = 1.f;
434  return (unsigned int)(f * UINT_MAX);
435  }
436  };
437 
438  typedef std::map<const View *, MagnitudeRange> ViewMagMap;
440  mutable std::vector<MagnitudeRange> m_columnMags;
441  void invalidateMagnitudes();
442  bool updateViewMagnitudes(View *v) const;
443  bool paintDrawBuffer(View *v, int w, int h,
444  int *binforx, float *binfory,
445  bool usePeaksCache,
446  MagnitudeRange &overallMag,
447  bool &overallMagChanged) const;
448  bool paintDrawBufferPeakFrequencies(View *v, int w, int h,
449  int *binforx,
450  int minbin,
451  int maxbin,
452  float displayMinFreq,
453  float displayMaxFreq,
454  bool logarithmic,
455  MagnitudeRange &overallMag,
456  bool &overallMagChanged) const;
457 
458  virtual void updateMeasureRectYCoords(View *v, const MeasureRect &r) const;
459  virtual void setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const;
460 };
461 
462 #endif
ColourScale m_colourScale
void setChannel(int)
Specify the channel to use from the source model.
virtual bool snapToFeatureFrame(View *v, int &frame, int &resolution, SnapType snap) const
Adjust the given frame to snap to the nearest feature, if possible.
void setColourRotation(int)
Specify the colourmap rotation for the colour scale.
bool getNormalizeHybrid() const
virtual void measureDoubleClick(View *, QMouseEvent *)
FFTModel * getFFTModel(const View *v) const
virtual bool hasLightBackground() const
bool paintDrawBuffer(View *v, int w, int h, int *binforx, float *binfory, bool usePeaksCache, MagnitudeRange &overallMag, bool &overallMagChanged) const
SpectrogramLayer(Configuration=FullRangeDb)
virtual const Model * getSliceableModel() const
int getColourRotation() const
virtual void setVerticalZoomStep(int)
Set the vertical zoom step.
void illuminateLocalFeatures(View *v, QPainter &painter) const
std::map< const View *, Dense3DModelPeakCache * > PeakCacheMap
PeakCacheMap m_peakCaches
virtual const Model * getModel() const
SpectrogramLayer represents waveform data (obtained from a DenseTimeValueModel) in spectrogram form.
void setColourScale(ColourScale)
Specify the scale for sample levels.
virtual ColourSignificance getLayerColourSignificance() const
This should return the degree of meaning associated with colour in this layer.
bool getYBinRange(View *v, int y, float &freqBinMin, float &freqBinMax) const
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Convert the layer's data (though not those of the model it refers to) into XML for file output.
virtual void paintVerticalScale(View *v, bool detailed, QPainter &paint, QRect rect) const
virtual void paint(View *v, QPainter &paint, QRect rect) const
Paint the given rectangle of this layer onto the given view using the given painter,...
WindowType getWindowType() const
int getFFTSize(const View *v) const
void set(float min, float max)
bool getNormalizeVisibleArea() const
virtual int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const
ColourScale getColourScale() const
Dense3DModelPeakCache * getPeakCache(const View *v) const
virtual QString getPropertyGroupName(const PropertyName &) const
virtual int getCurrentVerticalZoomStep() const
Get the current vertical zoom step.
virtual void setProperty(const PropertyName &, int value)
void setThreshold(float threshold)
Set the threshold for sample values to qualify for being shown in the FFT, in voltage units.
virtual VerticalPosition getPreferredFrameCountPosition() const
bool getXBinRange(View *v, int x, float &windowMin, float &windowMax) const
std::map< const View *, MagnitudeRange > ViewMagMap
ColourSignificance
Definition: Layer.h:304
unsigned char getDisplayValue(View *v, float input) const
WindowType m_windowType
VerticalPosition
Definition: Layer.h:106
virtual PropertyList getProperties() const
void setWindowHopLevel(int level)
const DenseTimeValueModel * m_model
float getGain() const
void setProperties(const QXmlAttributes &attributes)
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
void setColourMap(int map)
virtual bool getYScaleValue(const View *, int, float &, QString &) const
Return the value and unit at the given y coordinate in the given view.
bool getAdjustedYBinSourceRange(View *v, int x, int y, float &freqMin, float &freqMax, float &adjFreqMin, float &adjFreqMax) const
virtual bool setDisplayExtents(float min, float max)
Set the displayed minimum and maximum values for the y axis to the given range, if supported.
bool getXYBinSourceRange(View *v, int x, int y, float &min, float &max, float &phaseMin, float &phaseMax) const
int getZeroPadLevel() const
virtual void setLayerDormant(const View *v, bool dormant)
Indicate that a layer is not currently visible in the given view and is not expected to become visibl...
std::pair< FFTModel *, int > FFTFillPair
virtual const ZoomConstraint * getZoomConstraint() const
Return a zoom constraint object defining the supported zoom levels for this layer.
bool getSmoothedYBinRange(View *v, int y, float &freqBinMin, float &freqBinMax) const
virtual int getVerticalZoomSteps(int &defaultStep) const
Get the number of vertical zoom steps available for this layer.
virtual QString getFeatureDescription(View *v, QPoint &) const
float getEffectiveMaxFrequency() const
virtual PropertyType getPropertyType(const PropertyName &) const
void setFrequencyScale(FrequencyScale)
Specify the scale for the y axis.
bool sample(const MagnitudeRange &r)
float getThreshold() const
virtual void setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const
int getColourScaleWidth(QPainter &) const
int getMinFrequency() const
BinDisplay m_binDisplay
FrequencyScale getFrequencyScale() const
SnapType
Definition: Layer.h:157
void preferenceChanged(PropertyContainer::PropertyName name)
bool updateViewMagnitudes(View *v) const
ViewFFTMap m_fftModels
virtual QString getError(View *v) const
Return an error string if any errors have occurred while loading or processing data for the given vie...
void setZeroPadLevel(int level)
ImageCache covers the area of the view, at view resolution.
virtual int getVerticalScaleWidth(View *v, bool detailed, QPainter &) const
virtual bool isLayerScrollable(const View *) const
This should return true if the layer can safely be scrolled automatically by a given view (simply cop...
bool getXBinSourceRange(View *v, int x, RealTime &timeMin, RealTime &timeMax) const
std::map< const View *, FFTFillPair > ViewFFTMap
virtual void paintCrosshairs(View *, QPainter &, QPoint) const
QImage m_drawBuffer
When painting, we draw directly onto the draw buffer and then copy this to the part of the image cach...
void setNormalizeHybrid(bool n)
Normalize each column to its maximum value, and then scale by the log of the (absolute) maximum value...
int getWindowSize() const
virtual bool getDisplayExtents(float &min, float &max) const
Return the minimum and maximum values within the displayed range for the y axis, if only a subset of ...
virtual QString getPropertyIconName(const PropertyName &) const
virtual QString getPropertyValueLabel(const PropertyName &, int value) const
BinDisplay getBinDisplay() const
float getEffectiveMinFrequency() const
bool getYBinSourceRange(View *v, int y, float &freqMin, float &freqMax) const
std::vector< MagnitudeRange > m_columnMags
virtual QString getPropertyLabel(const PropertyName &) const
void setNormalizeVisibleArea(bool n)
Normalize each value against the maximum in the visible region.
int getWindowHopLevel() const
View is the base class of widgets that display one or more overlaid views of data against a horizonta...
Definition: View.h:50
Base class for layers that can be sliced, that is, that contain models appropriate for use in a Slice...
virtual bool isLayerOpaque() const
This should return true if the layer completely obscures any underlying layers.
float getFrequencyForY(const View *v, int y) const
void setGain(float gain)
Set the gain multiplier for sample values in this view.
int getWindowIncrement() const
int getMaxFrequency() const
bool paintDrawBufferPeakFrequencies(View *v, int w, int h, int *binforx, int minbin, int maxbin, float displayMinFreq, float displayMaxFreq, bool logarithmic, MagnitudeRange &overallMag, bool &overallMagChanged) const
virtual void updateMeasureRectYCoords(View *v, const MeasureRect &r) const
virtual void setSynchronousPainting(bool synchronous)
Enable or disable synchronous painting.
float getYForFrequency(const View *v, float frequency) const
ViewImageCache m_imageCaches
std::map< const View *, ImageCache > ViewImageCache
bool operator==(const MagnitudeRange &r)
FrequencyScale m_frequencyScale
virtual bool getCrosshairExtents(View *, QPainter &, QPoint cursorPos, std::vector< QRect > &extents) const
QColor getColour(unsigned char index) const
void setModel(const DenseTimeValueModel *model)
void setColour(unsigned char index, QColor colour)
void setWindowType(WindowType type)
virtual RangeMapper * getNewVerticalZoomRangeMapper() const
Create and return a range mapper for vertical zoom step values.
void setNormalizeColumns(bool n)
Normalize each column to its maximum value, independent of its neighbours.
bool getNormalizeColumns() const
virtual int getCompletion(View *v) const
Return the proportion of background work complete in drawing this view, as a percentage – in most cas...
void setBinDisplay(BinDisplay)
Specify the processing of frequency bins for the y axis.
virtual RangeMapper * getNewPropertyRangeMapper(const PropertyName &) const
int getColourMap() const
void rotatePalette(int distance)
virtual bool getValueExtents(float &min, float &max, bool &logarithmic, QString &unit) const
Return the minimum and maximum values for the y axis of the model in this layer, as well as whether t...