annotate data/model/Model.h @ 1008:d9e0e59a1581

When using an aggregate model to pass data to a transform, zero-pad the shorter input to the duration of the longer rather than truncating the longer. (This is better behaviour for e.g. MATCH, and in any case the code was previously truncating incorrectly and ending up with garbage data at the end.)
author Chris Cannam
date Fri, 14 Nov 2014 13:51:33 +0000
parents d03b3d956358
children cc27f35aa75c
rev   line source
Chris@150 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@150 2
Chris@150 3 /*
Chris@150 4 Sonic Visualiser
Chris@150 5 An audio file viewer and annotation editor.
Chris@150 6 Centre for Digital Music, Queen Mary, University of London.
Chris@150 7 This file copyright 2006 Chris Cannam.
Chris@150 8
Chris@150 9 This program is free software; you can redistribute it and/or
Chris@150 10 modify it under the terms of the GNU General Public License as
Chris@150 11 published by the Free Software Foundation; either version 2 of the
Chris@150 12 License, or (at your option) any later version. See the file
Chris@150 13 COPYING included with this distribution for more information.
Chris@150 14 */
Chris@150 15
Chris@150 16 #ifndef _MODEL_H_
Chris@150 17 #define _MODEL_H_
Chris@150 18
Chris@150 19 #include <vector>
Chris@150 20 #include <QObject>
Chris@150 21
Chris@150 22 #include "base/XmlExportable.h"
Chris@391 23 #include "base/Playable.h"
Chris@150 24
Chris@290 25 typedef std::vector<float> SampleBlock;
Chris@290 26
Chris@179 27 class ZoomConstraint;
Chris@319 28 class AlignmentModel;
Chris@179 29
Chris@150 30 /**
Chris@150 31 * Model is the base class for all data models that represent any sort
Chris@150 32 * of data on a time scale based on an audio frame rate.
Chris@150 33 */
Chris@150 34
Chris@179 35 class Model : public QObject,
Chris@391 36 public XmlExportable,
Chris@391 37 public Playable
Chris@150 38 {
Chris@150 39 Q_OBJECT
Chris@150 40
Chris@150 41 public:
Chris@150 42 virtual ~Model();
Chris@150 43
Chris@150 44 /**
Chris@150 45 * Return true if the model was constructed successfully. Classes
Chris@150 46 * that refer to the model should always test this before use.
Chris@150 47 */
Chris@150 48 virtual bool isOK() const = 0;
Chris@150 49
Chris@150 50 /**
Chris@150 51 * Return the first audio frame spanned by the model.
Chris@150 52 */
Chris@929 53 virtual int getStartFrame() const = 0;
Chris@150 54
Chris@150 55 /**
Chris@150 56 * Return the last audio frame spanned by the model.
Chris@150 57 */
Chris@929 58 virtual int getEndFrame() const = 0;
Chris@150 59
Chris@150 60 /**
Chris@150 61 * Return the frame rate in frames per second.
Chris@150 62 */
Chris@929 63 virtual int getSampleRate() const = 0;
Chris@150 64
Chris@150 65 /**
Chris@297 66 * Return the frame rate of the underlying material, if the model
Chris@297 67 * itself has already been resampled.
Chris@297 68 */
Chris@929 69 virtual int getNativeRate() const { return getSampleRate(); }
Chris@297 70
Chris@297 71 /**
Chris@333 72 * Return the "work title" of the model, if known.
Chris@333 73 */
Chris@333 74 virtual QString getTitle() const;
Chris@333 75
Chris@333 76 /**
Chris@333 77 * Return the "artist" or "maker" of the model, if known.
Chris@333 78 */
Chris@333 79 virtual QString getMaker() const;
Chris@333 80
Chris@333 81 /**
Chris@345 82 * Return the location of the data in this model (e.g. source
Chris@345 83 * URL). This should not normally be returned for editable models
Chris@345 84 * that have been edited.
Chris@345 85 */
Chris@345 86 virtual QString getLocation() const;
Chris@345 87
Chris@345 88 /**
Chris@345 89 * Return the type of the model. For display purposes only.
Chris@345 90 */
Chris@345 91 virtual QString getTypeName() const = 0;
Chris@345 92
Chris@345 93 /**
Chris@150 94 * Return a copy of this model.
Chris@150 95 *
Chris@150 96 * If the model is not editable, this may be effectively a shallow
Chris@150 97 * copy. If the model is editable, however, this operation must
Chris@150 98 * properly copy all of the model's editable data.
Chris@150 99 *
Chris@150 100 * In general this operation is not useful for non-editable dense
Chris@150 101 * models such as waveforms, because there may be no efficient
Chris@150 102 * copy operation implemented -- for such models it is better not
Chris@150 103 * to copy at all.
Chris@150 104 *
Chris@150 105 * Caller owns the returned value.
Chris@150 106 */
Chris@150 107 virtual Model *clone() const = 0;
Chris@923 108
Chris@923 109 /**
Chris@923 110 * Mark the model as abandoning. This means that the application
Chris@923 111 * no longer needs it, so it can stop doing any background
Chris@923 112 * calculations it may be involved in. Note that as far as the
Chris@923 113 * model API is concerned, this does nothing more than tell the
Chris@923 114 * model to return true from isAbandoning(). The actual response
Chris@923 115 * to this will depend on the model's context -- it's possible
Chris@923 116 * nothing at all will change.
Chris@923 117 */
Chris@923 118 virtual void abandon() {
Chris@923 119 m_abandoning = true;
Chris@923 120 }
Chris@923 121
Chris@923 122 /**
Chris@923 123 * Query whether the model has been marked as abandoning.
Chris@923 124 */
Chris@923 125 virtual bool isAbandoning() const {
Chris@923 126 return m_abandoning;
Chris@923 127 }
Chris@923 128
Chris@150 129 /**
Chris@150 130 * Return true if the model has finished loading or calculating
Chris@150 131 * all its data, for a model that is capable of calculating in a
Chris@150 132 * background thread. The default implementation is appropriate
Chris@150 133 * for a thread that does not background any work but carries out
Chris@150 134 * all its calculation from the constructor or accessors.
Chris@150 135 *
Chris@150 136 * If "completion" is non-NULL, this function should return
Chris@150 137 * through it an estimated percentage value showing how far
Chris@150 138 * through the background operation it thinks it is (for progress
Chris@150 139 * reporting). If it has no way to calculate progress, it may
Chris@150 140 * return the special value COMPLETION_UNKNOWN.
Chris@150 141 */
Chris@150 142 virtual bool isReady(int *completion = 0) const {
Chris@150 143 bool ok = isOK();
Chris@150 144 if (completion) *completion = (ok ? 100 : 0);
Chris@150 145 return ok;
Chris@150 146 }
Chris@150 147 static const int COMPLETION_UNKNOWN;
Chris@150 148
Chris@179 149 /**
Chris@179 150 * If this model imposes a zoom constraint, i.e. some limit to the
Chris@179 151 * set of resolutions at which its data can meaningfully be
Chris@179 152 * displayed, then return it.
Chris@179 153 */
Chris@179 154 virtual const ZoomConstraint *getZoomConstraint() const {
Chris@179 155 return 0;
Chris@179 156 }
Chris@179 157
Chris@297 158 /**
Chris@297 159 * If this model was derived from another, return the model it was
Chris@297 160 * derived from. The assumption is that the source model's
Chris@297 161 * alignment will also apply to this model, unless some other
Chris@319 162 * property (such as a specific alignment model set on this model)
Chris@319 163 * indicates otherwise.
Chris@297 164 */
Chris@297 165 virtual Model *getSourceModel() const {
Chris@297 166 return m_sourceModel;
Chris@297 167 }
Chris@297 168
Chris@297 169 /**
Chris@297 170 * Set the source model for this model.
Chris@297 171 */
Chris@319 172 virtual void setSourceModel(Model *model);
Chris@319 173
Chris@319 174 /**
Chris@319 175 * Specify an aligment between this model's timeline and that of a
Chris@319 176 * reference model. The alignment model records both the
Chris@319 177 * reference and the alignment. This model takes ownership of the
Chris@319 178 * alignment model.
Chris@319 179 */
Chris@319 180 virtual void setAlignment(AlignmentModel *alignment);
Chris@319 181
Chris@319 182 /**
Chris@407 183 * Retrieve the alignment model for this model. This is not a
Chris@407 184 * generally useful function, as the alignment you really want may
Chris@407 185 * be performed by the source model instead. You should normally
Chris@407 186 * use getAlignmentReference, alignToReference and
Chris@407 187 * alignFromReference instead of this. The main intended
Chris@407 188 * application for this function is in streaming out alignments to
Chris@407 189 * the session file.
Chris@407 190 */
Chris@407 191 virtual const AlignmentModel *getAlignment() const;
Chris@407 192
Chris@407 193 /**
Chris@319 194 * Return the reference model for the current alignment timeline,
Chris@319 195 * if any.
Chris@319 196 */
Chris@319 197 virtual const Model *getAlignmentReference() const;
Chris@319 198
Chris@319 199 /**
Chris@319 200 * Return the frame number of the reference model that corresponds
Chris@319 201 * to the given frame number in this model.
Chris@319 202 */
Chris@929 203 virtual int alignToReference(int frame) const;
Chris@319 204
Chris@319 205 /**
Chris@319 206 * Return the frame number in this model that corresponds to the
Chris@319 207 * given frame number of the reference model.
Chris@319 208 */
Chris@929 209 virtual int alignFromReference(int referenceFrame) const;
Chris@319 210
Chris@319 211 /**
Chris@319 212 * Return the completion percentage for the alignment model: 100
Chris@319 213 * if there is no alignment model or it has been entirely
Chris@319 214 * calculated, or less than 100 if it is still being calculated.
Chris@319 215 */
Chris@319 216 virtual int getAlignmentCompletion() const;
Chris@297 217
Chris@558 218 /**
Chris@558 219 * Set the event, feature, or signal type URI for the features
Chris@558 220 * contained in this model, according to the Audio Features RDF
Chris@558 221 * ontology.
Chris@558 222 */
Chris@558 223 void setRDFTypeURI(QString uri) { m_typeUri = uri; }
Chris@558 224
Chris@558 225 /**
Chris@558 226 * Retrieve the event, feature, or signal type URI for the
Chris@558 227 * features contained in this model, if previously set with
Chris@558 228 * setRDFTypeURI.
Chris@558 229 */
Chris@558 230 QString getRDFTypeURI() const { return m_typeUri; }
Chris@558 231
Chris@150 232 virtual void toXml(QTextStream &stream,
Chris@150 233 QString indent = "",
Chris@150 234 QString extraAttributes = "") const;
Chris@150 235
Chris@838 236 virtual QString toDelimitedDataString(QString delimiter) const {
Chris@929 237 return toDelimitedDataStringSubset(delimiter, getStartFrame(), getEndFrame());
Chris@838 238 }
Chris@929 239 virtual QString toDelimitedDataStringSubset(QString, int /* f0 */, int /* f1 */) const {
Chris@838 240 return "";
Chris@838 241 }
Chris@150 242
Chris@319 243 public slots:
Chris@319 244 void aboutToDelete();
Chris@319 245 void sourceModelAboutToBeDeleted();
Chris@319 246
Chris@150 247 signals:
Chris@150 248 /**
Chris@150 249 * Emitted when a model has been edited (or more data retrieved
Chris@150 250 * from cache, in the case of a cached model that generates slowly)
Chris@150 251 */
Chris@150 252 void modelChanged();
Chris@150 253
Chris@150 254 /**
Chris@150 255 * Emitted when a model has been edited (or more data retrieved
Chris@150 256 * from cache, in the case of a cached model that generates slowly)
Chris@150 257 */
Chris@931 258 void modelChangedWithin(int startFrame, int endFrame);
Chris@150 259
Chris@150 260 /**
Chris@150 261 * Emitted when some internal processing has advanced a stage, but
Chris@150 262 * the model has not changed externally. Views should respond by
Chris@150 263 * updating any progress meters or other monitoring, but not
Chris@150 264 * refreshing the actual view.
Chris@150 265 */
Chris@150 266 void completionChanged();
Chris@150 267
Chris@319 268 /**
Chris@411 269 * Emitted when internal processing is complete (i.e. when
Chris@411 270 * isReady() would return true, with completion at 100).
Chris@411 271 */
Chris@411 272 void ready();
Chris@411 273
Chris@411 274 /**
Chris@319 275 * Emitted when the completion percentage changes for the
Chris@319 276 * calculation of this model's alignment model.
Chris@319 277 */
Chris@319 278 void alignmentCompletionChanged();
Chris@319 279
Chris@319 280 /**
Chris@319 281 * Emitted when something notifies this model (through calling
Chris@319 282 * aboutToDelete() that it is about to delete it. Note that this
Chris@319 283 * depends on an external agent such as a Document object or
Chris@319 284 * owning model telling the model that it is about to delete it;
Chris@319 285 * there is nothing in the model to guarantee that this signal
Chris@319 286 * will be emitted before the actual deletion.
Chris@319 287 */
Chris@319 288 void aboutToBeDeleted();
Chris@319 289
Chris@150 290 protected:
Chris@923 291 Model() :
Chris@923 292 m_sourceModel(0),
Chris@923 293 m_alignment(0),
Chris@923 294 m_abandoning(false),
Chris@923 295 m_aboutToDelete(false) { }
Chris@150 296
Chris@150 297 // Not provided.
Chris@150 298 Model(const Model &);
Chris@150 299 Model &operator=(const Model &);
Chris@297 300
Chris@297 301 Model *m_sourceModel;
Chris@319 302 AlignmentModel *m_alignment;
Chris@558 303 QString m_typeUri;
Chris@923 304 bool m_abandoning;
Chris@319 305 bool m_aboutToDelete;
Chris@150 306 };
Chris@150 307
Chris@150 308 #endif