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