Chris@147: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@147: 
Chris@147: /*
Chris@147:     Sonic Visualiser
Chris@147:     An audio file viewer and annotation editor.
Chris@147:     Centre for Digital Music, Queen Mary, University of London.
Chris@202:     This file copyright 2006 Chris Cannam and QMUL.
Chris@147:     
Chris@147:     This program is free software; you can redistribute it and/or
Chris@147:     modify it under the terms of the GNU General Public License as
Chris@147:     published by the Free Software Foundation; either version 2 of the
Chris@147:     License, or (at your option) any later version.  See the file
Chris@147:     COPYING included with this distribution for more information.
Chris@147: */
Chris@147: 
Chris@147: #ifndef _DENSE_THREE_DIMENSIONAL_MODEL_H_
Chris@147: #define _DENSE_THREE_DIMENSIONAL_MODEL_H_
Chris@147: 
Chris@150: #include "Model.h"
Chris@500: #include "TabularModel.h"
Chris@147: #include "base/ZoomConstraint.h"
Chris@500: #include "base/RealTime.h"
Chris@147: 
Chris@147: #include <QMutex>
Chris@533: #include <QVector>
Chris@147: 
Chris@500: class DenseThreeDimensionalModel : public Model,
Chris@500:                                    public TabularModel
Chris@147: {
Chris@147:     Q_OBJECT
Chris@147: 
Chris@147: public:
Chris@147:     /**
Chris@182:      * Return the number of sample frames covered by each column of bins.
Chris@147:      */
Chris@929:     virtual int getResolution() const = 0;
Chris@147: 
Chris@147:     /**
Chris@182:      * Return the number of columns of bins in the model.
Chris@147:      */
Chris@929:     virtual int getWidth() const = 0;
Chris@147: 
Chris@147:     /**
Chris@182:      * Return the number of bins in each column.
Chris@182:      */
Chris@929:     virtual int getHeight() const = 0; 
Chris@182: 
Chris@182:     /**
Chris@182:      * Return the minimum permissible value in each bin.
Chris@147:      */
Chris@152:     virtual float getMinimumLevel() const = 0;
Chris@147: 
Chris@147:     /**
Chris@182:      * Return the maximum permissible value in each bin.
Chris@147:      */
Chris@152:     virtual float getMaximumLevel() const = 0;
Chris@147: 
Chris@182:     /**
Chris@182:      * Return true if there are data available for the given column.
Chris@223:      * This should return true only if getColumn(column) would not
Chris@223:      * have to do any substantial work to calculate its return values.
Chris@223:      * If this function returns false, it may still be possible to
Chris@223:      * retrieve the column, but its values may have to be calculated.
Chris@182:      */
Chris@929:     virtual bool isColumnAvailable(int column) const = 0;
Chris@182: 
Chris@533:     typedef QVector<float> Column;
Chris@147: 
Chris@147:     /**
Chris@182:      * Get data from the given column of bin values.
Chris@147:      */
Chris@929:     virtual Column getColumn(int column) const = 0;
Chris@147: 
Chris@147:     /**
Chris@182:      * Get the single data point from the n'th bin of the given column.
Chris@147:      */
Chris@929:     virtual float getValueAt(int column, int n) const = 0;
Chris@147: 
Chris@182:     /**
Chris@182:      * Get the name of a given bin (i.e. a label to associate with
Chris@182:      * that bin across all columns).
Chris@182:      */
Chris@929:     virtual QString getBinName(int n) const = 0;
Chris@147: 
Chris@182:     /**
Chris@887:      * Return true if the bins have values as well as names. If this
Chris@887:      * returns true, getBinValue() may be used to retrieve the values.
Chris@887:      */
Chris@887:     virtual bool hasBinValues() const { return false; }
Chris@887: 
Chris@887:     /**
Chris@887:      * Return the value of bin n, if any. This is a "vertical scale"
Chris@887:      * value which does not vary from one column to the next. This is
Chris@887:      * only meaningful if hasBinValues() returns true.
Chris@887:      */
Chris@1038:     virtual float getBinValue(int n) const { return float(n); }
Chris@887: 
Chris@887:     /**
Chris@887:      * Obtain the name of the unit of the values returned from
Chris@887:      * getBinValue(), if any.
Chris@887:      */
Chris@887:     virtual QString getBinValueUnit() const { return ""; }
Chris@887: 
Chris@887:     /**
Chris@478:      * Estimate whether a logarithmic scale might be appropriate for
Chris@478:      * the value scale.
Chris@478:      */
Chris@478:     virtual bool shouldUseLogValueScale() const = 0;
Chris@478: 
Chris@478:     /**
Chris@182:      * Utility function to query whether a given bin is greater than
Chris@182:      * its (vertical) neighbours.
Chris@182:      */
Chris@929:     bool isLocalPeak(int x, int y) {
Chris@182:         float value = getValueAt(x, y);
Chris@182:         if (y > 0 && value < getValueAt(x, y - 1)) return false;
Chris@182:         if (y < getHeight() - 1 && value < getValueAt(x, y + 1)) return false;
Chris@182:         return true;
Chris@182:     }
Chris@182: 
Chris@182:     /**
Chris@182:      * Utility function to query whether a given bin is greater than a
Chris@182:      * certain threshold.
Chris@182:      */
Chris@929:     bool isOverThreshold(int x, int y, float threshold) {
Chris@182:         return getValueAt(x, y) > threshold;
Chris@182:     }
Chris@182: 
Chris@345:     QString getTypeName() const { return tr("Dense 3-D"); }
Chris@345: 
Chris@152:     virtual int getCompletion() const = 0;
Chris@147: 
Chris@500:     /*
Chris@500:        TabularModel methods.
Chris@500:        This class is non-editable -- subclasses may be editable.
Chris@500:        Row and column are transposed for the tabular view (which is
Chris@500:        "on its side").
Chris@500:      */
Chris@500:     
Chris@500:     virtual int getRowCount() const { return getWidth(); }
Chris@500:     virtual int getColumnCount() const { return getHeight() + 2; }
Chris@500: 
Chris@500:     virtual QString getHeading(int column) const
Chris@500:     {
Chris@500:         switch (column) {
Chris@500:         case 0: return tr("Time");
Chris@500:         case 1: return tr("Frame");
Chris@500:         default: return getBinName(column - 2);
Chris@500:         }
Chris@500:     }
Chris@500: 
Chris@568:     virtual QVariant getData(int row, int column, int) const 
Chris@500:     {
Chris@500:         switch (column) {
Chris@500:         case 0: {
Chris@500:             RealTime rt = RealTime::frame2RealTime(row * getResolution(),
Chris@500:                                                    getSampleRate());
Chris@500:             return rt.toText().c_str();
Chris@500:         }
Chris@500:         case 1:
Chris@500:             return int(row * getResolution());
Chris@500:         default:
Chris@500:             return getValueAt(row, column - 2);
Chris@500:         }
Chris@500:     }
Chris@500: 
Chris@500:     virtual bool isColumnTimeValue(int col) const {
Chris@500:         return col < 2;
Chris@500:     }
Chris@568:     virtual SortType getSortType(int) const {
Chris@500:         return SortNumeric;
Chris@500:     }
Chris@500: 
Chris@1038:     virtual sv_frame_t getFrameForRow(int row) const {
Chris@1038:         return sv_frame_t(row) * getResolution();
Chris@500:     }
Chris@1038:     virtual int getRowForFrame(sv_frame_t frame) const {
Chris@1038:         return int(frame / getResolution());
Chris@500:     }
Chris@500: 
Chris@147: protected:
Chris@152:     DenseThreeDimensionalModel() { }
Chris@147: };
Chris@147: 
Chris@147: #endif