1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
Sonic Visualiser
An audio file viewer and annotation editor.
Centre for Digital Music, Queen Mary, University of London.
This file copyright 2009 QMUL.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version. See the file
COPYING included with this distribution for more information.
*/
#include "Dense3DModelPeakCache.h"
#include "base/Profiler.h"
Dense3DModelPeakCache::Dense3DModelPeakCache(DenseThreeDimensionalModel *source,
int columnsPerPeak) :
m_source(source),
m_resolution(columnsPerPeak)
{
m_coverage.resize(1); // otherwise it is simply invalid
m_cache = new EditableDenseThreeDimensionalModel
(source->getSampleRate(),
getResolution(),
source->getHeight(),
EditableDenseThreeDimensionalModel::NoCompression,
false);
connect(source, SIGNAL(modelChanged()),
this, SLOT(sourceModelChanged()));
connect(source, SIGNAL(aboutToBeDeleted()),
this, SLOT(sourceModelAboutToBeDeleted()));
}
Dense3DModelPeakCache::~Dense3DModelPeakCache()
{
delete m_cache;
}
bool
Dense3DModelPeakCache::isColumnAvailable(int column) const
{
if (!m_source) return false;
if (haveColumn(column)) return true;
for (int i = m_resolution; i > 0; ) {
--i;
if (!m_source->isColumnAvailable(column * m_resolution + i)) {
return false;
}
}
return true;
}
Dense3DModelPeakCache::Column
Dense3DModelPeakCache::getColumn(int column) const
{
Profiler profiler("Dense3DModelPeakCache::getColumn");
if (!m_source) return Column();
if (!haveColumn(column)) fillColumn(column);
return m_cache->getColumn(column);
}
float
Dense3DModelPeakCache::getValueAt(int column, int n) const
{
if (!m_source) return 0.f;
if (!haveColumn(column)) fillColumn(column);
return m_cache->getValueAt(column, n);
}
void
Dense3DModelPeakCache::sourceModelChanged()
{
if (!m_source) return;
if (m_coverage.size() > 0) {
// The last peak may have come from an incomplete read, which
// may since have been filled, so reset it
m_coverage.reset(m_coverage.size()-1);
}
m_coverage.resize(getWidth()); // retaining data
}
void
Dense3DModelPeakCache::sourceModelAboutToBeDeleted()
{
m_source = 0;
}
bool
Dense3DModelPeakCache::haveColumn(int column) const
{
return column < (int)m_coverage.size() && m_coverage.get(column);
}
void
Dense3DModelPeakCache::fillColumn(int column) const
{
Profiler profiler("Dense3DModelPeakCache::fillColumn");
if (column >= (int)m_coverage.size()) {
// see note in sourceModelChanged
if (m_coverage.size() > 0) m_coverage.reset(m_coverage.size()-1);
m_coverage.resize(column + 1);
}
Column peak;
for (int i = 0; i < int(m_resolution); ++i) {
Column here = m_source->getColumn(column * m_resolution + i);
if (i == 0) {
peak = here;
} else {
for (int j = 0; j < (int)peak.size() && j < (int)here.size(); ++j) {
if (here[j] > peak[j]) peak[j] = here[j];
}
}
}
m_cache->setColumn(column, peak);
m_coverage.set(column);
}
|