comparison data/model/Dense3DModelPeakCache.cpp @ 1778:59d9dcfd67c2

Replace the model used for the cache part of the peak-cache model with a simple vector of vectors. Avoids unnecessary locking in a class that is not thread-safe in any case. Also record whether the final column is actually truncated, rather than risk possible backward seeks to re-read it in the case where it simply might be
author Chris Cannam
date Wed, 11 Sep 2019 11:19:27 +0100
parents d484490cdf69
children
comparison
equal deleted inserted replaced
1777:d484490cdf69 1778:59d9dcfd67c2
20 #include "base/HitCount.h" 20 #include "base/HitCount.h"
21 21
22 Dense3DModelPeakCache::Dense3DModelPeakCache(ModelId sourceId, 22 Dense3DModelPeakCache::Dense3DModelPeakCache(ModelId sourceId,
23 int columnsPerPeak) : 23 int columnsPerPeak) :
24 m_source(sourceId), 24 m_source(sourceId),
25 m_columnsPerPeak(columnsPerPeak) 25 m_columnsPerPeak(columnsPerPeak),
26 m_finalColumnIncomplete(false)
26 { 27 {
27 auto source = ModelById::getAs<DenseThreeDimensionalModel>(m_source); 28 auto source = ModelById::getAs<DenseThreeDimensionalModel>(m_source);
28 if (!source) { 29 if (!source) {
29 SVCERR << "WARNING: Dense3DModelPeakCache constructed for unknown or wrong-type source model id " << m_source << endl; 30 SVCERR << "WARNING: Dense3DModelPeakCache constructed for unknown or wrong-type source model id " << m_source << endl;
30 m_source = {}; 31 m_source = {};
31 return; 32 return;
32 } 33 }
33
34 m_cache.reset(new EditableDenseThreeDimensionalModel
35 (source->getSampleRate(),
36 source->getResolution() * m_columnsPerPeak,
37 source->getHeight(),
38 false));
39 34
40 connect(source.get(), SIGNAL(modelChanged(ModelId)), 35 connect(source.get(), SIGNAL(modelChanged(ModelId)),
41 this, SLOT(sourceModelChanged(ModelId))); 36 this, SLOT(sourceModelChanged(ModelId)));
42 } 37 }
43 38
47 42
48 Dense3DModelPeakCache::Column 43 Dense3DModelPeakCache::Column
49 Dense3DModelPeakCache::getColumn(int column) const 44 Dense3DModelPeakCache::getColumn(int column) const
50 { 45 {
51 if (!haveColumn(column)) fillColumn(column); 46 if (!haveColumn(column)) fillColumn(column);
52 return m_cache->getColumn(column); 47 return m_cache.at(column);
53 } 48 }
54 49
55 float 50 float
56 Dense3DModelPeakCache::getValueAt(int column, int n) const 51 Dense3DModelPeakCache::getValueAt(int column, int n) const
57 { 52 {
58 if (!haveColumn(column)) fillColumn(column); 53 if (!haveColumn(column)) fillColumn(column);
59 return m_cache->getValueAt(column, n); 54 return m_cache.at(column).at(n);
60 } 55 }
61 56
62 void 57 void
63 Dense3DModelPeakCache::sourceModelChanged(ModelId) 58 Dense3DModelPeakCache::sourceModelChanged(ModelId)
64 { 59 {
65 if (m_coverage.size() > 0) { 60 if (m_finalColumnIncomplete && m_coverage.size() > 0) {
66 // The last peak may have come from an incomplete read, which 61 // The last peak came from an incomplete read, which may since
67 // may since have been filled, so reset it 62 // have been filled, so reset it
68 m_coverage[m_coverage.size()-1] = false; 63 m_coverage[m_coverage.size()-1] = false;
64 m_finalColumnIncomplete = false;
69 } 65 }
70 m_coverage.resize(getWidth(), false); // retaining data
71 } 66 }
72 67
73 bool 68 bool
74 Dense3DModelPeakCache::haveColumn(int column) const 69 Dense3DModelPeakCache::haveColumn(int column) const
75 { 70 {
87 Dense3DModelPeakCache::fillColumn(int column) const 82 Dense3DModelPeakCache::fillColumn(int column) const
88 { 83 {
89 Profiler profiler("Dense3DModelPeakCache::fillColumn"); 84 Profiler profiler("Dense3DModelPeakCache::fillColumn");
90 85
91 if (!in_range_for(m_coverage, column)) { 86 if (!in_range_for(m_coverage, column)) {
92 if (m_coverage.size() > 0) { 87 if (m_finalColumnIncomplete && m_coverage.size() > 0) {
93 // The last peak may have come from an incomplete read, which 88 // The last peak may have come from an incomplete read, which
94 // may since have been filled, so reset it 89 // may since have been filled, so reset it
95 m_coverage[m_coverage.size()-1] = false; 90 m_coverage[m_coverage.size()-1] = false;
91 m_finalColumnIncomplete = false;
96 } 92 }
97 m_coverage.resize(column + 1, false); 93 m_coverage.resize(column + 1, false);
94 m_cache.resize(column + 1, {});
95 }
96
97 auto source = ModelById::getAs<DenseThreeDimensionalModel>(m_source);
98 if (!source) {
99 return;
100 }
101
102 int sourceWidth = source->getWidth();
103 int sourceColumn = column * m_columnsPerPeak;
104 if (sourceColumn >= sourceWidth) {
105 return;
98 } 106 }
99 107
100 auto source = ModelById::getAs<DenseThreeDimensionalModel>(m_source); 108 Column peak = source->getColumn(sourceColumn);
101 if (!source) return; 109 int n = int(peak.size());
102 110
103 int sourceWidth = source->getWidth(); 111 for (int i = 1; i < m_columnsPerPeak; ++i) {
104
105 Column peak;
106 int n = 0;
107 for (int i = 0; i < m_columnsPerPeak; ++i) {
108 112
109 int sourceColumn = column * m_columnsPerPeak + i; 113 ++sourceColumn;
110 if (sourceColumn >= sourceWidth) break; 114 if (sourceColumn >= sourceWidth) {
115 m_finalColumnIncomplete = true;
116 break;
117 }
111 118
112 Column here = source->getColumn(sourceColumn); 119 Column here = source->getColumn(sourceColumn);
113 120 int m = std::min(n, int(here.size()));
114 // cerr << "Dense3DModelPeakCache::fillColumn(" << column << "): source col " 121 for (int j = 0; j < m; ++j) {
115 // << sourceColumn << " of " << sourceWidth 122 peak[j] = std::max(here[j], peak[j]);
116 // << " returned " << here.size() << " elts" << endl;
117
118 if (i == 0) {
119 peak = here;
120 n = int(peak.size());
121 } else {
122 int m = std::min(n, int(here.size()));
123 for (int j = 0; j < m; ++j) {
124 peak[j] = std::max(here[j], peak[j]);
125 }
126 } 123 }
127 } 124 }
128 125
129 m_cache->setColumn(column, peak); 126 m_cache[column] = peak;
130 m_coverage[column] = true; 127 m_coverage[column] = true;
131 } 128 }
132 129
133 130