Chris@152: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@152: 
Chris@152: /*
Chris@152:     Sonic Visualiser
Chris@152:     An audio file viewer and annotation editor.
Chris@152:     Centre for Digital Music, Queen Mary, University of London.
Chris@202:     This file copyright 2006 Chris Cannam and QMUL.
Chris@152:     
Chris@152:     This program is free software; you can redistribute it and/or
Chris@152:     modify it under the terms of the GNU General Public License as
Chris@152:     published by the Free Software Foundation; either version 2 of the
Chris@152:     License, or (at your option) any later version.  See the file
Chris@152:     COPYING included with this distribution for more information.
Chris@152: */
Chris@152: 
Chris@152: #ifndef _EDITABLE_DENSE_THREE_DIMENSIONAL_MODEL_H_
Chris@152: #define _EDITABLE_DENSE_THREE_DIMENSIONAL_MODEL_H_
Chris@152: 
Chris@152: #include "DenseThreeDimensionalModel.h"
Chris@152: 
Chris@536: #include <QReadWriteLock>
Chris@536: 
Chris@533: #include <vector>
Chris@533: 
Chris@152: class EditableDenseThreeDimensionalModel : public DenseThreeDimensionalModel
Chris@152: {
Chris@152:     Q_OBJECT
Chris@152: 
Chris@152: public:
Chris@535: 
Chris@535:     // EditableDenseThreeDimensionalModel supports a basic compression
Chris@535:     // method that reduces the size of multirate data (e.g. wavelet
Chris@535:     // transform outputs) that are stored as plain 3d grids by about
Chris@535:     // 60% or thereabouts.  However, it can only be used for models
Chris@535:     // whose columns are set in order from 0 and never subsequently
Chris@535:     // changed.  If the model is going to be actually edited, it must
Chris@535:     // have NoCompression.
Chris@535: 
Chris@535:     enum CompressionType
Chris@535:     {
Chris@535:         NoCompression,
Chris@535:         BasicMultirateCompression
Chris@535:     };
Chris@535: 
Chris@1040:     EditableDenseThreeDimensionalModel(sv_samplerate_t sampleRate,
Chris@929: 				       int resolution,
Chris@1252: 				       int height,
Chris@535:                                        CompressionType compression,
Chris@152: 				       bool notifyOnAdd = true);
Chris@152: 
Chris@152:     virtual bool isOK() const;
Chris@152: 
Chris@1040:     virtual sv_samplerate_t getSampleRate() const;
Chris@1038:     virtual sv_frame_t getStartFrame() const;
Chris@1038:     virtual sv_frame_t getEndFrame() const;
Chris@152: 
Chris@152:     /**
Chris@611:      * Set the frame offset of the first column.
Chris@611:      */
Chris@1038:     virtual void setStartFrame(sv_frame_t);
Chris@611: 
Chris@611:     /**
Chris@152:      * Return the number of sample frames covered by each set of bins.
Chris@152:      */
Chris@929:     virtual int getResolution() const;
Chris@152: 
Chris@152:     /**
Chris@152:      * Set the number of sample frames covered by each set of bins.
Chris@152:      */
Chris@929:     virtual void setResolution(int sz);
Chris@152: 
Chris@152:     /**
Chris@182:      * Return the number of columns.
Chris@182:      */
Chris@929:     virtual int getWidth() const;
Chris@182: 
Chris@182:     /**
Chris@1252:      * Return the number of bins in each column.
Chris@152:      */
Chris@929:     virtual int getHeight() const; 
Chris@152: 
Chris@152:     /**
Chris@1252:      * Set the number of bins in each column.
Chris@1252:      *
Chris@1252:      * You can set (via setColumn) a vector of any length as a column,
Chris@1252:      * but any column being retrieved will be resized to this height
Chris@1252:      * (or the height that was supplied to the constructor, if this is
Chris@1252:      * never called) on retrieval. That is, the model owner determines
Chris@1252:      * the height of the model at a single stroke; the columns
Chris@1252:      * themselves don't have any effect on the height of the model.
Chris@152:      */
Chris@929:     virtual void setHeight(int sz);
Chris@152: 
Chris@152:     /**
Chris@152:      * Return the minimum value of the value in each bin.
Chris@152:      */
Chris@152:     virtual float getMinimumLevel() const;
Chris@152: 
Chris@152:     /**
Chris@152:      * Set the minimum value of the value in a bin.
Chris@152:      */
Chris@152:     virtual void setMinimumLevel(float sz);
Chris@152: 
Chris@152:     /**
Chris@152:      * Return the maximum value of the value in each bin.
Chris@152:      */
Chris@152:     virtual float getMaximumLevel() const;
Chris@152: 
Chris@152:     /**
Chris@152:      * Set the maximum value of the value in a bin.
Chris@152:      */
Chris@152:     virtual void setMaximumLevel(float sz);
Chris@152: 
Chris@182:     /**
Chris@182:      * Get the set of bin values at the given column.
Chris@152:      */
Chris@929:     virtual Column getColumn(int x) const;
Chris@152: 
Chris@152:     /**
Chris@182:      * Get a single value, from the n'th bin of the given column.
Chris@152:      */
Chris@929:     virtual float getValueAt(int x, int n) const;
Chris@152: 
Chris@152:     /**
Chris@182:      * Set the entire set of bin values at the given column.
Chris@152:      */
Chris@929:     virtual void setColumn(int x, const Column &values);
Chris@152: 
Chris@881:     /**
Chris@881:      * Return the name of bin n. This is a single label per bin that
Chris@881:      * does not vary from one column to the next.
Chris@881:      */
Chris@929:     virtual QString getBinName(int n) const;
Chris@881: 
Chris@881:     /**
Chris@881:      * Set the name of bin n.
Chris@881:      */
Chris@929:     virtual void setBinName(int n, QString);
Chris@881: 
Chris@881:     /**
Chris@881:      * Set the names of all bins.
Chris@881:      */
Chris@152:     virtual void setBinNames(std::vector<QString> names);
Chris@152: 
Chris@881:     /**
Chris@886:      * Return true if the bins have values as well as names. (The
Chris@886:      * values may have been derived from the names, e.g. by parsing
Chris@886:      * numbers from them.) If this returns true, getBinValue() may be
Chris@886:      * used to retrieve the values.
Chris@886:      */
Chris@886:     virtual bool hasBinValues() const;
Chris@886: 
Chris@886:     /**
Chris@886:      * Return the value of bin n, if any. This is a "vertical scale"
Chris@886:      * value which does not vary from one column to the next. This is
Chris@886:      * only meaningful if hasBinValues() returns true.
Chris@886:      */
Chris@929:     virtual float getBinValue(int n) const;
Chris@886: 
Chris@886:     /**
Chris@886:      * Set the values of all bins (separate from their labels). These
Chris@886:      * are "vertical scale" values which do not vary from one column
Chris@886:      * to the next.
Chris@886:      */
Chris@886:     virtual void setBinValues(std::vector<float> values);
Chris@886: 
Chris@886:     /**
Chris@886:      * Obtain the name of the unit of the values returned from
Chris@886:      * getBinValue(), if any.
Chris@886:      */
Chris@886:     virtual QString getBinValueUnit() const;
Chris@886: 
Chris@886:     /**
Chris@886:      * Set the name of the unit of the values return from
Chris@886:      * getBinValue() if any.
Chris@886:      */
Chris@886:     virtual void setBinValueUnit(QString unit);
Chris@886: 
Chris@886:     /**
Chris@881:      * Return true if the distribution of values in the bins is such
Chris@881:      * as to suggest a log scale (mapping to colour etc) may be better
Chris@881:      * than a linear one.
Chris@881:      */
Chris@478:     bool shouldUseLogValueScale() const;
Chris@478: 
Chris@333:     virtual void setCompletion(int completion, bool update = true);
Chris@152:     virtual int getCompletion() const { return m_completion; }
Chris@152: 
Chris@345:     QString getTypeName() const { return tr("Editable Dense 3-D"); }
Chris@345: 
Chris@318:     virtual QString toDelimitedDataString(QString delimiter) const;
Chris@1038:     virtual QString toDelimitedDataStringSubset(QString delimiter, sv_frame_t f0, sv_frame_t f1) const;
Chris@318: 
Chris@152:     virtual void toXml(QTextStream &out,
Chris@152:                        QString indent = "",
Chris@152:                        QString extraAttributes = "") const;
Chris@152: 
Chris@152: protected:
Chris@1154:     typedef std::vector<Column> ValueMatrix;
Chris@152:     ValueMatrix m_data;
Chris@152: 
Chris@535:     // m_trunc is used for simple compression.  If at least the top N
Chris@535:     // elements of column x (for N = some proportion of the column
Chris@535:     // height) are equal to those of an earlier column x', then
Chris@535:     // m_trunc[x] will contain x-x' and column x will be truncated so
Chris@535:     // as to remove the duplicate elements.  If the equal elements are
Chris@535:     // at the bottom, then m_trunc[x] will contain x'-x (a negative
Chris@535:     // value).  If m_trunc[x] is 0 then the whole of column x is
Chris@535:     // stored.
Chris@535:     std::vector<signed char> m_trunc;
Chris@929:     void truncateAndStore(int index, const Column & values);
Chris@929:     Column expandAndRetrieve(int index) const;
Chris@1252:     Column rightHeight(const Column &c) const;
Chris@534: 
Chris@152:     std::vector<QString> m_binNames;
Chris@886:     std::vector<float> m_binValues;
Chris@886:     QString m_binValueUnit;
Chris@152: 
Chris@1038:     sv_frame_t m_startFrame;
Chris@1040:     sv_samplerate_t m_sampleRate;
Chris@929:     int m_resolution;
Chris@929:     int m_yBinCount;
Chris@535:     CompressionType m_compression;
Chris@152:     float m_minimum;
Chris@152:     float m_maximum;
Chris@256:     bool m_haveExtents;
Chris@152:     bool m_notifyOnAdd;
Chris@1110:     sv_frame_t m_sinceLastNotifyMin;
Chris@1110:     sv_frame_t m_sinceLastNotifyMax;
Chris@152:     int m_completion;
Chris@152: 
Chris@536:     mutable QReadWriteLock m_lock;
Chris@152: };
Chris@152: 
Chris@152: #endif