annotate data/model/AggregateWaveModel.cpp @ 1784:4eac4bf35b45

More graceful handling of failure to construct FFT models in the case where the source model has already been deleted before this occurs
author Chris Cannam
date Tue, 17 Sep 2019 11:21:33 +0100
parents dffc70996f54
children
rev   line source
Chris@297 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@297 2
Chris@297 3 /*
Chris@297 4 Sonic Visualiser
Chris@297 5 An audio file viewer and annotation editor.
Chris@297 6 Centre for Digital Music, Queen Mary, University of London.
Chris@297 7 This file copyright 2007 QMUL.
Chris@297 8
Chris@297 9 This program is free software; you can redistribute it and/or
Chris@297 10 modify it under the terms of the GNU General Public License as
Chris@297 11 published by the Free Software Foundation; either version 2 of the
Chris@297 12 License, or (at your option) any later version. See the file
Chris@297 13 COPYING included with this distribution for more information.
Chris@297 14 */
Chris@297 15
Chris@297 16 #include "AggregateWaveModel.h"
Chris@297 17
Chris@297 18 #include <iostream>
Chris@297 19
Chris@314 20 #include <QTextStream>
Chris@314 21
Chris@1096 22 using namespace std;
Chris@1096 23
Chris@1556 24 //#define DEBUG_AGGREGATE_WAVE_FILE_MODEL 1
Chris@1556 25
Chris@297 26 PowerOfSqrtTwoZoomConstraint
Chris@297 27 AggregateWaveModel::m_zoomConstraint;
Chris@297 28
Chris@297 29 AggregateWaveModel::AggregateWaveModel(ChannelSpecList channelSpecs) :
Chris@1732 30 m_components(channelSpecs)
Chris@297 31 {
Chris@1732 32 sv_samplerate_t overallRate = 0;
Chris@1389 33
Chris@1732 34 for (int channel = 0; in_range_for(m_components, channel); ++channel) {
Chris@1732 35
Chris@1732 36 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>
Chris@1732 37 (m_components[channel].model);
Chris@1732 38
Chris@1732 39 if (!model) {
Chris@1732 40 SVCERR << "AggregateWaveModel: WARNING: component for channel "
Chris@1732 41 << channel << " is not found or is of wrong model type"
Chris@1732 42 << endl;
Chris@1732 43 continue;
Chris@1732 44 }
Chris@1732 45
Chris@1732 46 sv_samplerate_t rate = model->getSampleRate();
Chris@1732 47
Chris@1732 48 if (!rate) {
Chris@1732 49 SVCERR << "AggregateWaveModel: WARNING: component for channel "
Chris@1732 50 << channel << " reports zero sample rate" << endl;
Chris@1732 51
Chris@1732 52 } else if (!overallRate) {
Chris@1732 53
Chris@1732 54 overallRate = rate;
Chris@1732 55
Chris@1732 56 } else if (rate != overallRate) {
Chris@1732 57 SVCERR << "AggregateWaveModel: WARNING: component for channel "
Chris@1732 58 << channel << " has different sample rate from earlier "
Chris@1732 59 << "channels (has " << rate << ", expected " << overallRate
Chris@1732 60 << ")" << endl;
Chris@297 61 }
Chris@1770 62
Chris@1770 63 connect(model.get(), SIGNAL(modelChanged(ModelId)),
Chris@1770 64 this, SLOT(componentModelChanged(ModelId)));
Chris@1770 65 connect(model.get(), SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)),
Chris@1770 66 this, SLOT(componentModelChangedWithin(ModelId, sv_frame_t, sv_frame_t)));
Chris@1770 67 connect(model.get(), SIGNAL(completionChanged(ModelId)),
Chris@1770 68 this, SLOT(componentModelCompletionChanged(ModelId)));
Chris@297 69 }
Chris@297 70 }
Chris@297 71
Chris@297 72 AggregateWaveModel::~AggregateWaveModel()
Chris@297 73 {
Chris@1688 74 SVDEBUG << "AggregateWaveModel::~AggregateWaveModel" << endl;
Chris@297 75 }
Chris@297 76
Chris@297 77 bool
Chris@297 78 AggregateWaveModel::isOK() const
Chris@297 79 {
Chris@1732 80 if (m_components.empty()) {
Chris@1389 81 return false;
Chris@1389 82 }
Chris@1732 83 for (const auto &c: m_components) {
Chris@1732 84 auto model = ModelById::get(c.model);
Chris@1732 85 if (!model || !model->isOK()) {
Chris@1389 86 return false;
Chris@1389 87 }
Chris@297 88 }
Chris@297 89 return true;
Chris@297 90 }
Chris@297 91
Chris@297 92 bool
Chris@297 93 AggregateWaveModel::isReady(int *completion) const
Chris@297 94 {
Chris@297 95 if (completion) *completion = 100;
Chris@1389 96
Chris@297 97 bool ready = true;
Chris@1732 98 for (auto c: m_components) {
Chris@297 99 int completionHere = 100;
Chris@1732 100 auto model = ModelById::get(c.model);
Chris@1732 101 if (!model) continue;
Chris@1732 102 if (!model->isReady(&completionHere)) {
Chris@1556 103 ready = false;
Chris@1556 104 }
Chris@297 105 if (completion && completionHere < *completion) {
Chris@297 106 *completion = completionHere;
Chris@297 107 }
Chris@297 108 }
Chris@1556 109
Chris@1556 110 #ifdef DEBUG_AGGREGATE_WAVE_FILE_MODEL
Chris@1556 111 SVDEBUG << "AggregateWaveModel(" << objectName()
Chris@1556 112 << ")::isReady: returning " << ready << endl;
Chris@1556 113 #endif
Chris@1556 114
Chris@297 115 return ready;
Chris@297 116 }
Chris@297 117
Chris@1038 118 sv_frame_t
Chris@297 119 AggregateWaveModel::getFrameCount() const
Chris@297 120 {
Chris@1038 121 sv_frame_t count = 0;
Chris@1732 122 for (auto c: m_components) {
Chris@1732 123 auto model = ModelById::get(c.model);
Chris@1732 124 if (!model) continue;
Chris@1732 125 sv_frame_t thisCount = model->getEndFrame() - model->getStartFrame();
Chris@297 126 if (thisCount > count) count = thisCount;
Chris@297 127 }
Chris@297 128 return count;
Chris@297 129 }
Chris@297 130
Chris@929 131 int
Chris@297 132 AggregateWaveModel::getChannelCount() const
Chris@297 133 {
Chris@1038 134 return int(m_components.size());
Chris@297 135 }
Chris@297 136
Chris@1040 137 sv_samplerate_t
Chris@297 138 AggregateWaveModel::getSampleRate() const
Chris@297 139 {
Chris@1732 140 if (m_components.empty()) return 0;
Chris@1732 141 auto model = ModelById::get(m_components.begin()->model);
Chris@1732 142 if (!model) return 0;
Chris@1732 143 return model->getSampleRate();
Chris@297 144 }
Chris@297 145
Chris@1326 146 floatvec_t
Chris@1096 147 AggregateWaveModel::getData(int channel, sv_frame_t start, sv_frame_t count) const
Chris@297 148 {
Chris@1732 149 if (m_components.empty()) return {};
Chris@1732 150
Chris@297 151 int ch0 = channel, ch1 = channel;
Chris@297 152 if (channel == -1) {
Chris@297 153 ch0 = 0;
Chris@297 154 ch1 = getChannelCount()-1;
Chris@1732 155 } else if (!in_range_for(m_components, channel)) {
Chris@1732 156 return {};
Chris@297 157 }
Chris@297 158
Chris@1326 159 floatvec_t result(count, 0.f);
Chris@1038 160 sv_frame_t longest = 0;
Chris@1008 161
Chris@297 162 for (int c = ch0; c <= ch1; ++c) {
Chris@1096 163
Chris@1732 164 auto model = ModelById::getAs<RangeSummarisableTimeValueModel>
Chris@1732 165 (m_components[c].model);
Chris@1732 166 if (!model) continue;
Chris@1732 167
Chris@1732 168 auto here = model->getData(m_components[c].channel, start, count);
Chris@1100 169 if (sv_frame_t(here.size()) > longest) {
Chris@1100 170 longest = sv_frame_t(here.size());
Chris@1008 171 }
Chris@1096 172 for (sv_frame_t i = 0; in_range_for(here, i); ++i) {
Chris@1096 173 result[i] += here[i];
Chris@297 174 }
Chris@297 175 }
Chris@297 176
Chris@1096 177 result.resize(longest);
Chris@1096 178 return result;
Chris@297 179 }
Chris@363 180
Chris@1326 181 vector<floatvec_t>
Chris@1086 182 AggregateWaveModel::getMultiChannelData(int fromchannel, int tochannel,
Chris@1096 183 sv_frame_t start, sv_frame_t count) const
Chris@363 184 {
Chris@1038 185 sv_frame_t min = count;
Chris@363 186
Chris@1326 187 vector<floatvec_t> result;
Chris@1096 188
Chris@929 189 for (int c = fromchannel; c <= tochannel; ++c) {
Chris@1096 190 auto here = getData(c, start, count);
Chris@1100 191 if (sv_frame_t(here.size()) < min) {
Chris@1100 192 min = sv_frame_t(here.size());
Chris@1100 193 }
Chris@1096 194 result.push_back(here);
Chris@1096 195 }
Chris@1096 196
Chris@1096 197 if (min < count) {
Chris@1096 198 for (auto &v : result) v.resize(min);
Chris@363 199 }
Chris@363 200
Chris@1096 201 return result;
Chris@363 202 }
Chris@377 203
Chris@929 204 int
Chris@929 205 AggregateWaveModel::getSummaryBlockSize(int desired) const
Chris@377 206 {
Chris@377 207 //!!! complete
Chris@377 208 return desired;
Chris@377 209 }
Chris@297 210
Chris@297 211 void
Chris@1038 212 AggregateWaveModel::getSummaries(int, sv_frame_t, sv_frame_t,
Chris@929 213 RangeBlock &, int &) const
Chris@297 214 {
Chris@297 215 //!!! complete
Chris@297 216 }
Chris@297 217
Chris@297 218 AggregateWaveModel::Range
Chris@1038 219 AggregateWaveModel::getSummary(int, sv_frame_t, sv_frame_t) const
Chris@297 220 {
Chris@297 221 //!!! complete
Chris@297 222 return Range();
Chris@297 223 }
Chris@297 224
Chris@929 225 int
Chris@297 226 AggregateWaveModel::getComponentCount() const
Chris@297 227 {
Chris@1038 228 return int(m_components.size());
Chris@297 229 }
Chris@297 230
Chris@297 231 AggregateWaveModel::ModelChannelSpec
Chris@929 232 AggregateWaveModel::getComponent(int c) const
Chris@297 233 {
Chris@297 234 return m_components[c];
Chris@297 235 }
Chris@297 236
Chris@297 237 void
Chris@1770 238 AggregateWaveModel::componentModelChanged(ModelId)
Chris@297 239 {
Chris@1770 240 emit modelChanged(getId());
Chris@297 241 }
Chris@297 242
Chris@297 243 void
Chris@1770 244 AggregateWaveModel::componentModelChangedWithin(ModelId, sv_frame_t start, sv_frame_t end)
Chris@297 245 {
Chris@1770 246 emit modelChangedWithin(getId(), start, end);
Chris@297 247 }
Chris@297 248
Chris@297 249 void
Chris@1770 250 AggregateWaveModel::componentModelCompletionChanged(ModelId)
Chris@297 251 {
Chris@1770 252 emit completionChanged(getId());
Chris@297 253 }
Chris@297 254
Chris@297 255 void
Chris@1391 256 AggregateWaveModel::toXml(QTextStream &out,
Chris@1391 257 QString indent,
Chris@1391 258 QString extraAttributes) const
Chris@297 259 {
Chris@1391 260 QStringList componentStrings;
Chris@1391 261 for (const auto &c: m_components) {
Chris@1732 262 auto model = ModelById::get(c.model);
Chris@1732 263 if (!model) continue;
Chris@1732 264 componentStrings.push_back(QString("%1").arg(model->getExportId()));
Chris@1391 265 }
Chris@1391 266 Model::toXml(out, indent,
Chris@1391 267 QString("type=\"aggregatewave\" components=\"%1\" %2")
Chris@1391 268 .arg(componentStrings.join(","))
Chris@1391 269 .arg(extraAttributes));
Chris@297 270 }
Chris@297 271