annotate data/model/WritableWaveFileModel.h @ 1671:82d03c9661f9 single-point

Rework isReady()/getCompletion() on models. Previously the new overhauled models were implementing getCompletion() but inheriting a version of isReady() (from the Model base) that didn't call it, referring only to isOK(). So they were reporting completion as soon as they had begun. Instead hoist getCompletion() to abstract base and call it from Model::isReady().
author Chris Cannam
date Wed, 27 Mar 2019 13:15:16 +0000
parents c01cbe41aeb5
children 26da177d7266
rev   line source
Chris@175 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@175 2
Chris@175 3 /*
Chris@175 4 Sonic Visualiser
Chris@175 5 An audio file viewer and annotation editor.
Chris@175 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 QMUL.
Chris@175 8
Chris@175 9 This program is free software; you can redistribute it and/or
Chris@175 10 modify it under the terms of the GNU General Public License as
Chris@175 11 published by the Free Software Foundation; either version 2 of the
Chris@175 12 License, or (at your option) any later version. See the file
Chris@175 13 COPYING included with this distribution for more information.
Chris@175 14 */
Chris@175 15
Chris@1122 16 #ifndef WRITABLE_WAVE_FILE_MODEL_H
Chris@1122 17 #define WRITABLE_WAVE_FILE_MODEL_H
Chris@175 18
Chris@175 19 #include "WaveFileModel.h"
Chris@1122 20 #include "ReadOnlyWaveFileModel.h"
Chris@1122 21 #include "PowerOfSqrtTwoZoomConstraint.h"
Chris@175 22
Chris@175 23 class WavFileWriter;
Chris@175 24 class WavFileReader;
Chris@175 25
Chris@1122 26 class WritableWaveFileModel : public WaveFileModel
Chris@175 27 {
Chris@175 28 Q_OBJECT
Chris@175 29
Chris@175 30 public:
Chris@1520 31 enum class Normalisation { None, Peak };
Chris@1520 32
Chris@1520 33 /**
Chris@1520 34 * Create a WritableWaveFileModel of the given sample rate and
Chris@1520 35 * channel count, storing data in a new float-type extended WAV
Chris@1520 36 * file with the given path. If path is the empty string, the data
Chris@1520 37 * will be stored in a newly-created temporary file.
Chris@1520 38 *
Chris@1520 39 * If normalisation == None, sample values will be written
Chris@1520 40 * verbatim, and will be ready to read as soon as they have been
Chris@1520 41 * written. Otherwise samples will be normalised on writing; this
Chris@1520 42 * will require an additional pass and temporary file, and no
Chris@1520 43 * samples will be available to read until after writeComplete()
Chris@1520 44 * has returned.
Chris@1520 45 */
Chris@1520 46 WritableWaveFileModel(QString path,
Chris@1520 47 sv_samplerate_t sampleRate,
Chris@1520 48 int channels,
Chris@1520 49 Normalisation normalisation);
Chris@1520 50
Chris@1520 51 /**
Chris@1520 52 * Create a WritableWaveFileModel of the given sample rate and
Chris@1520 53 * channel count, storing data in a new float-type extended WAV
Chris@1520 54 * file in a temporary location. This is equivalent to passing an
Chris@1520 55 * empty path to the constructor above.
Chris@1520 56 *
Chris@1520 57 * If normalisation == None, sample values will be written
Chris@1520 58 * verbatim, and will be ready to read as soon as they have been
Chris@1520 59 * written. Otherwise samples will be normalised on writing; this
Chris@1520 60 * will require an additional pass and temporary file, and no
Chris@1520 61 * samples will be available to read until after writeComplete()
Chris@1520 62 * has returned.
Chris@1520 63 */
Chris@1517 64 WritableWaveFileModel(sv_samplerate_t sampleRate,
Chris@1517 65 int channels,
Chris@1520 66 Normalisation normalisation);
Chris@1520 67
Chris@1520 68 /**
Chris@1520 69 * Create a WritableWaveFileModel of the given sample rate and
Chris@1520 70 * channel count, storing data in a new float-type extended WAV
Chris@1520 71 * file in a temporary location, and applying no normalisation.
Chris@1520 72 *
Chris@1520 73 * This is equivalent to passing an empty path and
Chris@1520 74 * Normalisation::None to the first constructor above.
Chris@1520 75 */
Chris@1520 76 WritableWaveFileModel(sv_samplerate_t sampleRate,
Chris@1520 77 int channels);
Chris@1520 78
Chris@175 79 ~WritableWaveFileModel();
Chris@175 80
Chris@188 81 /**
Chris@188 82 * Call addSamples to append a block of samples to the end of the
Chris@1337 83 * file.
Chris@1337 84 *
Chris@1337 85 * This function only appends the samples to the file being
Chris@1337 86 * written; it does not update the model's view of the samples in
Chris@1337 87 * that file. That is, it updates the file on disc but the model
Chris@1337 88 * itself does not change its content. This is because re-reading
Chris@1337 89 * the file to update the model may be more expensive than adding
Chris@1337 90 * the samples in the first place. If you are writing small
Chris@1337 91 * numbers of samples repeatedly, you probably only want the model
Chris@1337 92 * to update periodically rather than after every write.
Chris@1337 93 *
Chris@1337 94 * Call updateModel() periodically to tell the model to update its
Chris@1337 95 * own view of the samples in the file being written.
Chris@1337 96 *
Chris@1337 97 * Call setWriteProportion() periodically if the file being
Chris@1337 98 * written has known duration and you want the model to be able to
Chris@1337 99 * report the write progress as a percentage.
Chris@1337 100 *
Chris@1337 101 * Call writeComplete() when the file has been completely written.
Chris@188 102 */
Chris@1325 103 virtual bool addSamples(const float *const *samples, sv_frame_t count);
Chris@1133 104
Chris@1133 105 /**
Chris@1337 106 * Tell the model to update its own (read) view of the (written)
Chris@1337 107 * file. May cause modelChanged() and modelChangedWithin() to be
Chris@1337 108 * emitted. See the comment to addSamples above for rationale.
Chris@1337 109 */
Chris@1337 110 void updateModel();
Chris@1337 111
Chris@1337 112 /**
Chris@1133 113 * Set the proportion of the file which has been written so far,
Chris@1133 114 * as a percentage. This may be used to indicate progress.
Chris@1133 115 *
Chris@1133 116 * Note that this differs from the "completion" percentage
Chris@1133 117 * reported through isReady()/getCompletion(). That percentage is
Chris@1133 118 * updated when "internal processing has advanced... but the model
Chris@1133 119 * has not changed externally", i.e. it reports progress in
Chris@1133 120 * calculating the initial state of a model. In contrast, an
Chris@1133 121 * update to setWriteProportion corresponds to a change in the
Chris@1133 122 * externally visible state of the model (i.e. it contains more
Chris@1133 123 * data than before).
Chris@1133 124 */
Chris@1133 125 void setWriteProportion(int proportion);
Chris@1133 126
Chris@1133 127 /**
Chris@1133 128 * Indicate that writing is complete. You should call this even if
Chris@1337 129 * you have never called setWriteProportion() or updateModel().
Chris@1133 130 */
Chris@1133 131 void writeComplete();
Chris@1133 132
Chris@1133 133 static const int PROPORTION_UNKNOWN;
Chris@1133 134
Chris@1133 135 /**
Chris@1133 136 * Get the proportion of the file which has been written so far,
Chris@1133 137 * as a percentage. Return PROPORTION_UNKNOWN if unknown.
Chris@1133 138 */
Chris@1133 139 int getWriteProportion() const;
Chris@175 140
Chris@1580 141 bool isOK() const override;
Chris@1133 142
Chris@1133 143 /**
Chris@1133 144 * Return the generation completion percentage of this model. This
Chris@1133 145 * is always 100, because the model is always in a complete state
Chris@1133 146 * -- it just contains varying amounts of data depending on how
Chris@1133 147 * much has been written.
Chris@1133 148 */
Chris@1671 149 int getCompletion() const override { return 100; }
Chris@188 150
Chris@1580 151 const ZoomConstraint *getZoomConstraint() const override {
Chris@179 152 static PowerOfSqrtTwoZoomConstraint zc;
Chris@179 153 return &zc;
Chris@179 154 }
Chris@179 155
Chris@1580 156 sv_frame_t getFrameCount() const override;
Chris@1580 157 int getChannelCount() const override { return m_channels; }
Chris@1580 158 sv_samplerate_t getSampleRate() const override { return m_sampleRate; }
Chris@1580 159 sv_samplerate_t getNativeRate() const override { return m_sampleRate; }
Chris@1122 160
Chris@1580 161 QString getTitle() const override {
Chris@1122 162 if (m_model) return m_model->getTitle();
Chris@1122 163 else return "";
Chris@1122 164 }
Chris@1580 165 QString getMaker() const override {
Chris@1122 166 if (m_model) return m_model->getMaker();
Chris@1122 167 else return "";
Chris@1122 168 }
Chris@1580 169 QString getLocation() const override {
Chris@1122 170 if (m_model) return m_model->getLocation();
Chris@1122 171 else return "";
Chris@1122 172 }
Chris@175 173
Chris@1580 174 float getValueMinimum() const override { return -1.0f; }
Chris@1580 175 float getValueMaximum() const override { return 1.0f; }
Chris@175 176
Chris@1580 177 sv_frame_t getStartFrame() const override { return m_startFrame; }
Chris@1580 178 sv_frame_t getEndFrame() const override { return m_startFrame + getFrameCount(); }
Chris@175 179
Chris@1580 180 void setStartFrame(sv_frame_t startFrame) override;
Chris@175 181
Chris@1580 182 floatvec_t getData(int channel, sv_frame_t start, sv_frame_t count) const override;
Chris@175 183
Chris@1580 184 std::vector<floatvec_t> getMultiChannelData(int fromchannel, int tochannel, sv_frame_t start, sv_frame_t count) const override;
Chris@363 185
Chris@1580 186 int getSummaryBlockSize(int desired) const override;
Chris@377 187
Chris@1580 188 void getSummaries(int channel, sv_frame_t start, sv_frame_t count,
Chris@1580 189 RangeBlock &ranges, int &blockSize) const override;
Chris@300 190
Chris@1580 191 Range getSummary(int channel, sv_frame_t start, sv_frame_t count) const override;
Chris@175 192
Chris@1580 193 QString getTypeName() const override { return tr("Writable Wave File"); }
Chris@345 194
Chris@1580 195 void toXml(QTextStream &out,
Chris@175 196 QString indent = "",
Chris@1580 197 QString extraAttributes = "") const override;
Chris@175 198
Chris@175 199 protected:
Chris@1122 200 ReadOnlyWaveFileModel *m_model;
Chris@1520 201
Chris@1520 202 /** When normalising, this writer is used to write verbatim
Chris@1520 203 * samples to the temporary file prior to
Chris@1520 204 * normalisation. Otherwise it's null
Chris@1520 205 */
Chris@1520 206 WavFileWriter *m_temporaryWriter;
Chris@1520 207 QString m_temporaryPath;
Chris@1520 208
Chris@1520 209 /** When not normalising, this writer is used to write verbatim
Chris@1520 210 * samples direct to the target file. When normalising, it is
Chris@1520 211 * used to write normalised samples to the target after the
Chris@1520 212 * temporary file has been completed. But it is still created on
Chris@1520 213 * initialisation, so that there is a file header ready for the
Chris@1520 214 * reader to address.
Chris@1520 215 */
Chris@1520 216 WavFileWriter *m_targetWriter;
Chris@1520 217 QString m_targetPath;
Chris@1520 218
Chris@175 219 WavFileReader *m_reader;
Chris@1520 220 Normalisation m_normalisation;
Chris@1040 221 sv_samplerate_t m_sampleRate;
Chris@929 222 int m_channels;
Chris@1038 223 sv_frame_t m_frameCount;
Chris@1038 224 sv_frame_t m_startFrame;
Chris@1133 225 int m_proportion;
Chris@1520 226
Chris@1520 227 private:
Chris@1520 228 void init(QString path = "");
Chris@1520 229 void normaliseToTarget();
Chris@175 230 };
Chris@175 231
Chris@175 232 #endif
Chris@175 233