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@545: Dense3DModelPeakCache::Dense3DModelPeakCache(DenseThreeDimensionalModel *source, Chris@929: int columnsPerPeak) : Chris@545: m_source(source), Chris@545: m_resolution(columnsPerPeak) Chris@545: { Chris@545: m_cache = new EditableDenseThreeDimensionalModel Chris@545: (source->getSampleRate(), Chris@545: getResolution(), Chris@545: source->getHeight(), Chris@545: EditableDenseThreeDimensionalModel::NoCompression, Chris@545: false); Chris@545: Chris@545: connect(source, SIGNAL(modelChanged()), Chris@545: this, SLOT(sourceModelChanged())); Chris@546: connect(source, SIGNAL(aboutToBeDeleted()), Chris@545: this, SLOT(sourceModelAboutToBeDeleted())); Chris@545: Chris@545: } Chris@545: Chris@545: Dense3DModelPeakCache::~Dense3DModelPeakCache() Chris@545: { Chris@545: delete m_cache; Chris@545: } Chris@545: Chris@545: Dense3DModelPeakCache::Column Chris@929: Dense3DModelPeakCache::getColumn(int column) const Chris@545: { Chris@551: Profiler profiler("Dense3DModelPeakCache::getColumn"); Chris@545: if (!m_source) return Column(); Chris@545: if (!haveColumn(column)) fillColumn(column); Chris@545: return m_cache->getColumn(column); Chris@545: } Chris@545: Chris@545: float Chris@929: Dense3DModelPeakCache::getValueAt(int column, int n) const Chris@545: { Chris@545: if (!m_source) return 0.f; Chris@545: if (!haveColumn(column)) fillColumn(column); Chris@545: return m_cache->getValueAt(column, n); Chris@545: } Chris@545: Chris@545: void Chris@545: Dense3DModelPeakCache::sourceModelChanged() Chris@545: { Chris@545: if (!m_source) return; Chris@546: if (m_coverage.size() > 0) { Chris@546: // The last peak may have come from an incomplete read, which Chris@546: // may since have been filled, so reset it Chris@1153: m_coverage[m_coverage.size()-1] = false; Chris@546: } Chris@1153: m_coverage.resize(getWidth(), false); // retaining data Chris@545: } Chris@545: Chris@545: void Chris@545: Dense3DModelPeakCache::sourceModelAboutToBeDeleted() Chris@545: { Chris@545: m_source = 0; Chris@545: } Chris@545: Chris@545: bool Chris@929: Dense3DModelPeakCache::haveColumn(int column) const Chris@545: { Chris@1153: return in_range_for(m_coverage, column) && m_coverage[column]; 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@551: // see note in sourceModelChanged Chris@1153: if (m_coverage.size() > 0) m_coverage[m_coverage.size()-1] = false; Chris@1153: m_coverage.resize(column + 1, false); Chris@551: } Chris@546: Chris@545: Column peak; Chris@1153: for (int i = 0; i < m_resolution; ++i) { Chris@545: Column here = m_source->getColumn(column * m_resolution + i); Chris@545: if (i == 0) { Chris@545: peak = here; Chris@545: } else { Chris@1153: for (int j = 0; in_range_for(peak, j) && in_range_for(here, j); ++j) { Chris@545: if (here[j] > peak[j]) peak[j] = here[j]; Chris@545: } Chris@545: } Chris@545: } Chris@546: Chris@545: m_cache->setColumn(column, peak); Chris@1153: m_coverage[column] = true; Chris@545: } Chris@545: Chris@545: