svcore  1.9
Dense3DModelPeakCache.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2009 QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "Dense3DModelPeakCache.h"
00017 
00018 #include "base/Profiler.h"
00019 
00020 Dense3DModelPeakCache::Dense3DModelPeakCache(DenseThreeDimensionalModel *source,
00021                                              int columnsPerPeak) :
00022     m_source(source),
00023     m_resolution(columnsPerPeak)
00024 {
00025     m_coverage.resize(1); // otherwise it is simply invalid
00026 
00027     m_cache = new EditableDenseThreeDimensionalModel
00028         (source->getSampleRate(),
00029          getResolution(),
00030          source->getHeight(),
00031          EditableDenseThreeDimensionalModel::NoCompression,
00032          false);
00033 
00034     connect(source, SIGNAL(modelChanged()),
00035             this, SLOT(sourceModelChanged()));
00036     connect(source, SIGNAL(aboutToBeDeleted()),
00037             this, SLOT(sourceModelAboutToBeDeleted()));
00038 
00039 }
00040 
00041 Dense3DModelPeakCache::~Dense3DModelPeakCache()
00042 {
00043     delete m_cache;
00044 }
00045 
00046 bool
00047 Dense3DModelPeakCache::isColumnAvailable(int column) const
00048 {
00049     if (!m_source) return false;
00050     if (haveColumn(column)) return true;
00051     for (int i = m_resolution; i > 0; ) {
00052         --i;
00053         if (!m_source->isColumnAvailable(column * m_resolution + i)) {
00054             return false;
00055         }
00056     }
00057     return true;
00058 }
00059 
00060 Dense3DModelPeakCache::Column
00061 Dense3DModelPeakCache::getColumn(int column) const
00062 {
00063     Profiler profiler("Dense3DModelPeakCache::getColumn");
00064     if (!m_source) return Column();
00065     if (!haveColumn(column)) fillColumn(column);
00066     return m_cache->getColumn(column);
00067 }
00068 
00069 float
00070 Dense3DModelPeakCache::getValueAt(int column, int n) const
00071 {
00072     if (!m_source) return 0.f;
00073     if (!haveColumn(column)) fillColumn(column);
00074     return m_cache->getValueAt(column, n);
00075 }
00076 
00077 void
00078 Dense3DModelPeakCache::sourceModelChanged()
00079 {
00080     if (!m_source) return;
00081     if (m_coverage.size() > 0) {
00082         // The last peak may have come from an incomplete read, which
00083         // may since have been filled, so reset it
00084         m_coverage.reset(m_coverage.size()-1);
00085     }
00086     m_coverage.resize(getWidth()); // retaining data
00087 }
00088 
00089 void
00090 Dense3DModelPeakCache::sourceModelAboutToBeDeleted()
00091 {
00092     m_source = 0;
00093 }
00094 
00095 bool
00096 Dense3DModelPeakCache::haveColumn(int column) const
00097 {
00098     return column < (int)m_coverage.size() && m_coverage.get(column);
00099 }
00100 
00101 void
00102 Dense3DModelPeakCache::fillColumn(int column) const
00103 {
00104     Profiler profiler("Dense3DModelPeakCache::fillColumn");
00105 
00106     if (column >= (int)m_coverage.size()) {
00107         // see note in sourceModelChanged
00108         if (m_coverage.size() > 0) m_coverage.reset(m_coverage.size()-1);
00109         m_coverage.resize(column + 1);
00110     }
00111 
00112     Column peak;
00113     for (int i = 0; i < int(m_resolution); ++i) {
00114         Column here = m_source->getColumn(column * m_resolution + i);
00115         if (i == 0) {
00116             peak = here;
00117         } else {
00118             for (int j = 0; j < (int)peak.size() && j < (int)here.size(); ++j) {
00119                 if (here[j] > peak[j]) peak[j] = here[j];
00120             }
00121         }
00122     }
00123 
00124     m_cache->setColumn(column, peak);
00125     m_coverage.set(column);
00126 }
00127 
00128