Chris@545: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@545: Chris@545: /* Chris@545: Sonic Visualiser Chris@545: An audio file viewer and annotation editor. Chris@545: Centre for Digital Music, Queen Mary, University of London. Chris@545: This file copyright 2009 QMUL. Chris@545: Chris@545: This program is free software; you can redistribute it and/or Chris@545: modify it under the terms of the GNU General Public License as Chris@545: published by the Free Software Foundation; either version 2 of the Chris@545: License, or (at your option) any later version. See the file Chris@545: COPYING included with this distribution for more information. Chris@545: */ Chris@545: Chris@545: #include "Dense3DModelPeakCache.h" Chris@545: Chris@551: #include "base/Profiler.h" Chris@551: Chris@1340: #include "base/HitCount.h" Chris@1340: Chris@1739: Dense3DModelPeakCache::Dense3DModelPeakCache(ModelId sourceId, Chris@1429: int columnsPerPeak) : Chris@1739: m_source(sourceId), Chris@1778: m_columnsPerPeak(columnsPerPeak), Chris@1778: m_finalColumnIncomplete(false) Chris@545: { Chris@1739: auto source = ModelById::getAs(m_source); Chris@1739: if (!source) { Chris@1739: SVCERR << "WARNING: Dense3DModelPeakCache constructed for unknown or wrong-type source model id " << m_source << endl; Chris@1739: m_source = {}; Chris@1739: return; Chris@1739: } Chris@545: Chris@1752: connect(source.get(), SIGNAL(modelChanged(ModelId)), Chris@1752: this, SLOT(sourceModelChanged(ModelId))); Chris@545: } Chris@545: Chris@545: Dense3DModelPeakCache::~Dense3DModelPeakCache() Chris@545: { Chris@545: } Chris@545: Chris@545: Dense3DModelPeakCache::Column Chris@929: Dense3DModelPeakCache::getColumn(int column) const Chris@545: { Chris@545: if (!haveColumn(column)) fillColumn(column); Chris@1778: return m_cache.at(column); Chris@545: } Chris@545: Chris@545: float Chris@929: Dense3DModelPeakCache::getValueAt(int column, int n) const Chris@545: { Chris@545: if (!haveColumn(column)) fillColumn(column); Chris@1778: return m_cache.at(column).at(n); Chris@545: } Chris@545: Chris@545: void Chris@1752: Dense3DModelPeakCache::sourceModelChanged(ModelId) Chris@545: { Chris@1778: if (m_finalColumnIncomplete && m_coverage.size() > 0) { Chris@1778: // The last peak came from an incomplete read, which may since Chris@1778: // have been filled, so reset it Chris@1153: m_coverage[m_coverage.size()-1] = false; Chris@1778: m_finalColumnIncomplete = false; Chris@546: } Chris@545: } Chris@545: Chris@545: bool Chris@929: Dense3DModelPeakCache::haveColumn(int column) const Chris@545: { Chris@1340: static HitCount count("Dense3DModelPeakCache"); Chris@1340: if (in_range_for(m_coverage, column) && m_coverage[column]) { Chris@1340: count.hit(); Chris@1340: return true; Chris@1340: } else { Chris@1340: count.miss(); Chris@1340: return false; Chris@1340: } Chris@545: } Chris@545: Chris@545: void Chris@929: Dense3DModelPeakCache::fillColumn(int column) const Chris@545: { Chris@551: Profiler profiler("Dense3DModelPeakCache::fillColumn"); Chris@551: Chris@1153: if (!in_range_for(m_coverage, column)) { Chris@1778: if (m_finalColumnIncomplete && m_coverage.size() > 0) { Chris@1192: // The last peak may have come from an incomplete read, which Chris@1192: // may since have been filled, so reset it Chris@1192: m_coverage[m_coverage.size()-1] = false; Chris@1778: m_finalColumnIncomplete = false; Chris@1192: } Chris@1153: m_coverage.resize(column + 1, false); Chris@1778: m_cache.resize(column + 1, {}); Chris@1778: } Chris@1778: Chris@1778: auto source = ModelById::getAs(m_source); Chris@1778: if (!source) { Chris@1778: return; Chris@1778: } Chris@1778: Chris@1778: int sourceWidth = source->getWidth(); Chris@1778: int sourceColumn = column * m_columnsPerPeak; Chris@1778: if (sourceColumn >= sourceWidth) { Chris@1778: return; Chris@551: } Chris@546: Chris@1778: Column peak = source->getColumn(sourceColumn); Chris@1778: int n = int(peak.size()); Chris@1739: Chris@1778: for (int i = 1; i < m_columnsPerPeak; ++i) { Chris@1192: Chris@1778: ++sourceColumn; Chris@1778: if (sourceColumn >= sourceWidth) { Chris@1778: m_finalColumnIncomplete = true; Chris@1778: break; Chris@1778: } Chris@1192: Chris@1739: Column here = source->getColumn(sourceColumn); Chris@1778: int m = std::min(n, int(here.size())); Chris@1778: for (int j = 0; j < m; ++j) { Chris@1778: peak[j] = std::max(here[j], peak[j]); Chris@545: } Chris@545: } Chris@546: Chris@1778: m_cache[column] = peak; Chris@1153: m_coverage[column] = true; Chris@545: } Chris@545: Chris@545: