annotate data/model/Dense3DModelPeakCache.cpp @ 1305:9f9f55a8af92 mp3-gapless

Add gapless flag to MP3FileReader, and implement trimming the delay samples from the start (padding is not yet trimmed from end)
author Chris Cannam
date Tue, 29 Nov 2016 11:35:56 +0000
parents 9884efa1f88a
children f5f83fb49852
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@1191 20 Dense3DModelPeakCache::Dense3DModelPeakCache(const DenseThreeDimensionalModel *source,
Chris@929 21 int columnsPerPeak) :
Chris@545 22 m_source(source),
Chris@1190 23 m_columnsPerPeak(columnsPerPeak)
Chris@545 24 {
Chris@545 25 m_cache = new EditableDenseThreeDimensionalModel
Chris@545 26 (source->getSampleRate(),
Chris@545 27 getResolution(),
Chris@545 28 source->getHeight(),
Chris@545 29 EditableDenseThreeDimensionalModel::NoCompression,
Chris@545 30 false);
Chris@545 31
Chris@545 32 connect(source, SIGNAL(modelChanged()),
Chris@545 33 this, SLOT(sourceModelChanged()));
Chris@546 34 connect(source, SIGNAL(aboutToBeDeleted()),
Chris@545 35 this, SLOT(sourceModelAboutToBeDeleted()));
Chris@545 36
Chris@545 37 }
Chris@545 38
Chris@545 39 Dense3DModelPeakCache::~Dense3DModelPeakCache()
Chris@545 40 {
Chris@545 41 delete m_cache;
Chris@545 42 }
Chris@545 43
Chris@545 44 Dense3DModelPeakCache::Column
Chris@929 45 Dense3DModelPeakCache::getColumn(int column) const
Chris@545 46 {
Chris@551 47 Profiler profiler("Dense3DModelPeakCache::getColumn");
Chris@545 48 if (!m_source) return Column();
Chris@545 49 if (!haveColumn(column)) fillColumn(column);
Chris@545 50 return m_cache->getColumn(column);
Chris@545 51 }
Chris@545 52
Chris@545 53 float
Chris@929 54 Dense3DModelPeakCache::getValueAt(int column, int n) const
Chris@545 55 {
Chris@545 56 if (!m_source) return 0.f;
Chris@545 57 if (!haveColumn(column)) fillColumn(column);
Chris@545 58 return m_cache->getValueAt(column, n);
Chris@545 59 }
Chris@545 60
Chris@545 61 void
Chris@545 62 Dense3DModelPeakCache::sourceModelChanged()
Chris@545 63 {
Chris@545 64 if (!m_source) return;
Chris@546 65 if (m_coverage.size() > 0) {
Chris@546 66 // The last peak may have come from an incomplete read, which
Chris@546 67 // may since have been filled, so reset it
Chris@1153 68 m_coverage[m_coverage.size()-1] = false;
Chris@546 69 }
Chris@1153 70 m_coverage.resize(getWidth(), false); // retaining data
Chris@545 71 }
Chris@545 72
Chris@545 73 void
Chris@545 74 Dense3DModelPeakCache::sourceModelAboutToBeDeleted()
Chris@545 75 {
Chris@545 76 m_source = 0;
Chris@545 77 }
Chris@545 78
Chris@545 79 bool
Chris@929 80 Dense3DModelPeakCache::haveColumn(int column) const
Chris@545 81 {
Chris@1153 82 return in_range_for(m_coverage, column) && m_coverage[column];
Chris@545 83 }
Chris@545 84
Chris@545 85 void
Chris@929 86 Dense3DModelPeakCache::fillColumn(int column) const
Chris@545 87 {
Chris@551 88 Profiler profiler("Dense3DModelPeakCache::fillColumn");
Chris@551 89
Chris@1153 90 if (!in_range_for(m_coverage, column)) {
Chris@1192 91 if (m_coverage.size() > 0) {
Chris@1192 92 // The last peak may have come from an incomplete read, which
Chris@1192 93 // may since have been filled, so reset it
Chris@1192 94 m_coverage[m_coverage.size()-1] = false;
Chris@1192 95 }
Chris@1153 96 m_coverage.resize(column + 1, false);
Chris@551 97 }
Chris@546 98
Chris@1192 99 int sourceWidth = m_source->getWidth();
Chris@1192 100
Chris@545 101 Column peak;
Chris@1156 102 int n = 0;
Chris@1190 103 for (int i = 0; i < m_columnsPerPeak; ++i) {
Chris@1192 104
Chris@1192 105 int sourceColumn = column * m_columnsPerPeak + i;
Chris@1192 106 if (sourceColumn >= sourceWidth) break;
Chris@1192 107
Chris@1192 108 Column here = m_source->getColumn(sourceColumn);
Chris@1192 109
Chris@1192 110 // cerr << "Dense3DModelPeakCache::fillColumn(" << column << "): source col "
Chris@1192 111 // << sourceColumn << " of " << sourceWidth
Chris@1192 112 // << " returned " << here.size() << " elts" << endl;
Chris@1192 113
Chris@545 114 if (i == 0) {
Chris@545 115 peak = here;
Chris@1156 116 n = int(peak.size());
Chris@545 117 } else {
Chris@1156 118 int m = std::min(n, int(here.size()));
Chris@1156 119 for (int j = 0; j < m; ++j) {
Chris@1156 120 peak[j] = std::max(here[j], peak[j]);
Chris@545 121 }
Chris@545 122 }
Chris@545 123 }
Chris@546 124
Chris@545 125 m_cache->setColumn(column, peak);
Chris@1153 126 m_coverage[column] = true;
Chris@545 127 }
Chris@545 128
Chris@545 129