annotate data/model/AlignmentModel.cpp @ 335:02d2ad95ea52 spectrogram-cache-rejig

* Get storage advice for each cache in an FFT data server. Allows us to be more confident about the actual memory situation and cut over from memory to disc part way through an FFT calculation if necessary. StorageAdviser is now a bit too optimistic though (it's too keen to allocate large numbers of small blocks in memory).
author Chris Cannam
date Tue, 13 Nov 2007 13:54:10 +0000
parents 1afaf98dbf11
children f14e2f7b24f7 6f6ab834449d
rev   line source
Chris@297 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@297 2
Chris@297 3 /*
Chris@297 4 Sonic Visualiser
Chris@297 5 An audio file viewer and annotation editor.
Chris@297 6 Centre for Digital Music, Queen Mary, University of London.
Chris@297 7 This file copyright 2007 QMUL.
Chris@297 8
Chris@297 9 This program is free software; you can redistribute it and/or
Chris@297 10 modify it under the terms of the GNU General Public License as
Chris@297 11 published by the Free Software Foundation; either version 2 of the
Chris@297 12 License, or (at your option) any later version. See the file
Chris@297 13 COPYING included with this distribution for more information.
Chris@297 14 */
Chris@297 15
Chris@297 16 #include "AlignmentModel.h"
Chris@297 17
Chris@297 18 #include "SparseTimeValueModel.h"
Chris@297 19
Chris@297 20 AlignmentModel::AlignmentModel(Model *reference,
Chris@297 21 Model *aligned,
Chris@297 22 Model *inputModel,
Chris@297 23 SparseTimeValueModel *path) :
Chris@297 24 m_reference(reference),
Chris@297 25 m_aligned(aligned),
Chris@297 26 m_inputModel(inputModel),
Chris@297 27 m_path(path),
Chris@297 28 m_reversePath(0),
Chris@323 29 m_pathBegun(false),
Chris@297 30 m_pathComplete(false)
Chris@297 31 {
Chris@297 32 connect(m_path, SIGNAL(modelChanged()),
Chris@297 33 this, SLOT(pathChanged()));
Chris@297 34
Chris@297 35 connect(m_path, SIGNAL(modelChanged(size_t, size_t)),
Chris@297 36 this, SLOT(pathChanged(size_t, size_t)));
Chris@297 37
Chris@297 38 connect(m_path, SIGNAL(completionChanged()),
Chris@297 39 this, SLOT(pathCompletionChanged()));
Chris@297 40
Chris@297 41 constructReversePath();
Chris@297 42 }
Chris@297 43
Chris@297 44 AlignmentModel::~AlignmentModel()
Chris@297 45 {
Chris@297 46 delete m_inputModel;
Chris@297 47 delete m_path;
Chris@297 48 delete m_reversePath;
Chris@297 49 }
Chris@297 50
Chris@297 51 bool
Chris@297 52 AlignmentModel::isOK() const
Chris@297 53 {
Chris@297 54 return m_path->isOK();
Chris@297 55 }
Chris@297 56
Chris@297 57 size_t
Chris@297 58 AlignmentModel::getStartFrame() const
Chris@297 59 {
Chris@297 60 //!!! do we care about distinct rates?
Chris@297 61 size_t a = m_reference->getStartFrame();
Chris@297 62 size_t b = m_aligned->getStartFrame();
Chris@297 63 return std::min(a, b);
Chris@297 64 }
Chris@297 65
Chris@297 66 size_t
Chris@297 67 AlignmentModel::getEndFrame() const
Chris@297 68 {
Chris@297 69 //!!! do we care about distinct rates?
Chris@297 70 size_t a = m_reference->getEndFrame();
Chris@297 71 size_t b = m_aligned->getEndFrame();
Chris@297 72 return std::max(a, b);
Chris@297 73 }
Chris@297 74
Chris@297 75 size_t
Chris@297 76 AlignmentModel::getSampleRate() const
Chris@297 77 {
Chris@297 78 return m_reference->getSampleRate();
Chris@297 79 }
Chris@297 80
Chris@297 81 Model *
Chris@297 82 AlignmentModel::clone() const
Chris@297 83 {
Chris@297 84 return new AlignmentModel
Chris@297 85 (m_reference, m_aligned,
Chris@297 86 m_inputModel ? m_inputModel->clone() : 0,
Chris@297 87 m_path ? static_cast<SparseTimeValueModel *>(m_path->clone()) : 0);
Chris@297 88 }
Chris@297 89
Chris@297 90 bool
Chris@297 91 AlignmentModel::isReady(int *completion) const
Chris@297 92 {
Chris@323 93 if (!m_pathBegun) {
Chris@323 94 completion = 0;
Chris@323 95 return false;
Chris@323 96 }
Chris@297 97 return m_path->isReady(completion);
Chris@297 98 }
Chris@297 99
Chris@297 100 const ZoomConstraint *
Chris@297 101 AlignmentModel::getZoomConstraint() const
Chris@297 102 {
Chris@297 103 return m_path->getZoomConstraint();
Chris@297 104 }
Chris@297 105
Chris@297 106 const Model *
Chris@297 107 AlignmentModel::getReferenceModel() const
Chris@297 108 {
Chris@297 109 return m_reference;
Chris@297 110 }
Chris@297 111
Chris@297 112 const Model *
Chris@297 113 AlignmentModel::getAlignedModel() const
Chris@297 114 {
Chris@297 115 return m_aligned;
Chris@297 116 }
Chris@297 117
Chris@297 118 size_t
Chris@297 119 AlignmentModel::toReference(size_t frame) const
Chris@297 120 {
Chris@297 121 // std::cerr << "AlignmentModel::toReference(" << frame << ")" << std::endl;
Chris@297 122 if (!m_reversePath) constructReversePath();
Chris@297 123 return align(m_reversePath, frame);
Chris@297 124 }
Chris@297 125
Chris@297 126 size_t
Chris@297 127 AlignmentModel::fromReference(size_t frame) const
Chris@297 128 {
Chris@297 129 // std::cerr << "AlignmentModel::fromReference(" << frame << ")" << std::endl;
Chris@297 130 return align(m_path, frame);
Chris@297 131 }
Chris@297 132
Chris@297 133 void
Chris@297 134 AlignmentModel::pathChanged()
Chris@297 135 {
Chris@297 136 }
Chris@297 137
Chris@297 138 void
Chris@297 139 AlignmentModel::pathChanged(size_t, size_t)
Chris@297 140 {
Chris@297 141 if (!m_pathComplete) return;
Chris@297 142 constructReversePath();
Chris@297 143 }
Chris@297 144
Chris@297 145 void
Chris@297 146 AlignmentModel::pathCompletionChanged()
Chris@297 147 {
Chris@323 148 m_pathBegun = true;
Chris@323 149
Chris@297 150 if (!m_pathComplete) {
Chris@297 151 int completion = 0;
Chris@297 152 m_path->isReady(&completion);
Chris@333 153 // std::cerr << "AlignmentModel::pathCompletionChanged: completion = "
Chris@333 154 // << completion << std::endl;
Chris@323 155 m_pathComplete = (completion == 100);
Chris@297 156 if (m_pathComplete) {
Chris@297 157 constructReversePath();
Chris@297 158 delete m_inputModel;
Chris@297 159 m_inputModel = 0;
Chris@297 160 }
Chris@297 161 }
Chris@323 162
Chris@297 163 emit completionChanged();
Chris@297 164 }
Chris@297 165
Chris@297 166 void
Chris@297 167 AlignmentModel::constructReversePath() const
Chris@297 168 {
Chris@297 169 if (!m_reversePath) {
Chris@297 170 m_reversePath = new SparseTimeValueModel
Chris@297 171 (m_path->getSampleRate(), m_path->getResolution(), false);
Chris@297 172 }
Chris@297 173
Chris@297 174 m_reversePath->clear();
Chris@297 175
Chris@297 176 SparseTimeValueModel::PointList points = m_path->getPoints();
Chris@297 177
Chris@297 178 for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
Chris@297 179 i != points.end(); ++i) {
Chris@297 180 long frame = i->frame;
Chris@297 181 float value = i->value;
Chris@297 182 long rframe = lrintf(value * m_aligned->getSampleRate());
Chris@297 183 float rvalue = (float)frame / (float)m_reference->getSampleRate();
Chris@297 184 m_reversePath->addPoint
Chris@297 185 (SparseTimeValueModel::Point(rframe, rvalue, ""));
Chris@297 186 }
Chris@297 187
Chris@312 188 std::cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(SparseTimeValueModel::Point))) << " bytes" << std::endl;
Chris@297 189 }
Chris@297 190
Chris@297 191 size_t
Chris@297 192 AlignmentModel::align(SparseTimeValueModel *path, size_t frame) const
Chris@297 193 {
Chris@297 194 // The path consists of a series of points, each with x (time)
Chris@297 195 // equal to the time on the source model and y (value) equal to
Chris@297 196 // the time on the target model. Times and values are both
Chris@297 197 // monotonically increasing.
Chris@297 198
Chris@297 199 const SparseTimeValueModel::PointList &points = path->getPoints();
Chris@297 200
Chris@297 201 if (points.empty()) {
Chris@297 202 // std::cerr << "AlignmentModel::align: No points" << std::endl;
Chris@297 203 return frame;
Chris@297 204 }
Chris@297 205
Chris@297 206 SparseTimeValueModel::Point point(frame);
Chris@297 207 SparseTimeValueModel::PointList::const_iterator i = points.lower_bound(point);
Chris@297 208 if (i == points.end()) --i;
Chris@312 209 while (i != points.begin() && i->frame > frame) --i;
Chris@297 210
Chris@312 211 long foundFrame = i->frame;
Chris@312 212 float foundTime = i->value;
Chris@297 213
Chris@312 214 long followingFrame = foundFrame;
Chris@312 215 float followingTime = foundTime;
Chris@297 216
Chris@312 217 if (++i != points.end()) {
Chris@312 218 followingFrame = i->frame;
Chris@312 219 followingTime = i->value;
Chris@312 220 }
Chris@312 221
Chris@312 222 float resultTime = foundTime;
Chris@312 223
Chris@312 224 if (followingFrame != foundFrame && frame > foundFrame) {
Chris@312 225
Chris@313 226 // std::cerr << "AlignmentModel::align: foundFrame = " << foundFrame << ", frame = " << frame << ", followingFrame = " << followingFrame << std::endl;
Chris@312 227
Chris@312 228 float interp = float(frame - foundFrame) / float(followingFrame - foundFrame);
Chris@313 229 // std::cerr << "AlignmentModel::align: interp = " << interp << ", result " << resultTime << " -> ";
Chris@312 230
Chris@312 231 resultTime += (followingTime - foundTime) * interp;
Chris@312 232
Chris@313 233 // std::cerr << resultTime << std::endl;
Chris@312 234 }
Chris@312 235
Chris@312 236 size_t resultFrame = lrintf(resultTime * getSampleRate());
Chris@312 237
Chris@313 238 // std::cerr << "AlignmentModel::align: resultFrame = " << resultFrame << std::endl;
Chris@312 239
Chris@312 240 return resultFrame;
Chris@297 241 }
Chris@297 242