annotate data/model/IntervalModel.h @ 1008:d9e0e59a1581

When using an aggregate model to pass data to a transform, zero-pad the shorter input to the duration of the longer rather than truncating the longer. (This is better behaviour for e.g. MATCH, and in any case the code was previously truncating incorrectly and ending up with garbage data at the end.)
author Chris Cannam
date Fri, 14 Nov 2014 13:51:33 +0000
parents bfe724787abf
children cc27f35aa75c
rev   line source
Chris@437 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@437 2
Chris@437 3 /*
Chris@437 4 Sonic Visualiser
Chris@437 5 An audio file viewer and annotation editor.
Chris@437 6 Centre for Digital Music, Queen Mary, University of London.
Chris@437 7 This file copyright 2006-2008 Chris Cannam and QMUL.
Chris@437 8
Chris@437 9 This program is free software; you can redistribute it and/or
Chris@437 10 modify it under the terms of the GNU General Public License as
Chris@437 11 published by the Free Software Foundation; either version 2 of the
Chris@437 12 License, or (at your option) any later version. See the file
Chris@437 13 COPYING included with this distribution for more information.
Chris@437 14 */
Chris@437 15
Chris@437 16 #ifndef _INTERVAL_MODEL_H_
Chris@437 17 #define _INTERVAL_MODEL_H_
Chris@437 18
Chris@437 19 #include "SparseValueModel.h"
Chris@437 20 #include "base/RealTime.h"
Chris@437 21
Chris@437 22 /**
Chris@437 23 * Model containing sparse data (points with some properties) of which
Chris@437 24 * the properties include a duration and an arbitrary float value.
Chris@437 25 * The other properties depend on the point type.
Chris@437 26 */
Chris@437 27
Chris@437 28 template <typename PointType>
Chris@437 29 class IntervalModel : public SparseValueModel<PointType>
Chris@437 30 {
Chris@437 31 public:
Chris@929 32 IntervalModel(int sampleRate, int resolution,
Chris@437 33 bool notifyOnAdd = true) :
Chris@437 34 SparseValueModel<PointType>(sampleRate, resolution, notifyOnAdd)
Chris@437 35 { }
Chris@437 36
Chris@929 37 IntervalModel(int sampleRate, int resolution,
Chris@437 38 float valueMinimum, float valueMaximum,
Chris@437 39 bool notifyOnAdd = true) :
Chris@437 40 SparseValueModel<PointType>(sampleRate, resolution,
Chris@437 41 valueMinimum, valueMaximum,
Chris@437 42 notifyOnAdd)
Chris@437 43 { }
Chris@437 44
Chris@437 45 /**
Chris@437 46 * PointTypes have a duration, so this returns all points that span any
Chris@437 47 * of the given range (as well as the usual additional few before
Chris@437 48 * and after). Consequently this can be very slow (optimised data
Chris@437 49 * structures still to be done!).
Chris@437 50 */
Chris@437 51 virtual typename SparseValueModel<PointType>::PointList getPoints(long start, long end) const;
Chris@437 52
Chris@437 53 /**
Chris@437 54 * PointTypes have a duration, so this returns all points that span the
Chris@437 55 * given frame. Consequently this can be very slow (optimised
Chris@437 56 * data structures still to be done!).
Chris@437 57 */
Chris@437 58 virtual typename SparseValueModel<PointType>::PointList getPoints(long frame) const;
Chris@437 59
Chris@459 60 virtual const typename SparseModel<PointType>::PointList &getPoints() const {
Chris@459 61 return SparseModel<PointType>::getPoints();
Chris@459 62 }
Chris@459 63
Chris@437 64 /**
Chris@437 65 * TabularModel methods.
Chris@437 66 */
Chris@437 67
Chris@437 68 virtual QVariant getData(int row, int column, int role) const
Chris@437 69 {
Chris@437 70 if (column < 2) {
Chris@437 71 return SparseValueModel<PointType>::getData
Chris@437 72 (row, column, role);
Chris@437 73 }
Chris@437 74
Chris@437 75 typename SparseModel<PointType>::PointList::const_iterator i
Chris@437 76 = SparseModel<PointType>::getPointListIteratorForRow(row);
Chris@437 77 if (i == SparseModel<PointType>::m_points.end()) return QVariant();
Chris@437 78
Chris@437 79 switch (column) {
Chris@437 80 case 2:
Chris@437 81 if (role == Qt::EditRole || role == TabularModel::SortRole) return i->value;
Chris@437 82 else return QString("%1 %2").arg(i->value).arg
Chris@437 83 (IntervalModel<PointType>::getScaleUnits());
Chris@437 84 case 3: return int(i->duration); //!!! could be better presented
Chris@437 85 default: return QVariant();
Chris@437 86 }
Chris@437 87 }
Chris@437 88
Chris@437 89 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
Chris@437 90 {
Chris@438 91 typedef IntervalModel<PointType> I;
Chris@438 92
Chris@437 93 if (column < 2) {
Chris@437 94 return SparseValueModel<PointType>::getSetDataCommand
Chris@437 95 (row, column, value, role);
Chris@437 96 }
Chris@437 97
Chris@740 98 if (role != Qt::EditRole) return 0;
Chris@438 99 typename I::PointList::const_iterator i
Chris@438 100 = I::getPointListIteratorForRow(row);
Chris@740 101 if (i == I::m_points.end()) return 0;
Chris@438 102 typename I::EditCommand *command = new typename I::EditCommand
Chris@438 103 (this, I::tr("Edit Data"));
Chris@437 104
Chris@437 105 PointType point(*i);
Chris@437 106 command->deletePoint(point);
Chris@437 107
Chris@437 108 switch (column) {
Chris@970 109 // column cannot be 0 or 1, those cases were handled above
Chris@437 110 case 2: point.value = value.toDouble(); break;
Chris@437 111 case 3: point.duration = value.toInt(); break;
Chris@437 112 }
Chris@437 113
Chris@437 114 command->addPoint(point);
Chris@437 115 return command->finish();
Chris@437 116 }
Chris@437 117
Chris@437 118 virtual bool isColumnTimeValue(int column) const
Chris@437 119 {
Chris@618 120 // NB duration is not a "time value" -- that's for columns
Chris@618 121 // whose sort ordering is exactly that of the frame time
Chris@618 122 return (column < 2);
Chris@437 123 }
Chris@437 124 };
Chris@437 125
Chris@437 126 template <typename PointType>
Chris@437 127 typename SparseValueModel<PointType>::PointList
Chris@437 128 IntervalModel<PointType>::getPoints(long start, long end) const
Chris@437 129 {
Chris@437 130 typedef IntervalModel<PointType> I;
Chris@437 131
Chris@437 132 if (start > end) return typename I::PointList();
Chris@437 133
Chris@437 134 QMutex &mutex(I::m_mutex);
Chris@437 135 QMutexLocker locker(&mutex);
Chris@437 136
Chris@437 137 PointType endPoint(end);
Chris@437 138
Chris@608 139 typename I::PointListConstIterator endItr = I::m_points.upper_bound(endPoint);
Chris@437 140
Chris@437 141 if (endItr != I::m_points.end()) ++endItr;
Chris@437 142 if (endItr != I::m_points.end()) ++endItr;
Chris@437 143
Chris@437 144 typename I::PointList rv;
Chris@437 145
Chris@608 146 for (typename I::PointListConstIterator i = endItr; i != I::m_points.begin(); ) {
Chris@437 147 --i;
Chris@437 148 if (i->frame < start) {
Chris@437 149 if (i->frame + long(i->duration) >= start) {
Chris@437 150 rv.insert(*i);
Chris@437 151 }
Chris@437 152 } else if (i->frame <= end) {
Chris@437 153 rv.insert(*i);
Chris@437 154 }
Chris@437 155 }
Chris@437 156
Chris@437 157 return rv;
Chris@437 158 }
Chris@437 159
Chris@437 160 template <typename PointType>
Chris@437 161 typename SparseValueModel<PointType>::PointList
Chris@437 162 IntervalModel<PointType>::getPoints(long frame) const
Chris@437 163 {
Chris@437 164 typedef IntervalModel<PointType> I;
Chris@437 165
Chris@437 166 QMutex &mutex(I::m_mutex);
Chris@437 167 QMutexLocker locker(&mutex);
Chris@437 168
Chris@437 169 if (I::m_resolution == 0) return typename I::PointList();
Chris@437 170
Chris@437 171 long start = (frame / I::m_resolution) * I::m_resolution;
Chris@437 172 long end = start + I::m_resolution;
Chris@437 173
Chris@437 174 PointType endPoint(end);
Chris@437 175
Chris@608 176 typename I::PointListConstIterator endItr = I::m_points.upper_bound(endPoint);
Chris@437 177
Chris@437 178 typename I::PointList rv;
Chris@437 179
Chris@608 180 for (typename I::PointListConstIterator i = endItr; i != I::m_points.begin(); ) {
Chris@437 181 --i;
Chris@437 182 if (i->frame < start) {
Chris@437 183 if (i->frame + long(i->duration) >= start) {
Chris@437 184 rv.insert(*i);
Chris@437 185 }
Chris@437 186 } else if (i->frame <= end) {
Chris@437 187 rv.insert(*i);
Chris@437 188 }
Chris@437 189 }
Chris@437 190
Chris@437 191 return rv;
Chris@437 192 }
Chris@437 193
Chris@437 194 #endif