annotate data/model/Dense3DModelPeakCache.cpp @ 1752:6d09d68165a4 by-id

Further review of ById: make IDs only available when adding a model to the ById store, not by querying the item directly. This means any id encountered in the wild must have been added to the store at some point (even if later released), which simplifies reasoning about lifecycles
author Chris Cannam
date Fri, 05 Jul 2019 15:28:07 +0100
parents 565575463752
children d484490cdf69
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 EditableDenseThreeDimensionalModel::NoCompression,
Chris@1739 39 false));
Chris@1739 40
Chris@1752 41 connect(source.get(), SIGNAL(modelChanged(ModelId)),
Chris@1752 42 this, SLOT(sourceModelChanged(ModelId)));
Chris@545 43 }
Chris@545 44
Chris@545 45 Dense3DModelPeakCache::~Dense3DModelPeakCache()
Chris@545 46 {
Chris@545 47 }
Chris@545 48
Chris@545 49 Dense3DModelPeakCache::Column
Chris@929 50 Dense3DModelPeakCache::getColumn(int column) const
Chris@545 51 {
Chris@545 52 if (!haveColumn(column)) fillColumn(column);
Chris@545 53 return m_cache->getColumn(column);
Chris@545 54 }
Chris@545 55
Chris@545 56 float
Chris@929 57 Dense3DModelPeakCache::getValueAt(int column, int n) const
Chris@545 58 {
Chris@545 59 if (!haveColumn(column)) fillColumn(column);
Chris@545 60 return m_cache->getValueAt(column, n);
Chris@545 61 }
Chris@545 62
Chris@545 63 void
Chris@1752 64 Dense3DModelPeakCache::sourceModelChanged(ModelId)
Chris@545 65 {
Chris@546 66 if (m_coverage.size() > 0) {
Chris@546 67 // The last peak may have come from an incomplete read, which
Chris@546 68 // may since have been filled, so reset it
Chris@1153 69 m_coverage[m_coverage.size()-1] = false;
Chris@546 70 }
Chris@1153 71 m_coverage.resize(getWidth(), false); // retaining data
Chris@545 72 }
Chris@545 73
Chris@545 74 bool
Chris@929 75 Dense3DModelPeakCache::haveColumn(int column) const
Chris@545 76 {
Chris@1340 77 static HitCount count("Dense3DModelPeakCache");
Chris@1340 78 if (in_range_for(m_coverage, column) && m_coverage[column]) {
Chris@1340 79 count.hit();
Chris@1340 80 return true;
Chris@1340 81 } else {
Chris@1340 82 count.miss();
Chris@1340 83 return false;
Chris@1340 84 }
Chris@545 85 }
Chris@545 86
Chris@545 87 void
Chris@929 88 Dense3DModelPeakCache::fillColumn(int column) const
Chris@545 89 {
Chris@551 90 Profiler profiler("Dense3DModelPeakCache::fillColumn");
Chris@551 91
Chris@1153 92 if (!in_range_for(m_coverage, column)) {
Chris@1192 93 if (m_coverage.size() > 0) {
Chris@1192 94 // The last peak may have come from an incomplete read, which
Chris@1192 95 // may since have been filled, so reset it
Chris@1192 96 m_coverage[m_coverage.size()-1] = false;
Chris@1192 97 }
Chris@1153 98 m_coverage.resize(column + 1, false);
Chris@551 99 }
Chris@546 100
Chris@1739 101 auto source = ModelById::getAs<DenseThreeDimensionalModel>(m_source);
Chris@1739 102 if (!source) return;
Chris@1739 103
Chris@1739 104 int sourceWidth = source->getWidth();
Chris@1192 105
Chris@545 106 Column peak;
Chris@1156 107 int n = 0;
Chris@1190 108 for (int i = 0; i < m_columnsPerPeak; ++i) {
Chris@1192 109
Chris@1192 110 int sourceColumn = column * m_columnsPerPeak + i;
Chris@1192 111 if (sourceColumn >= sourceWidth) break;
Chris@1192 112
Chris@1739 113 Column here = source->getColumn(sourceColumn);
Chris@1192 114
Chris@1192 115 // cerr << "Dense3DModelPeakCache::fillColumn(" << column << "): source col "
Chris@1192 116 // << sourceColumn << " of " << sourceWidth
Chris@1192 117 // << " returned " << here.size() << " elts" << endl;
Chris@1192 118
Chris@545 119 if (i == 0) {
Chris@545 120 peak = here;
Chris@1156 121 n = int(peak.size());
Chris@545 122 } else {
Chris@1156 123 int m = std::min(n, int(here.size()));
Chris@1156 124 for (int j = 0; j < m; ++j) {
Chris@1156 125 peak[j] = std::max(here[j], peak[j]);
Chris@545 126 }
Chris@545 127 }
Chris@545 128 }
Chris@546 129
Chris@545 130 m_cache->setColumn(column, peak);
Chris@1153 131 m_coverage[column] = true;
Chris@545 132 }
Chris@545 133
Chris@545 134