AggregateWaveModel.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2007 QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "AggregateWaveModel.h"
17 
18 #include <iostream>
19 
20 #include <QTextStream>
21 
22 using namespace std;
23 
24 //#define DEBUG_AGGREGATE_WAVE_FILE_MODEL 1
25 
28 
30  m_components(channelSpecs)
31 {
32  sv_samplerate_t overallRate = 0;
33 
34  for (int channel = 0; in_range_for(m_components, channel); ++channel) {
35 
36  auto model = ModelById::getAs<RangeSummarisableTimeValueModel>
37  (m_components[channel].model);
38 
39  if (!model) {
40  SVCERR << "AggregateWaveModel: WARNING: component for channel "
41  << channel << " is not found or is of wrong model type"
42  << endl;
43  continue;
44  }
45 
46  sv_samplerate_t rate = model->getSampleRate();
47 
48  if (!rate) {
49  SVCERR << "AggregateWaveModel: WARNING: component for channel "
50  << channel << " reports zero sample rate" << endl;
51 
52  } else if (!overallRate) {
53 
54  overallRate = rate;
55 
56  } else if (rate != overallRate) {
57  SVCERR << "AggregateWaveModel: WARNING: component for channel "
58  << channel << " has different sample rate from earlier "
59  << "channels (has " << rate << ", expected " << overallRate
60  << ")" << endl;
61  }
62 
63  connect(model.get(), SIGNAL(modelChanged(ModelId)),
64  this, SLOT(componentModelChanged(ModelId)));
65  connect(model.get(), SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)),
67  connect(model.get(), SIGNAL(completionChanged(ModelId)),
69  }
70 }
71 
73 {
74  SVDEBUG << "AggregateWaveModel::~AggregateWaveModel" << endl;
75 }
76 
77 bool
79 {
80  if (m_components.empty()) {
81  return false;
82  }
83  for (const auto &c: m_components) {
84  auto model = ModelById::get(c.model);
85  if (!model || !model->isOK()) {
86  return false;
87  }
88  }
89  return true;
90 }
91 
92 bool
93 AggregateWaveModel::isReady(int *completion) const
94 {
95  if (completion) *completion = 100;
96 
97  bool ready = true;
98  for (auto c: m_components) {
99  int completionHere = 100;
100  auto model = ModelById::get(c.model);
101  if (!model) continue;
102  if (!model->isReady(&completionHere)) {
103  ready = false;
104  }
105  if (completion && completionHere < *completion) {
106  *completion = completionHere;
107  }
108  }
109 
110 #ifdef DEBUG_AGGREGATE_WAVE_FILE_MODEL
111  SVDEBUG << "AggregateWaveModel(" << objectName()
112  << ")::isReady: returning " << ready << endl;
113 #endif
114 
115  return ready;
116 }
117 
120 {
121  sv_frame_t count = 0;
122  for (auto c: m_components) {
123  auto model = ModelById::get(c.model);
124  if (!model) continue;
125  sv_frame_t thisCount = model->getEndFrame() - model->getStartFrame();
126  if (thisCount > count) count = thisCount;
127  }
128  return count;
129 }
130 
131 int
133 {
134  return int(m_components.size());
135 }
136 
139 {
140  if (m_components.empty()) return 0;
141  auto model = ModelById::get(m_components.begin()->model);
142  if (!model) return 0;
143  return model->getSampleRate();
144 }
145 
147 AggregateWaveModel::getData(int channel, sv_frame_t start, sv_frame_t count) const
148 {
149  if (m_components.empty()) return {};
150 
151  int ch0 = channel, ch1 = channel;
152  if (channel == -1) {
153  ch0 = 0;
154  ch1 = getChannelCount()-1;
155  } else if (!in_range_for(m_components, channel)) {
156  return {};
157  }
158 
159  floatvec_t result(count, 0.f);
160  sv_frame_t longest = 0;
161 
162  for (int c = ch0; c <= ch1; ++c) {
163 
164  auto model = ModelById::getAs<RangeSummarisableTimeValueModel>
165  (m_components[c].model);
166  if (!model) continue;
167 
168  auto here = model->getData(m_components[c].channel, start, count);
169  if (sv_frame_t(here.size()) > longest) {
170  longest = sv_frame_t(here.size());
171  }
172  for (sv_frame_t i = 0; in_range_for(here, i); ++i) {
173  result[i] += here[i];
174  }
175  }
176 
177  result.resize(longest);
178  return result;
179 }
180 
181 vector<floatvec_t>
182 AggregateWaveModel::getMultiChannelData(int fromchannel, int tochannel,
183  sv_frame_t start, sv_frame_t count) const
184 {
185  sv_frame_t min = count;
186 
187  vector<floatvec_t> result;
188 
189  for (int c = fromchannel; c <= tochannel; ++c) {
190  auto here = getData(c, start, count);
191  if (sv_frame_t(here.size()) < min) {
192  min = sv_frame_t(here.size());
193  }
194  result.push_back(here);
195  }
196 
197  if (min < count) {
198  for (auto &v : result) v.resize(min);
199  }
200 
201  return result;
202 }
203 
204 int
206 {
208  return desired;
209 }
210 
211 void
213  RangeBlock &, int &) const
214 {
216 }
217 
220 {
222  return Range();
223 }
224 
225 int
227 {
228  return int(m_components.size());
229 }
230 
233 {
234  return m_components[c];
235 }
236 
237 void
239 {
240  emit modelChanged(getId());
241 }
242 
243 void
245 {
246  emit modelChangedWithin(getId(), start, end);
247 }
248 
249 void
251 {
252  emit completionChanged(getId());
253 }
254 
255 void
256 AggregateWaveModel::toXml(QTextStream &out,
257  QString indent,
258  QString extraAttributes) const
259 {
260  QStringList componentStrings;
261  for (const auto &c: m_components) {
262  auto model = ModelById::get(c.model);
263  if (!model) continue;
264  componentStrings.push_back(QString("%1").arg(model->getExportId()));
265  }
266  Model::toXml(out, indent,
267  QString("type=\"aggregatewave\" components=\"%1\" %2")
268  .arg(componentStrings.join(","))
269  .arg(extraAttributes));
270 }
271 
double sv_samplerate_t
Sample rate.
Definition: BaseTypes.h:51
void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const override
Stream this exportable object out to XML on a text stream.
Definition: Model.cpp:204
void componentModelChanged(ModelId)
int64_t sv_frame_t
Frame index, the unit of our time axis.
Definition: BaseTypes.h:31
static PowerOfSqrtTwoZoomConstraint m_zoomConstraint
ModelChannelSpec getComponent(int c) const
int getChannelCount() const override
Return the number of distinct channels for this model.
floatvec_t getData(int channel, sv_frame_t start, sv_frame_t count) const override
Get the specified set of samples from the given channel of the model in single-precision floating-poi...
sv_frame_t getFrameCount() const
AggregateWaveModel(ChannelSpecList channelSpecs)
void ready(ModelId myId)
Emitted when internal processing is complete (i.e.
Id getId() const
Return an id for this object.
Definition: ById.h:193
ChannelSpecList m_components
std::vector< float, breakfastquay::StlAllocator< float > > floatvec_t
Definition: BaseTypes.h:53
sv_samplerate_t getSampleRate() const override
Return the frame rate in frames per second.
Range getSummary(int channel, sv_frame_t start, sv_frame_t count) const override
Return the range from the given start frame, corresponding to the given number of underlying sample f...
int getSummaryBlockSize(int desired) const override
void componentModelChangedWithin(ModelId, sv_frame_t, sv_frame_t)
void completionChanged(ModelId myId)
Emitted when some internal processing has advanced a stage, but the model has not changed externally...
std::vector< ModelChannelSpec > ChannelSpecList
bool isReady(int *) const override
Return true if the model has finished loading or calculating all its data, for a model that is capabl...
bool in_range_for(const C &container, T i)
Check whether an integer index is in range for a container, avoiding overflows and signed/unsigned co...
Definition: BaseTypes.h:37
void modelChangedWithin(ModelId myId, sv_frame_t startFrame, sv_frame_t endFrame)
Emitted when a model has been edited (or more data retrieved from cache, in the case of a cached mode...
#define SVDEBUG
Definition: Debug.h:106
void toXml(QTextStream &out, QString indent="", QString extraAttributes="") const override
Stream this exportable object out to XML on a text stream.
#define SVCERR
Definition: Debug.h:109
void componentModelCompletionChanged(ModelId)
bool isOK() const override
Return true if the model was constructed successfully.
int getComponentCount() const
Definition: ById.h:115
void getSummaries(int channel, sv_frame_t start, sv_frame_t count, RangeBlock &ranges, int &blockSize) const override
Return ranges from the given start frame, corresponding to the given number of underlying sample fram...
void modelChanged(ModelId myId)
Emitted when a model has been edited (or more data retrieved from cache, in the case of a cached mode...
static std::shared_ptr< Item > get(Id id)
Definition: ById.h:251
std::vector< floatvec_t > getMultiChannelData(int fromchannel, int tochannel, sv_frame_t start, sv_frame_t count) const override
Get the specified set of samples from given contiguous range of channels of the model in single-preci...