annotate data/model/EditableDenseThreeDimensionalModel.cpp @ 452:325112751f0e

* Save/load of region models
author Chris Cannam
date Thu, 09 Oct 2008 12:04:22 +0000
parents beb2948baa77
children 1405f4a2caf3
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@387 20 #include <QStringList>
Chris@387 21
Chris@181 22 #include <iostream>
Chris@181 23
Chris@256 24 #include <cmath>
Chris@256 25
Chris@152 26 EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate,
Chris@152 27 size_t resolution,
Chris@152 28 size_t yBinCount,
Chris@152 29 bool notifyOnAdd) :
Chris@152 30 m_sampleRate(sampleRate),
Chris@152 31 m_resolution(resolution),
Chris@152 32 m_yBinCount(yBinCount),
Chris@152 33 m_minimum(0.0),
Chris@152 34 m_maximum(0.0),
Chris@256 35 m_haveExtents(false),
Chris@152 36 m_notifyOnAdd(notifyOnAdd),
Chris@152 37 m_sinceLastNotifyMin(-1),
Chris@152 38 m_sinceLastNotifyMax(-1),
Chris@152 39 m_completion(100)
Chris@152 40 {
Chris@152 41 }
Chris@152 42
Chris@152 43 bool
Chris@152 44 EditableDenseThreeDimensionalModel::isOK() const
Chris@152 45 {
Chris@152 46 return true;
Chris@152 47 }
Chris@152 48
Chris@152 49 size_t
Chris@152 50 EditableDenseThreeDimensionalModel::getSampleRate() const
Chris@152 51 {
Chris@152 52 return m_sampleRate;
Chris@152 53 }
Chris@152 54
Chris@152 55 size_t
Chris@152 56 EditableDenseThreeDimensionalModel::getStartFrame() const
Chris@152 57 {
Chris@152 58 return 0;
Chris@152 59 }
Chris@152 60
Chris@152 61 size_t
Chris@152 62 EditableDenseThreeDimensionalModel::getEndFrame() const
Chris@152 63 {
Chris@152 64 return m_resolution * m_data.size() + (m_resolution - 1);
Chris@152 65 }
Chris@152 66
Chris@152 67 Model *
Chris@152 68 EditableDenseThreeDimensionalModel::clone() const
Chris@152 69 {
Chris@152 70 EditableDenseThreeDimensionalModel *model =
Chris@152 71 new EditableDenseThreeDimensionalModel
Chris@152 72 (m_sampleRate, m_resolution, m_yBinCount);
Chris@152 73
Chris@152 74 model->m_minimum = m_minimum;
Chris@152 75 model->m_maximum = m_maximum;
Chris@256 76 model->m_haveExtents = m_haveExtents;
Chris@152 77
Chris@152 78 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@182 79 model->setColumn(i, m_data[i]);
Chris@152 80 }
Chris@152 81
Chris@152 82 return model;
Chris@152 83 }
Chris@152 84
Chris@152 85 size_t
Chris@152 86 EditableDenseThreeDimensionalModel::getResolution() const
Chris@152 87 {
Chris@152 88 return m_resolution;
Chris@152 89 }
Chris@152 90
Chris@152 91 void
Chris@152 92 EditableDenseThreeDimensionalModel::setResolution(size_t sz)
Chris@152 93 {
Chris@152 94 m_resolution = sz;
Chris@152 95 }
Chris@152 96
Chris@152 97 size_t
Chris@182 98 EditableDenseThreeDimensionalModel::getWidth() const
Chris@182 99 {
Chris@182 100 return m_data.size();
Chris@182 101 }
Chris@182 102
Chris@182 103 size_t
Chris@182 104 EditableDenseThreeDimensionalModel::getHeight() const
Chris@152 105 {
Chris@152 106 return m_yBinCount;
Chris@152 107 }
Chris@152 108
Chris@152 109 void
Chris@182 110 EditableDenseThreeDimensionalModel::setHeight(size_t sz)
Chris@152 111 {
Chris@152 112 m_yBinCount = sz;
Chris@152 113 }
Chris@152 114
Chris@152 115 float
Chris@152 116 EditableDenseThreeDimensionalModel::getMinimumLevel() const
Chris@152 117 {
Chris@152 118 return m_minimum;
Chris@152 119 }
Chris@152 120
Chris@152 121 void
Chris@152 122 EditableDenseThreeDimensionalModel::setMinimumLevel(float level)
Chris@152 123 {
Chris@152 124 m_minimum = level;
Chris@152 125 }
Chris@152 126
Chris@152 127 float
Chris@152 128 EditableDenseThreeDimensionalModel::getMaximumLevel() const
Chris@152 129 {
Chris@152 130 return m_maximum;
Chris@152 131 }
Chris@152 132
Chris@152 133 void
Chris@152 134 EditableDenseThreeDimensionalModel::setMaximumLevel(float level)
Chris@152 135 {
Chris@152 136 m_maximum = level;
Chris@152 137 }
Chris@152 138
Chris@152 139 void
Chris@182 140 EditableDenseThreeDimensionalModel::getColumn(size_t index,
Chris@182 141 Column &result) const
Chris@152 142 {
Chris@152 143 QMutexLocker locker(&m_mutex);
Chris@152 144
Chris@182 145 if (index < m_data.size()) {
Chris@152 146 result = m_data[index];
Chris@152 147 } else {
Chris@152 148 result.clear();
Chris@152 149 }
Chris@152 150
Chris@152 151 while (result.size() < m_yBinCount) result.push_back(m_minimum);
Chris@152 152 }
Chris@152 153
Chris@152 154 float
Chris@182 155 EditableDenseThreeDimensionalModel::getValueAt(size_t index, size_t n) const
Chris@152 156 {
Chris@152 157 QMutexLocker locker(&m_mutex);
Chris@152 158
Chris@182 159 if (index < m_data.size()) {
Chris@182 160 const Column &s = m_data[index];
Chris@256 161 // std::cerr << "index " << index << ", n " << n << ", res " << m_resolution << ", size " << s.size()
Chris@256 162 // << std::endl;
Chris@152 163 if (n < s.size()) return s[n];
Chris@152 164 }
Chris@152 165
Chris@152 166 return m_minimum;
Chris@152 167 }
Chris@152 168
Chris@152 169 void
Chris@182 170 EditableDenseThreeDimensionalModel::setColumn(size_t index,
Chris@182 171 const Column &values)
Chris@152 172 {
Chris@152 173 QMutexLocker locker(&m_mutex);
Chris@152 174
Chris@182 175 while (index >= m_data.size()) {
Chris@182 176 m_data.push_back(Column());
Chris@152 177 }
Chris@152 178
Chris@152 179 bool allChange = false;
Chris@152 180
Chris@439 181 if (values.size() > m_yBinCount) m_yBinCount = values.size();
Chris@439 182
Chris@152 183 for (size_t i = 0; i < values.size(); ++i) {
Chris@256 184 float value = values[i];
Chris@257 185 if (std::isnan(value) || std::isinf(value)) {
Chris@256 186 continue;
Chris@256 187 }
Chris@256 188 if (!m_haveExtents || value < m_minimum) {
Chris@256 189 m_minimum = value;
Chris@152 190 allChange = true;
Chris@152 191 }
Chris@256 192 if (!m_haveExtents || value > m_maximum) {
Chris@256 193 m_maximum = value;
Chris@152 194 allChange = true;
Chris@152 195 }
Chris@256 196 m_haveExtents = true;
Chris@152 197 }
Chris@152 198
Chris@152 199 m_data[index] = values;
Chris@152 200
Chris@182 201 long windowStart = index;
Chris@182 202 windowStart *= m_resolution;
Chris@182 203
Chris@152 204 if (m_notifyOnAdd) {
Chris@152 205 if (allChange) {
Chris@152 206 emit modelChanged();
Chris@152 207 } else {
Chris@152 208 emit modelChanged(windowStart, windowStart + m_resolution);
Chris@152 209 }
Chris@152 210 } else {
Chris@152 211 if (allChange) {
Chris@152 212 m_sinceLastNotifyMin = -1;
Chris@152 213 m_sinceLastNotifyMax = -1;
Chris@152 214 emit modelChanged();
Chris@152 215 } else {
Chris@152 216 if (m_sinceLastNotifyMin == -1 ||
Chris@152 217 windowStart < m_sinceLastNotifyMin) {
Chris@152 218 m_sinceLastNotifyMin = windowStart;
Chris@152 219 }
Chris@152 220 if (m_sinceLastNotifyMax == -1 ||
Chris@152 221 windowStart > m_sinceLastNotifyMax) {
Chris@152 222 m_sinceLastNotifyMax = windowStart;
Chris@152 223 }
Chris@152 224 }
Chris@152 225 }
Chris@152 226 }
Chris@152 227
Chris@152 228 QString
Chris@152 229 EditableDenseThreeDimensionalModel::getBinName(size_t n) const
Chris@152 230 {
Chris@152 231 if (m_binNames.size() > n) return m_binNames[n];
Chris@152 232 else return "";
Chris@152 233 }
Chris@152 234
Chris@152 235 void
Chris@152 236 EditableDenseThreeDimensionalModel::setBinName(size_t n, QString name)
Chris@152 237 {
Chris@152 238 while (m_binNames.size() <= n) m_binNames.push_back("");
Chris@152 239 m_binNames[n] = name;
Chris@152 240 emit modelChanged();
Chris@152 241 }
Chris@152 242
Chris@152 243 void
Chris@152 244 EditableDenseThreeDimensionalModel::setBinNames(std::vector<QString> names)
Chris@152 245 {
Chris@152 246 m_binNames = names;
Chris@152 247 emit modelChanged();
Chris@152 248 }
Chris@152 249
Chris@152 250 void
Chris@333 251 EditableDenseThreeDimensionalModel::setCompletion(int completion, bool update)
Chris@152 252 {
Chris@152 253 if (m_completion != completion) {
Chris@152 254 m_completion = completion;
Chris@152 255
Chris@152 256 if (completion == 100) {
Chris@152 257
Chris@152 258 m_notifyOnAdd = true; // henceforth
Chris@152 259 emit modelChanged();
Chris@152 260
Chris@152 261 } else if (!m_notifyOnAdd) {
Chris@152 262
Chris@333 263 if (update &&
Chris@333 264 m_sinceLastNotifyMin >= 0 &&
Chris@152 265 m_sinceLastNotifyMax >= 0) {
Chris@152 266 emit modelChanged(m_sinceLastNotifyMin,
Chris@152 267 m_sinceLastNotifyMax + m_resolution);
Chris@152 268 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
Chris@152 269 } else {
Chris@152 270 emit completionChanged();
Chris@152 271 }
Chris@152 272 } else {
Chris@152 273 emit completionChanged();
Chris@152 274 }
Chris@152 275 }
Chris@152 276 }
Chris@152 277
Chris@318 278 QString
Chris@318 279 EditableDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter) const
Chris@318 280 {
Chris@318 281 QString s;
Chris@318 282 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@318 283 QStringList list;
Chris@318 284 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@318 285 list << QString("%1").arg(m_data[i][j]);
Chris@318 286 }
Chris@318 287 s += list.join(delimiter) + "\n";
Chris@318 288 }
Chris@318 289 return s;
Chris@318 290 }
Chris@318 291
Chris@152 292 void
Chris@152 293 EditableDenseThreeDimensionalModel::toXml(QTextStream &out,
Chris@314 294 QString indent,
Chris@314 295 QString extraAttributes) const
Chris@152 296 {
Chris@152 297 // For historical reasons we read and write "resolution" as "windowSize"
Chris@152 298
Chris@318 299 std::cerr << "EditableDenseThreeDimensionalModel::toXml" << std::endl;
Chris@318 300
Chris@314 301 Model::toXml
Chris@314 302 (out, indent,
Chris@314 303 QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6")
Chris@152 304 .arg(m_resolution)
Chris@152 305 .arg(m_yBinCount)
Chris@152 306 .arg(m_minimum)
Chris@152 307 .arg(m_maximum)
Chris@152 308 .arg(getObjectExportId(&m_data))
Chris@152 309 .arg(extraAttributes));
Chris@152 310
Chris@152 311 out << indent;
Chris@152 312 out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n")
Chris@152 313 .arg(getObjectExportId(&m_data));
Chris@152 314
Chris@152 315 for (size_t i = 0; i < m_binNames.size(); ++i) {
Chris@152 316 if (m_binNames[i] != "") {
Chris@152 317 out << indent + " ";
Chris@152 318 out << QString("<bin number=\"%1\" name=\"%2\"/>\n")
Chris@152 319 .arg(i).arg(m_binNames[i]);
Chris@152 320 }
Chris@152 321 }
Chris@152 322
Chris@152 323 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@152 324 out << indent + " ";
Chris@152 325 out << QString("<row n=\"%1\">").arg(i);
Chris@152 326 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@152 327 if (j > 0) out << " ";
Chris@152 328 out << m_data[i][j];
Chris@152 329 }
Chris@152 330 out << QString("</row>\n");
Chris@318 331 out.flush();
Chris@152 332 }
Chris@152 333
Chris@152 334 out << indent + "</dataset>\n";
Chris@152 335 }
Chris@152 336
Chris@152 337