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