Chris@297: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@297: Chris@297: /* Chris@297: Sonic Visualiser Chris@297: An audio file viewer and annotation editor. Chris@297: Centre for Digital Music, Queen Mary, University of London. Chris@297: This file copyright 2007 QMUL. Chris@297: Chris@297: This program is free software; you can redistribute it and/or Chris@297: modify it under the terms of the GNU General Public License as Chris@297: published by the Free Software Foundation; either version 2 of the Chris@297: License, or (at your option) any later version. See the file Chris@297: COPYING included with this distribution for more information. Chris@297: */ Chris@297: Chris@297: #include "AggregateWaveModel.h" Chris@297: Chris@297: #include Chris@297: Chris@314: #include Chris@314: Chris@1096: using namespace std; Chris@1096: Chris@1556: //#define DEBUG_AGGREGATE_WAVE_FILE_MODEL 1 Chris@1556: Chris@297: PowerOfSqrtTwoZoomConstraint Chris@297: AggregateWaveModel::m_zoomConstraint; Chris@297: Chris@297: AggregateWaveModel::AggregateWaveModel(ChannelSpecList channelSpecs) : Chris@1732: m_components(channelSpecs) Chris@297: { Chris@1732: sv_samplerate_t overallRate = 0; Chris@1389: Chris@1732: for (int channel = 0; in_range_for(m_components, channel); ++channel) { Chris@1732: Chris@1732: auto model = ModelById::getAs Chris@1732: (m_components[channel].model); Chris@1732: Chris@1732: if (!model) { Chris@1732: SVCERR << "AggregateWaveModel: WARNING: component for channel " Chris@1732: << channel << " is not found or is of wrong model type" Chris@1732: << endl; Chris@1732: continue; Chris@1732: } Chris@1732: Chris@1732: sv_samplerate_t rate = model->getSampleRate(); Chris@1732: Chris@1732: if (!rate) { Chris@1732: SVCERR << "AggregateWaveModel: WARNING: component for channel " Chris@1732: << channel << " reports zero sample rate" << endl; Chris@1732: Chris@1732: } else if (!overallRate) { Chris@1732: Chris@1732: overallRate = rate; Chris@1732: Chris@1732: } else if (rate != overallRate) { Chris@1732: SVCERR << "AggregateWaveModel: WARNING: component for channel " Chris@1732: << channel << " has different sample rate from earlier " Chris@1732: << "channels (has " << rate << ", expected " << overallRate Chris@1732: << ")" << endl; Chris@297: } Chris@1770: Chris@1770: connect(model.get(), SIGNAL(modelChanged(ModelId)), Chris@1770: this, SLOT(componentModelChanged(ModelId))); Chris@1770: connect(model.get(), SIGNAL(modelChangedWithin(ModelId, sv_frame_t, sv_frame_t)), Chris@1770: this, SLOT(componentModelChangedWithin(ModelId, sv_frame_t, sv_frame_t))); Chris@1770: connect(model.get(), SIGNAL(completionChanged(ModelId)), Chris@1770: this, SLOT(componentModelCompletionChanged(ModelId))); Chris@297: } Chris@297: } Chris@297: Chris@297: AggregateWaveModel::~AggregateWaveModel() Chris@297: { Chris@1688: SVDEBUG << "AggregateWaveModel::~AggregateWaveModel" << endl; Chris@297: } Chris@297: Chris@297: bool Chris@297: AggregateWaveModel::isOK() const Chris@297: { Chris@1732: if (m_components.empty()) { Chris@1389: return false; Chris@1389: } Chris@1732: for (const auto &c: m_components) { Chris@1732: auto model = ModelById::get(c.model); Chris@1732: if (!model || !model->isOK()) { Chris@1389: return false; Chris@1389: } Chris@297: } Chris@297: return true; Chris@297: } Chris@297: Chris@297: bool Chris@297: AggregateWaveModel::isReady(int *completion) const Chris@297: { Chris@297: if (completion) *completion = 100; Chris@1389: Chris@297: bool ready = true; Chris@1732: for (auto c: m_components) { Chris@297: int completionHere = 100; Chris@1732: auto model = ModelById::get(c.model); Chris@1732: if (!model) continue; Chris@1732: if (!model->isReady(&completionHere)) { Chris@1556: ready = false; Chris@1556: } Chris@297: if (completion && completionHere < *completion) { Chris@297: *completion = completionHere; Chris@297: } Chris@297: } Chris@1556: Chris@1556: #ifdef DEBUG_AGGREGATE_WAVE_FILE_MODEL Chris@1556: SVDEBUG << "AggregateWaveModel(" << objectName() Chris@1556: << ")::isReady: returning " << ready << endl; Chris@1556: #endif Chris@1556: Chris@297: return ready; Chris@297: } Chris@297: Chris@1038: sv_frame_t Chris@297: AggregateWaveModel::getFrameCount() const Chris@297: { Chris@1038: sv_frame_t count = 0; Chris@1732: for (auto c: m_components) { Chris@1732: auto model = ModelById::get(c.model); Chris@1732: if (!model) continue; Chris@1732: sv_frame_t thisCount = model->getEndFrame() - model->getStartFrame(); Chris@297: if (thisCount > count) count = thisCount; Chris@297: } Chris@297: return count; Chris@297: } Chris@297: Chris@929: int Chris@297: AggregateWaveModel::getChannelCount() const Chris@297: { Chris@1038: return int(m_components.size()); Chris@297: } Chris@297: Chris@1040: sv_samplerate_t Chris@297: AggregateWaveModel::getSampleRate() const Chris@297: { Chris@1732: if (m_components.empty()) return 0; Chris@1732: auto model = ModelById::get(m_components.begin()->model); Chris@1732: if (!model) return 0; Chris@1732: return model->getSampleRate(); Chris@297: } Chris@297: Chris@1326: floatvec_t Chris@1096: AggregateWaveModel::getData(int channel, sv_frame_t start, sv_frame_t count) const Chris@297: { Chris@1732: if (m_components.empty()) return {}; Chris@1732: Chris@297: int ch0 = channel, ch1 = channel; Chris@297: if (channel == -1) { Chris@297: ch0 = 0; Chris@297: ch1 = getChannelCount()-1; Chris@1732: } else if (!in_range_for(m_components, channel)) { Chris@1732: return {}; Chris@297: } Chris@297: Chris@1326: floatvec_t result(count, 0.f); Chris@1038: sv_frame_t longest = 0; Chris@1008: Chris@297: for (int c = ch0; c <= ch1; ++c) { Chris@1096: Chris@1732: auto model = ModelById::getAs Chris@1732: (m_components[c].model); Chris@1732: if (!model) continue; Chris@1732: Chris@1732: auto here = model->getData(m_components[c].channel, start, count); Chris@1100: if (sv_frame_t(here.size()) > longest) { Chris@1100: longest = sv_frame_t(here.size()); Chris@1008: } Chris@1096: for (sv_frame_t i = 0; in_range_for(here, i); ++i) { Chris@1096: result[i] += here[i]; Chris@297: } Chris@297: } Chris@297: Chris@1096: result.resize(longest); Chris@1096: return result; Chris@297: } Chris@363: Chris@1326: vector Chris@1086: AggregateWaveModel::getMultiChannelData(int fromchannel, int tochannel, Chris@1096: sv_frame_t start, sv_frame_t count) const Chris@363: { Chris@1038: sv_frame_t min = count; Chris@363: Chris@1326: vector result; Chris@1096: Chris@929: for (int c = fromchannel; c <= tochannel; ++c) { Chris@1096: auto here = getData(c, start, count); Chris@1100: if (sv_frame_t(here.size()) < min) { Chris@1100: min = sv_frame_t(here.size()); Chris@1100: } Chris@1096: result.push_back(here); Chris@1096: } Chris@1096: Chris@1096: if (min < count) { Chris@1096: for (auto &v : result) v.resize(min); Chris@363: } Chris@363: Chris@1096: return result; Chris@363: } Chris@377: Chris@929: int Chris@929: AggregateWaveModel::getSummaryBlockSize(int desired) const Chris@377: { Chris@377: //!!! complete Chris@377: return desired; Chris@377: } Chris@297: Chris@297: void Chris@1038: AggregateWaveModel::getSummaries(int, sv_frame_t, sv_frame_t, Chris@929: RangeBlock &, int &) const Chris@297: { Chris@297: //!!! complete Chris@297: } Chris@297: Chris@297: AggregateWaveModel::Range Chris@1038: AggregateWaveModel::getSummary(int, sv_frame_t, sv_frame_t) const Chris@297: { Chris@297: //!!! complete Chris@297: return Range(); Chris@297: } Chris@297: Chris@929: int Chris@297: AggregateWaveModel::getComponentCount() const Chris@297: { Chris@1038: return int(m_components.size()); Chris@297: } Chris@297: Chris@297: AggregateWaveModel::ModelChannelSpec Chris@929: AggregateWaveModel::getComponent(int c) const Chris@297: { Chris@297: return m_components[c]; Chris@297: } Chris@297: Chris@297: void Chris@1770: AggregateWaveModel::componentModelChanged(ModelId) Chris@297: { Chris@1770: emit modelChanged(getId()); Chris@297: } Chris@297: Chris@297: void Chris@1770: AggregateWaveModel::componentModelChangedWithin(ModelId, sv_frame_t start, sv_frame_t end) Chris@297: { Chris@1770: emit modelChangedWithin(getId(), start, end); Chris@297: } Chris@297: Chris@297: void Chris@1770: AggregateWaveModel::componentModelCompletionChanged(ModelId) Chris@297: { Chris@1770: emit completionChanged(getId()); Chris@297: } Chris@297: Chris@297: void Chris@1391: AggregateWaveModel::toXml(QTextStream &out, Chris@1391: QString indent, Chris@1391: QString extraAttributes) const Chris@297: { Chris@1391: QStringList componentStrings; Chris@1391: for (const auto &c: m_components) { Chris@1732: auto model = ModelById::get(c.model); Chris@1732: if (!model) continue; Chris@1732: componentStrings.push_back(QString("%1").arg(model->getExportId())); Chris@1391: } Chris@1391: Model::toXml(out, indent, Chris@1391: QString("type=\"aggregatewave\" components=\"%1\" %2") Chris@1391: .arg(componentStrings.join(",")) Chris@1391: .arg(extraAttributes)); Chris@297: } Chris@297: