annotate data/model/Dense3DModelPeakCache.cpp @ 1008:d9e0e59a1581

When using an aggregate model to pass data to a transform, zero-pad the shorter input to the duration of the longer rather than truncating the longer. (This is better behaviour for e.g. MATCH, and in any case the code was previously truncating incorrectly and ending up with garbage data at the end.)
author Chris Cannam
date Fri, 14 Nov 2014 13:51:33 +0000
parents 59e7fe1b1003
children ece369c5bb68
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@545 20 Dense3DModelPeakCache::Dense3DModelPeakCache(DenseThreeDimensionalModel *source,
Chris@929 21 int columnsPerPeak) :
Chris@545 22 m_source(source),
Chris@545 23 m_resolution(columnsPerPeak)
Chris@545 24 {
Chris@546 25 m_coverage.resize(1); // otherwise it is simply invalid
Chris@546 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
Chris@545 41 Dense3DModelPeakCache::~Dense3DModelPeakCache()
Chris@545 42 {
Chris@545 43 delete m_cache;
Chris@545 44 }
Chris@545 45
Chris@545 46 bool
Chris@929 47 Dense3DModelPeakCache::isColumnAvailable(int column) const
Chris@545 48 {
Chris@545 49 if (!m_source) return false;
Chris@545 50 if (haveColumn(column)) return true;
Chris@552 51 for (int i = m_resolution; i > 0; ) {
Chris@552 52 --i;
Chris@545 53 if (!m_source->isColumnAvailable(column * m_resolution + i)) {
Chris@545 54 return false;
Chris@545 55 }
Chris@545 56 }
Chris@545 57 return true;
Chris@545 58 }
Chris@545 59
Chris@545 60 Dense3DModelPeakCache::Column
Chris@929 61 Dense3DModelPeakCache::getColumn(int column) const
Chris@545 62 {
Chris@551 63 Profiler profiler("Dense3DModelPeakCache::getColumn");
Chris@545 64 if (!m_source) return Column();
Chris@545 65 if (!haveColumn(column)) fillColumn(column);
Chris@545 66 return m_cache->getColumn(column);
Chris@545 67 }
Chris@545 68
Chris@545 69 float
Chris@929 70 Dense3DModelPeakCache::getValueAt(int column, int n) const
Chris@545 71 {
Chris@545 72 if (!m_source) return 0.f;
Chris@545 73 if (!haveColumn(column)) fillColumn(column);
Chris@545 74 return m_cache->getValueAt(column, n);
Chris@545 75 }
Chris@545 76
Chris@545 77 void
Chris@545 78 Dense3DModelPeakCache::sourceModelChanged()
Chris@545 79 {
Chris@545 80 if (!m_source) return;
Chris@546 81 if (m_coverage.size() > 0) {
Chris@546 82 // The last peak may have come from an incomplete read, which
Chris@546 83 // may since have been filled, so reset it
Chris@546 84 m_coverage.reset(m_coverage.size()-1);
Chris@546 85 }
Chris@548 86 m_coverage.resize(getWidth()); // retaining data
Chris@545 87 }
Chris@545 88
Chris@545 89 void
Chris@545 90 Dense3DModelPeakCache::sourceModelAboutToBeDeleted()
Chris@545 91 {
Chris@545 92 m_source = 0;
Chris@545 93 }
Chris@545 94
Chris@545 95 bool
Chris@929 96 Dense3DModelPeakCache::haveColumn(int column) const
Chris@545 97 {
Chris@929 98 return column < (int)m_coverage.size() && m_coverage.get(column);
Chris@545 99 }
Chris@545 100
Chris@545 101 void
Chris@929 102 Dense3DModelPeakCache::fillColumn(int column) const
Chris@545 103 {
Chris@551 104 Profiler profiler("Dense3DModelPeakCache::fillColumn");
Chris@551 105
Chris@929 106 if (column >= (int)m_coverage.size()) {
Chris@551 107 // see note in sourceModelChanged
Chris@551 108 if (m_coverage.size() > 0) m_coverage.reset(m_coverage.size()-1);
Chris@551 109 m_coverage.resize(column + 1);
Chris@551 110 }
Chris@546 111
Chris@545 112 Column peak;
Chris@929 113 for (int i = 0; i < int(m_resolution); ++i) {
Chris@545 114 Column here = m_source->getColumn(column * m_resolution + i);
Chris@545 115 if (i == 0) {
Chris@545 116 peak = here;
Chris@545 117 } else {
Chris@929 118 for (int j = 0; j < (int)peak.size() && j < (int)here.size(); ++j) {
Chris@545 119 if (here[j] > peak[j]) peak[j] = here[j];
Chris@545 120 }
Chris@545 121 }
Chris@545 122 }
Chris@546 123
Chris@545 124 m_cache->setColumn(column, peak);
Chris@545 125 m_coverage.set(column);
Chris@545 126 }
Chris@545 127
Chris@545 128