annotate data/model/Dense3DModelPeakCache.cpp @ 1777:d484490cdf69

Split EditableDenseThreeDimensionalModel into explicitly compressed and uncompressed variants. Simplifies the uncompressed version, and we may want to consider whether we need the compressed one at all.
author Chris Cannam
date Tue, 10 Sep 2019 16:34:47 +0100
parents 6d09d68165a4
children 59d9dcfd67c2
rev   line source
Chris@545 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@545 2
Chris@545 3 /*
Chris@545 4 Sonic Visualiser
Chris@545 5 An audio file viewer and annotation editor.
Chris@545 6 Centre for Digital Music, Queen Mary, University of London.
Chris@545 7 This file copyright 2009 QMUL.
Chris@545 8
Chris@545 9 This program is free software; you can redistribute it and/or
Chris@545 10 modify it under the terms of the GNU General Public License as
Chris@545 11 published by the Free Software Foundation; either version 2 of the
Chris@545 12 License, or (at your option) any later version. See the file
Chris@545 13 COPYING included with this distribution for more information.
Chris@545 14 */
Chris@545 15
Chris@545 16 #include "Dense3DModelPeakCache.h"
Chris@545 17
Chris@551 18 #include "base/Profiler.h"
Chris@551 19
Chris@1340 20 #include "base/HitCount.h"
Chris@1340 21
Chris@1739 22 Dense3DModelPeakCache::Dense3DModelPeakCache(ModelId sourceId,
Chris@1429 23 int columnsPerPeak) :
Chris@1739 24 m_source(sourceId),
Chris@1190 25 m_columnsPerPeak(columnsPerPeak)
Chris@545 26 {
Chris@1739 27 auto source = ModelById::getAs<DenseThreeDimensionalModel>(m_source);
Chris@1739 28 if (!source) {
Chris@1739 29 SVCERR << "WARNING: Dense3DModelPeakCache constructed for unknown or wrong-type source model id " << m_source << endl;
Chris@1739 30 m_source = {};
Chris@1739 31 return;
Chris@1739 32 }
Chris@545 33
Chris@1739 34 m_cache.reset(new EditableDenseThreeDimensionalModel
Chris@1739 35 (source->getSampleRate(),
Chris@1739 36 source->getResolution() * m_columnsPerPeak,
Chris@1739 37 source->getHeight(),
Chris@1739 38 false));
Chris@1739 39
Chris@1752 40 connect(source.get(), SIGNAL(modelChanged(ModelId)),
Chris@1752 41 this, SLOT(sourceModelChanged(ModelId)));
Chris@545 42 }
Chris@545 43
Chris@545 44 Dense3DModelPeakCache::~Dense3DModelPeakCache()
Chris@545 45 {
Chris@545 46 }
Chris@545 47
Chris@545 48 Dense3DModelPeakCache::Column
Chris@929 49 Dense3DModelPeakCache::getColumn(int column) const
Chris@545 50 {
Chris@545 51 if (!haveColumn(column)) fillColumn(column);
Chris@545 52 return m_cache->getColumn(column);
Chris@545 53 }
Chris@545 54
Chris@545 55 float
Chris@929 56 Dense3DModelPeakCache::getValueAt(int column, int n) const
Chris@545 57 {
Chris@545 58 if (!haveColumn(column)) fillColumn(column);
Chris@545 59 return m_cache->getValueAt(column, n);
Chris@545 60 }
Chris@545 61
Chris@545 62 void
Chris@1752 63 Dense3DModelPeakCache::sourceModelChanged(ModelId)
Chris@545 64 {
Chris@546 65 if (m_coverage.size() > 0) {
Chris@546 66 // The last peak may have come from an incomplete read, which
Chris@546 67 // may since have been filled, so reset it
Chris@1153 68 m_coverage[m_coverage.size()-1] = false;
Chris@546 69 }
Chris@1153 70 m_coverage.resize(getWidth(), false); // retaining data
Chris@545 71 }
Chris@545 72
Chris@545 73 bool
Chris@929 74 Dense3DModelPeakCache::haveColumn(int column) const
Chris@545 75 {
Chris@1340 76 static HitCount count("Dense3DModelPeakCache");
Chris@1340 77 if (in_range_for(m_coverage, column) && m_coverage[column]) {
Chris@1340 78 count.hit();
Chris@1340 79 return true;
Chris@1340 80 } else {
Chris@1340 81 count.miss();
Chris@1340 82 return false;
Chris@1340 83 }
Chris@545 84 }
Chris@545 85
Chris@545 86 void
Chris@929 87 Dense3DModelPeakCache::fillColumn(int column) const
Chris@545 88 {
Chris@551 89 Profiler profiler("Dense3DModelPeakCache::fillColumn");
Chris@551 90
Chris@1153 91 if (!in_range_for(m_coverage, column)) {
Chris@1192 92 if (m_coverage.size() > 0) {
Chris@1192 93 // The last peak may have come from an incomplete read, which
Chris@1192 94 // may since have been filled, so reset it
Chris@1192 95 m_coverage[m_coverage.size()-1] = false;
Chris@1192 96 }
Chris@1153 97 m_coverage.resize(column + 1, false);
Chris@551 98 }
Chris@546 99
Chris@1739 100 auto source = ModelById::getAs<DenseThreeDimensionalModel>(m_source);
Chris@1739 101 if (!source) return;
Chris@1739 102
Chris@1739 103 int sourceWidth = source->getWidth();
Chris@1192 104
Chris@545 105 Column peak;
Chris@1156 106 int n = 0;
Chris@1190 107 for (int i = 0; i < m_columnsPerPeak; ++i) {
Chris@1192 108
Chris@1192 109 int sourceColumn = column * m_columnsPerPeak + i;
Chris@1192 110 if (sourceColumn >= sourceWidth) break;
Chris@1192 111
Chris@1739 112 Column here = source->getColumn(sourceColumn);
Chris@1192 113
Chris@1192 114 // cerr << "Dense3DModelPeakCache::fillColumn(" << column << "): source col "
Chris@1192 115 // << sourceColumn << " of " << sourceWidth
Chris@1192 116 // << " returned " << here.size() << " elts" << endl;
Chris@1192 117
Chris@545 118 if (i == 0) {
Chris@545 119 peak = here;
Chris@1156 120 n = int(peak.size());
Chris@545 121 } else {
Chris@1156 122 int m = std::min(n, int(here.size()));
Chris@1156 123 for (int j = 0; j < m; ++j) {
Chris@1156 124 peak[j] = std::max(here[j], peak[j]);
Chris@545 125 }
Chris@545 126 }
Chris@545 127 }
Chris@546 128
Chris@545 129 m_cache->setColumn(column, peak);
Chris@1153 130 m_coverage[column] = true;
Chris@545 131 }
Chris@545 132
Chris@545 133