annotate data/model/Dense3DModelPeakCache.cpp @ 1455:ec9e65fcf749

The use of the begin/end pairs here just seems to cause too many rows to be deleted (from the visual representation, not the underlying model). Things apparently work better if we just modify the underlying model and let the change signals percolate back up again. To that end, update the change handlers so as to cover their proper ranges with dataChanged signals.
author Chris Cannam
date Mon, 23 Apr 2018 16:03:35 +0100
parents 48e9f538e6e9
children 70e172e6cc59
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@1191 22 Dense3DModelPeakCache::Dense3DModelPeakCache(const DenseThreeDimensionalModel *source,
Chris@1429 23 int columnsPerPeak) :
Chris@545 24 m_source(source),
Chris@1190 25 m_columnsPerPeak(columnsPerPeak)
Chris@545 26 {
Chris@545 27 m_cache = new EditableDenseThreeDimensionalModel
Chris@545 28 (source->getSampleRate(),
Chris@545 29 getResolution(),
Chris@545 30 source->getHeight(),
Chris@545 31 EditableDenseThreeDimensionalModel::NoCompression,
Chris@545 32 false);
Chris@545 33
Chris@545 34 connect(source, SIGNAL(modelChanged()),
Chris@545 35 this, SLOT(sourceModelChanged()));
Chris@546 36 connect(source, SIGNAL(aboutToBeDeleted()),
Chris@545 37 this, SLOT(sourceModelAboutToBeDeleted()));
Chris@545 38 }
Chris@545 39
Chris@545 40 Dense3DModelPeakCache::~Dense3DModelPeakCache()
Chris@545 41 {
Chris@1384 42 if (m_cache) m_cache->aboutToDelete();
Chris@545 43 delete m_cache;
Chris@545 44 }
Chris@545 45
Chris@545 46 Dense3DModelPeakCache::Column
Chris@929 47 Dense3DModelPeakCache::getColumn(int column) const
Chris@545 48 {
Chris@545 49 if (!m_source) return Column();
Chris@545 50 if (!haveColumn(column)) fillColumn(column);
Chris@545 51 return m_cache->getColumn(column);
Chris@545 52 }
Chris@545 53
Chris@545 54 float
Chris@929 55 Dense3DModelPeakCache::getValueAt(int column, int n) const
Chris@545 56 {
Chris@545 57 if (!m_source) return 0.f;
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@545 63 Dense3DModelPeakCache::sourceModelChanged()
Chris@545 64 {
Chris@545 65 if (!m_source) return;
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 void
Chris@545 75 Dense3DModelPeakCache::sourceModelAboutToBeDeleted()
Chris@545 76 {
Chris@545 77 m_source = 0;
Chris@545 78 }
Chris@545 79
Chris@545 80 bool
Chris@929 81 Dense3DModelPeakCache::haveColumn(int column) const
Chris@545 82 {
Chris@1340 83 static HitCount count("Dense3DModelPeakCache");
Chris@1340 84 if (in_range_for(m_coverage, column) && m_coverage[column]) {
Chris@1340 85 count.hit();
Chris@1340 86 return true;
Chris@1340 87 } else {
Chris@1340 88 count.miss();
Chris@1340 89 return false;
Chris@1340 90 }
Chris@545 91 }
Chris@545 92
Chris@545 93 void
Chris@929 94 Dense3DModelPeakCache::fillColumn(int column) const
Chris@545 95 {
Chris@551 96 Profiler profiler("Dense3DModelPeakCache::fillColumn");
Chris@551 97
Chris@1153 98 if (!in_range_for(m_coverage, column)) {
Chris@1192 99 if (m_coverage.size() > 0) {
Chris@1192 100 // The last peak may have come from an incomplete read, which
Chris@1192 101 // may since have been filled, so reset it
Chris@1192 102 m_coverage[m_coverage.size()-1] = false;
Chris@1192 103 }
Chris@1153 104 m_coverage.resize(column + 1, false);
Chris@551 105 }
Chris@546 106
Chris@1192 107 int sourceWidth = m_source->getWidth();
Chris@1192 108
Chris@545 109 Column peak;
Chris@1156 110 int n = 0;
Chris@1190 111 for (int i = 0; i < m_columnsPerPeak; ++i) {
Chris@1192 112
Chris@1192 113 int sourceColumn = column * m_columnsPerPeak + i;
Chris@1192 114 if (sourceColumn >= sourceWidth) break;
Chris@1192 115
Chris@1192 116 Column here = m_source->getColumn(sourceColumn);
Chris@1192 117
Chris@1192 118 // cerr << "Dense3DModelPeakCache::fillColumn(" << column << "): source col "
Chris@1192 119 // << sourceColumn << " of " << sourceWidth
Chris@1192 120 // << " returned " << here.size() << " elts" << endl;
Chris@1192 121
Chris@545 122 if (i == 0) {
Chris@545 123 peak = here;
Chris@1156 124 n = int(peak.size());
Chris@545 125 } else {
Chris@1156 126 int m = std::min(n, int(here.size()));
Chris@1156 127 for (int j = 0; j < m; ++j) {
Chris@1156 128 peak[j] = std::max(here[j], peak[j]);
Chris@545 129 }
Chris@545 130 }
Chris@545 131 }
Chris@546 132
Chris@545 133 m_cache->setColumn(column, peak);
Chris@1153 134 m_coverage[column] = true;
Chris@545 135 }
Chris@545 136
Chris@545 137