annotate data/model/EditableDenseThreeDimensionalModel.cpp @ 299:576be0d0d218

* Merge transform directory from sv-match-alignment branch (the previous comment included notes for this stuff, but I missed it in the actual merge) * Fix crash when a transform fails to create an output model and the thread that created the transform then deletes its input model thinking it's no longer needed, even though the transform run thread is still using it -- fix is to wait() on the transform before returning the null output model
author Chris Cannam
date Fri, 28 Sep 2007 16:15:06 +0000
parents 46398ab6ff58
children 70a232b1f12a
rev   line source
Chris@152 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@152 2
Chris@152 3 /*
Chris@152 4 Sonic Visualiser
Chris@152 5 An audio file viewer and annotation editor.
Chris@152 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@152 8
Chris@152 9 This program is free software; you can redistribute it and/or
Chris@152 10 modify it under the terms of the GNU General Public License as
Chris@152 11 published by the Free Software Foundation; either version 2 of the
Chris@152 12 License, or (at your option) any later version. See the file
Chris@152 13 COPYING included with this distribution for more information.
Chris@152 14 */
Chris@152 15
Chris@152 16 #include "EditableDenseThreeDimensionalModel.h"
Chris@152 17
Chris@152 18 #include <QTextStream>
Chris@152 19
Chris@181 20 #include <iostream>
Chris@181 21
Chris@256 22 #include <cmath>
Chris@256 23
Chris@152 24 EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate,
Chris@152 25 size_t resolution,
Chris@152 26 size_t yBinCount,
Chris@152 27 bool notifyOnAdd) :
Chris@152 28 m_sampleRate(sampleRate),
Chris@152 29 m_resolution(resolution),
Chris@152 30 m_yBinCount(yBinCount),
Chris@152 31 m_minimum(0.0),
Chris@152 32 m_maximum(0.0),
Chris@256 33 m_haveExtents(false),
Chris@152 34 m_notifyOnAdd(notifyOnAdd),
Chris@152 35 m_sinceLastNotifyMin(-1),
Chris@152 36 m_sinceLastNotifyMax(-1),
Chris@152 37 m_completion(100)
Chris@152 38 {
Chris@152 39 }
Chris@152 40
Chris@152 41 bool
Chris@152 42 EditableDenseThreeDimensionalModel::isOK() const
Chris@152 43 {
Chris@152 44 return true;
Chris@152 45 }
Chris@152 46
Chris@152 47 size_t
Chris@152 48 EditableDenseThreeDimensionalModel::getSampleRate() const
Chris@152 49 {
Chris@152 50 return m_sampleRate;
Chris@152 51 }
Chris@152 52
Chris@152 53 size_t
Chris@152 54 EditableDenseThreeDimensionalModel::getStartFrame() const
Chris@152 55 {
Chris@152 56 return 0;
Chris@152 57 }
Chris@152 58
Chris@152 59 size_t
Chris@152 60 EditableDenseThreeDimensionalModel::getEndFrame() const
Chris@152 61 {
Chris@152 62 return m_resolution * m_data.size() + (m_resolution - 1);
Chris@152 63 }
Chris@152 64
Chris@152 65 Model *
Chris@152 66 EditableDenseThreeDimensionalModel::clone() const
Chris@152 67 {
Chris@152 68 EditableDenseThreeDimensionalModel *model =
Chris@152 69 new EditableDenseThreeDimensionalModel
Chris@152 70 (m_sampleRate, m_resolution, m_yBinCount);
Chris@152 71
Chris@152 72 model->m_minimum = m_minimum;
Chris@152 73 model->m_maximum = m_maximum;
Chris@256 74 model->m_haveExtents = m_haveExtents;
Chris@152 75
Chris@152 76 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@182 77 model->setColumn(i, m_data[i]);
Chris@152 78 }
Chris@152 79
Chris@152 80 return model;
Chris@152 81 }
Chris@152 82
Chris@152 83 size_t
Chris@152 84 EditableDenseThreeDimensionalModel::getResolution() const
Chris@152 85 {
Chris@152 86 return m_resolution;
Chris@152 87 }
Chris@152 88
Chris@152 89 void
Chris@152 90 EditableDenseThreeDimensionalModel::setResolution(size_t sz)
Chris@152 91 {
Chris@152 92 m_resolution = sz;
Chris@152 93 }
Chris@152 94
Chris@152 95 size_t
Chris@182 96 EditableDenseThreeDimensionalModel::getWidth() const
Chris@182 97 {
Chris@182 98 return m_data.size();
Chris@182 99 }
Chris@182 100
Chris@182 101 size_t
Chris@182 102 EditableDenseThreeDimensionalModel::getHeight() const
Chris@152 103 {
Chris@152 104 return m_yBinCount;
Chris@152 105 }
Chris@152 106
Chris@152 107 void
Chris@182 108 EditableDenseThreeDimensionalModel::setHeight(size_t sz)
Chris@152 109 {
Chris@152 110 m_yBinCount = sz;
Chris@152 111 }
Chris@152 112
Chris@152 113 float
Chris@152 114 EditableDenseThreeDimensionalModel::getMinimumLevel() const
Chris@152 115 {
Chris@152 116 return m_minimum;
Chris@152 117 }
Chris@152 118
Chris@152 119 void
Chris@152 120 EditableDenseThreeDimensionalModel::setMinimumLevel(float level)
Chris@152 121 {
Chris@152 122 m_minimum = level;
Chris@152 123 }
Chris@152 124
Chris@152 125 float
Chris@152 126 EditableDenseThreeDimensionalModel::getMaximumLevel() const
Chris@152 127 {
Chris@152 128 return m_maximum;
Chris@152 129 }
Chris@152 130
Chris@152 131 void
Chris@152 132 EditableDenseThreeDimensionalModel::setMaximumLevel(float level)
Chris@152 133 {
Chris@152 134 m_maximum = level;
Chris@152 135 }
Chris@152 136
Chris@152 137 void
Chris@182 138 EditableDenseThreeDimensionalModel::getColumn(size_t index,
Chris@182 139 Column &result) const
Chris@152 140 {
Chris@152 141 QMutexLocker locker(&m_mutex);
Chris@152 142
Chris@182 143 if (index < m_data.size()) {
Chris@152 144 result = m_data[index];
Chris@152 145 } else {
Chris@152 146 result.clear();
Chris@152 147 }
Chris@152 148
Chris@152 149 while (result.size() < m_yBinCount) result.push_back(m_minimum);
Chris@152 150 }
Chris@152 151
Chris@152 152 float
Chris@182 153 EditableDenseThreeDimensionalModel::getValueAt(size_t index, size_t n) const
Chris@152 154 {
Chris@152 155 QMutexLocker locker(&m_mutex);
Chris@152 156
Chris@182 157 if (index < m_data.size()) {
Chris@182 158 const Column &s = m_data[index];
Chris@256 159 // std::cerr << "index " << index << ", n " << n << ", res " << m_resolution << ", size " << s.size()
Chris@256 160 // << std::endl;
Chris@152 161 if (n < s.size()) return s[n];
Chris@152 162 }
Chris@152 163
Chris@152 164 return m_minimum;
Chris@152 165 }
Chris@152 166
Chris@152 167 void
Chris@182 168 EditableDenseThreeDimensionalModel::setColumn(size_t index,
Chris@182 169 const Column &values)
Chris@152 170 {
Chris@152 171 QMutexLocker locker(&m_mutex);
Chris@152 172
Chris@182 173 while (index >= m_data.size()) {
Chris@182 174 m_data.push_back(Column());
Chris@152 175 }
Chris@152 176
Chris@152 177 bool allChange = false;
Chris@152 178
Chris@152 179 for (size_t i = 0; i < values.size(); ++i) {
Chris@256 180 float value = values[i];
Chris@257 181 if (std::isnan(value) || std::isinf(value)) {
Chris@256 182 continue;
Chris@256 183 }
Chris@256 184 if (!m_haveExtents || value < m_minimum) {
Chris@256 185 m_minimum = value;
Chris@152 186 allChange = true;
Chris@152 187 }
Chris@256 188 if (!m_haveExtents || value > m_maximum) {
Chris@256 189 m_maximum = value;
Chris@152 190 allChange = true;
Chris@152 191 }
Chris@256 192 m_haveExtents = true;
Chris@152 193 }
Chris@152 194
Chris@152 195 m_data[index] = values;
Chris@152 196
Chris@182 197 long windowStart = index;
Chris@182 198 windowStart *= m_resolution;
Chris@182 199
Chris@152 200 if (m_notifyOnAdd) {
Chris@152 201 if (allChange) {
Chris@152 202 emit modelChanged();
Chris@152 203 } else {
Chris@152 204 emit modelChanged(windowStart, windowStart + m_resolution);
Chris@152 205 }
Chris@152 206 } else {
Chris@152 207 if (allChange) {
Chris@152 208 m_sinceLastNotifyMin = -1;
Chris@152 209 m_sinceLastNotifyMax = -1;
Chris@152 210 emit modelChanged();
Chris@152 211 } else {
Chris@152 212 if (m_sinceLastNotifyMin == -1 ||
Chris@152 213 windowStart < m_sinceLastNotifyMin) {
Chris@152 214 m_sinceLastNotifyMin = windowStart;
Chris@152 215 }
Chris@152 216 if (m_sinceLastNotifyMax == -1 ||
Chris@152 217 windowStart > m_sinceLastNotifyMax) {
Chris@152 218 m_sinceLastNotifyMax = windowStart;
Chris@152 219 }
Chris@152 220 }
Chris@152 221 }
Chris@152 222 }
Chris@152 223
Chris@152 224 QString
Chris@152 225 EditableDenseThreeDimensionalModel::getBinName(size_t n) const
Chris@152 226 {
Chris@152 227 if (m_binNames.size() > n) return m_binNames[n];
Chris@152 228 else return "";
Chris@152 229 }
Chris@152 230
Chris@152 231 void
Chris@152 232 EditableDenseThreeDimensionalModel::setBinName(size_t n, QString name)
Chris@152 233 {
Chris@152 234 while (m_binNames.size() <= n) m_binNames.push_back("");
Chris@152 235 m_binNames[n] = name;
Chris@152 236 emit modelChanged();
Chris@152 237 }
Chris@152 238
Chris@152 239 void
Chris@152 240 EditableDenseThreeDimensionalModel::setBinNames(std::vector<QString> names)
Chris@152 241 {
Chris@152 242 m_binNames = names;
Chris@152 243 emit modelChanged();
Chris@152 244 }
Chris@152 245
Chris@152 246 void
Chris@152 247 EditableDenseThreeDimensionalModel::setCompletion(int completion)
Chris@152 248 {
Chris@152 249 if (m_completion != completion) {
Chris@152 250 m_completion = completion;
Chris@152 251
Chris@152 252 if (completion == 100) {
Chris@152 253
Chris@152 254 m_notifyOnAdd = true; // henceforth
Chris@152 255 emit modelChanged();
Chris@152 256
Chris@152 257 } else if (!m_notifyOnAdd) {
Chris@152 258
Chris@152 259 if (m_sinceLastNotifyMin >= 0 &&
Chris@152 260 m_sinceLastNotifyMax >= 0) {
Chris@152 261 emit modelChanged(m_sinceLastNotifyMin,
Chris@152 262 m_sinceLastNotifyMax + m_resolution);
Chris@152 263 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
Chris@152 264 } else {
Chris@152 265 emit completionChanged();
Chris@152 266 }
Chris@152 267 } else {
Chris@152 268 emit completionChanged();
Chris@152 269 }
Chris@152 270 }
Chris@152 271 }
Chris@152 272
Chris@152 273 void
Chris@152 274 EditableDenseThreeDimensionalModel::toXml(QTextStream &out,
Chris@152 275 QString indent,
Chris@152 276 QString extraAttributes) const
Chris@152 277 {
Chris@152 278 // For historical reasons we read and write "resolution" as "windowSize"
Chris@152 279
Chris@152 280 out << Model::toXmlString
Chris@152 281 (indent, QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6")
Chris@152 282 .arg(m_resolution)
Chris@152 283 .arg(m_yBinCount)
Chris@152 284 .arg(m_minimum)
Chris@152 285 .arg(m_maximum)
Chris@152 286 .arg(getObjectExportId(&m_data))
Chris@152 287 .arg(extraAttributes));
Chris@152 288
Chris@152 289 out << indent;
Chris@152 290 out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n")
Chris@152 291 .arg(getObjectExportId(&m_data));
Chris@152 292
Chris@152 293 for (size_t i = 0; i < m_binNames.size(); ++i) {
Chris@152 294 if (m_binNames[i] != "") {
Chris@152 295 out << indent + " ";
Chris@152 296 out << QString("<bin number=\"%1\" name=\"%2\"/>\n")
Chris@152 297 .arg(i).arg(m_binNames[i]);
Chris@152 298 }
Chris@152 299 }
Chris@152 300
Chris@152 301 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@152 302 out << indent + " ";
Chris@152 303 out << QString("<row n=\"%1\">").arg(i);
Chris@152 304 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@152 305 if (j > 0) out << " ";
Chris@152 306 out << m_data[i][j];
Chris@152 307 }
Chris@152 308 out << QString("</row>\n");
Chris@152 309 }
Chris@152 310
Chris@152 311 out << indent + "</dataset>\n";
Chris@152 312 }
Chris@152 313
Chris@152 314 QString
Chris@152 315 EditableDenseThreeDimensionalModel::toXmlString(QString indent,
Chris@152 316 QString extraAttributes) const
Chris@152 317 {
Chris@152 318 QString s;
Chris@152 319
Chris@152 320 {
Chris@152 321 QTextStream out(&s);
Chris@152 322 toXml(out, indent, extraAttributes);
Chris@152 323 }
Chris@152 324
Chris@152 325 return s;
Chris@152 326 }
Chris@152 327