lbajardsilogic@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: Sonic Visualiser lbajardsilogic@0: An audio file viewer and annotation editor. lbajardsilogic@0: Centre for Digital Music, Queen Mary, University of London. lbajardsilogic@0: This file copyright 2006 Chris Cannam and QMUL. lbajardsilogic@0: lbajardsilogic@0: This program is free software; you can redistribute it and/or lbajardsilogic@0: modify it under the terms of the GNU General Public License as lbajardsilogic@0: published by the Free Software Foundation; either version 2 of the lbajardsilogic@0: License, or (at your option) any later version. See the file lbajardsilogic@0: COPYING included with this distribution for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: #include "EditableDenseThreeDimensionalModel.h" lbajardsilogic@0: #include "system/System.h" lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate, lbajardsilogic@0: size_t resolution, lbajardsilogic@0: size_t yBinCount, lbajardsilogic@0: bool notifyOnAdd) : lbajardsilogic@0: m_sampleRate(sampleRate), lbajardsilogic@0: m_resolution(resolution), lbajardsilogic@0: m_yBinCount(yBinCount), lbajardsilogic@0: m_minimum(0.0), lbajardsilogic@0: m_maximum(0.0), lbajardsilogic@0: m_haveExtents(false), lbajardsilogic@0: m_notifyOnAdd(notifyOnAdd), lbajardsilogic@0: m_sinceLastNotifyMin(-1), lbajardsilogic@0: m_sinceLastNotifyMax(-1), lbajardsilogic@0: m_completion(100) lbajardsilogic@0: { lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool lbajardsilogic@0: EditableDenseThreeDimensionalModel::isOK() const lbajardsilogic@0: { lbajardsilogic@0: return true; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: size_t lbajardsilogic@0: EditableDenseThreeDimensionalModel::getSampleRate() const lbajardsilogic@0: { lbajardsilogic@0: return m_sampleRate; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: size_t lbajardsilogic@0: EditableDenseThreeDimensionalModel::getStartFrame() const lbajardsilogic@0: { lbajardsilogic@0: return 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: size_t lbajardsilogic@0: EditableDenseThreeDimensionalModel::getEndFrame() const lbajardsilogic@0: { lbajardsilogic@0: return m_resolution * m_data.size() + (m_resolution - 1); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Model * lbajardsilogic@0: EditableDenseThreeDimensionalModel::clone() const lbajardsilogic@0: { lbajardsilogic@0: EditableDenseThreeDimensionalModel *model = lbajardsilogic@0: new EditableDenseThreeDimensionalModel lbajardsilogic@0: (m_sampleRate, m_resolution, m_yBinCount); lbajardsilogic@0: lbajardsilogic@0: model->m_minimum = m_minimum; lbajardsilogic@0: model->m_maximum = m_maximum; lbajardsilogic@0: model->m_haveExtents = m_haveExtents; lbajardsilogic@0: lbajardsilogic@0: for (size_t i = 0; i < m_data.size(); ++i) { lbajardsilogic@0: model->setColumn(i, m_data[i]); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return model; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: size_t lbajardsilogic@0: EditableDenseThreeDimensionalModel::getResolution() const lbajardsilogic@0: { lbajardsilogic@0: return m_resolution; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: EditableDenseThreeDimensionalModel::setResolution(size_t sz) lbajardsilogic@0: { lbajardsilogic@0: m_resolution = sz; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: size_t lbajardsilogic@0: EditableDenseThreeDimensionalModel::getWidth() const lbajardsilogic@0: { lbajardsilogic@0: return m_data.size(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: size_t lbajardsilogic@0: EditableDenseThreeDimensionalModel::getHeight() const lbajardsilogic@0: { lbajardsilogic@0: return m_yBinCount; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: EditableDenseThreeDimensionalModel::setHeight(size_t sz) lbajardsilogic@0: { lbajardsilogic@0: m_yBinCount = sz; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: float lbajardsilogic@0: EditableDenseThreeDimensionalModel::getMinimumLevel() const lbajardsilogic@0: { lbajardsilogic@0: return m_minimum; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: EditableDenseThreeDimensionalModel::setMinimumLevel(float level) lbajardsilogic@0: { lbajardsilogic@0: m_minimum = level; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: float lbajardsilogic@0: EditableDenseThreeDimensionalModel::getMaximumLevel() const lbajardsilogic@0: { lbajardsilogic@0: return m_maximum; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: EditableDenseThreeDimensionalModel::setMaximumLevel(float level) lbajardsilogic@0: { lbajardsilogic@0: m_maximum = level; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: EditableDenseThreeDimensionalModel::getColumn(size_t index, lbajardsilogic@0: Column &result) const lbajardsilogic@0: { lbajardsilogic@0: QMutexLocker locker(&m_mutex); lbajardsilogic@0: lbajardsilogic@0: if (index < m_data.size()) { lbajardsilogic@0: result = m_data[index]; lbajardsilogic@0: } else { lbajardsilogic@0: result.clear(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: while (result.size() < m_yBinCount) result.push_back(m_minimum); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: float lbajardsilogic@0: EditableDenseThreeDimensionalModel::getValueAt(size_t index, size_t n) const lbajardsilogic@0: { lbajardsilogic@0: QMutexLocker locker(&m_mutex); lbajardsilogic@0: lbajardsilogic@0: if (index < m_data.size()) { lbajardsilogic@0: const Column &s = m_data[index]; lbajardsilogic@0: // std::cerr << "index " << index << ", n " << n << ", res " << m_resolution << ", size " << s.size() lbajardsilogic@0: // << std::endl; lbajardsilogic@0: if (n < s.size()) return s[n]; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return m_minimum; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: EditableDenseThreeDimensionalModel::setColumn(size_t index, lbajardsilogic@0: const Column &values) lbajardsilogic@0: { lbajardsilogic@0: QMutexLocker locker(&m_mutex); lbajardsilogic@0: lbajardsilogic@0: while (index >= m_data.size()) { lbajardsilogic@0: m_data.push_back(Column()); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool allChange = false; lbajardsilogic@0: lbajardsilogic@0: for (size_t i = 0; i < values.size(); ++i) { lbajardsilogic@0: float value = values[i]; lbajardsilogic@0: if (isnan(value) || isinf(value)) { lbajardsilogic@0: continue; lbajardsilogic@0: } lbajardsilogic@0: if (!m_haveExtents || value < m_minimum) { lbajardsilogic@0: m_minimum = value; lbajardsilogic@0: allChange = true; lbajardsilogic@0: } lbajardsilogic@0: if (!m_haveExtents || value > m_maximum) { lbajardsilogic@0: m_maximum = value; lbajardsilogic@0: allChange = true; lbajardsilogic@0: } lbajardsilogic@0: m_haveExtents = true; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_data[index] = values; lbajardsilogic@0: lbajardsilogic@0: long windowStart = index; lbajardsilogic@0: windowStart *= m_resolution; lbajardsilogic@0: lbajardsilogic@0: if (m_notifyOnAdd) { lbajardsilogic@0: if (allChange) { lbajardsilogic@0: emit modelChanged(); lbajardsilogic@0: } else { lbajardsilogic@0: emit modelChanged(windowStart, windowStart + m_resolution); lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: if (allChange) { lbajardsilogic@0: m_sinceLastNotifyMin = -1; lbajardsilogic@0: m_sinceLastNotifyMax = -1; lbajardsilogic@0: emit modelChanged(); lbajardsilogic@0: } else { lbajardsilogic@0: if (m_sinceLastNotifyMin == -1 || lbajardsilogic@0: windowStart < m_sinceLastNotifyMin) { lbajardsilogic@0: m_sinceLastNotifyMin = windowStart; lbajardsilogic@0: } lbajardsilogic@0: if (m_sinceLastNotifyMax == -1 || lbajardsilogic@0: windowStart > m_sinceLastNotifyMax) { lbajardsilogic@0: m_sinceLastNotifyMax = windowStart; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString lbajardsilogic@0: EditableDenseThreeDimensionalModel::getBinName(size_t n) const lbajardsilogic@0: { lbajardsilogic@0: if (m_binNames.size() > n) return m_binNames[n]; lbajardsilogic@0: else return ""; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: EditableDenseThreeDimensionalModel::setBinName(size_t n, QString name) lbajardsilogic@0: { lbajardsilogic@0: while (m_binNames.size() <= n) m_binNames.push_back(""); lbajardsilogic@0: m_binNames[n] = name; lbajardsilogic@0: emit modelChanged(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: EditableDenseThreeDimensionalModel::setBinNames(std::vector names) lbajardsilogic@0: { lbajardsilogic@0: m_binNames = names; lbajardsilogic@0: emit modelChanged(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: EditableDenseThreeDimensionalModel::setCompletion(int completion) lbajardsilogic@0: { lbajardsilogic@0: if (m_completion != completion) { lbajardsilogic@0: m_completion = completion; lbajardsilogic@0: lbajardsilogic@0: if (completion == 100) { lbajardsilogic@0: lbajardsilogic@0: m_notifyOnAdd = true; // henceforth lbajardsilogic@0: emit modelChanged(); lbajardsilogic@0: lbajardsilogic@0: } else if (!m_notifyOnAdd) { lbajardsilogic@0: lbajardsilogic@0: if (m_sinceLastNotifyMin >= 0 && lbajardsilogic@0: m_sinceLastNotifyMax >= 0) { lbajardsilogic@0: emit modelChanged(m_sinceLastNotifyMin, lbajardsilogic@0: m_sinceLastNotifyMax + m_resolution); lbajardsilogic@0: m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1; lbajardsilogic@0: } else { lbajardsilogic@0: emit completionChanged(); lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: emit completionChanged(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: EditableDenseThreeDimensionalModel::toXml(QTextStream &out, lbajardsilogic@0: QString indent, lbajardsilogic@0: QString extraAttributes) const lbajardsilogic@0: { lbajardsilogic@0: // For historical reasons we read and write "resolution" as "windowSize" lbajardsilogic@0: lbajardsilogic@0: out << Model::toXmlString lbajardsilogic@0: (indent, QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6") lbajardsilogic@0: .arg(m_resolution) lbajardsilogic@0: .arg(m_yBinCount) lbajardsilogic@0: .arg(m_minimum) lbajardsilogic@0: .arg(m_maximum) lbajardsilogic@0: .arg(getObjectExportId(&m_data)) lbajardsilogic@0: .arg(extraAttributes)); lbajardsilogic@0: lbajardsilogic@0: out << indent; lbajardsilogic@0: out << QString("\n") lbajardsilogic@0: .arg(getObjectExportId(&m_data)); lbajardsilogic@0: lbajardsilogic@0: for (size_t i = 0; i < m_binNames.size(); ++i) { lbajardsilogic@0: if (m_binNames[i] != "") { lbajardsilogic@0: out << indent + " "; lbajardsilogic@0: out << QString("\n") lbajardsilogic@0: .arg(i).arg(m_binNames[i]); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: for (size_t i = 0; i < m_data.size(); ++i) { lbajardsilogic@0: out << indent + " "; lbajardsilogic@0: out << QString("").arg(i); lbajardsilogic@0: for (size_t j = 0; j < m_data[i].size(); ++j) { lbajardsilogic@0: if (j > 0) out << " "; lbajardsilogic@0: out << m_data[i][j]; lbajardsilogic@0: } lbajardsilogic@0: out << QString("\n"); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: out << indent + "\n"; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString lbajardsilogic@0: EditableDenseThreeDimensionalModel::toXmlString(QString indent, lbajardsilogic@0: QString extraAttributes) const lbajardsilogic@0: { lbajardsilogic@0: QString s; lbajardsilogic@0: lbajardsilogic@0: { lbajardsilogic@0: QTextStream out(&s); lbajardsilogic@0: toXml(out, indent, extraAttributes); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: return s; lbajardsilogic@0: } lbajardsilogic@0: