File: Dense3DModelPeakCache.cpp

package info (click to toggle)
sonic-visualiser 2.5~repack1-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 13,596 kB
  • ctags: 9,853
  • sloc: cpp: 93,843; ansic: 1,138; sh: 1,012; xml: 64; makefile: 35
file content (128 lines) | stat: -rw-r--r-- 3,495 bytes parent folder | download | duplicates (2)
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);
}