annotate base/Selection.cpp @ 33:51e158b505da

* Rearrange spectrogram cacheing so that gain, normalization, instantaneous frequency calculations etc can be done from the cached data (increasing the size of the cache, but also the usability).
author Chris Cannam
date Thu, 23 Feb 2006 18:01:31 +0000
parents bb9291d84810
children 935a2419a77c
rev   line source
Chris@8 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@8 2
Chris@8 3 /*
Chris@8 4 A waveform viewer and audio annotation editor.
Chris@8 5 Chris Cannam, Queen Mary University of London, 2005-2006
Chris@8 6
Chris@8 7 This is experimental software. Not for distribution.
Chris@8 8 */
Chris@8 9
Chris@8 10 #include "Selection.h"
Chris@8 11
Chris@8 12 Selection::Selection() :
Chris@8 13 m_startFrame(0),
Chris@8 14 m_endFrame(0)
Chris@8 15 {
Chris@8 16 }
Chris@8 17
Chris@8 18 Selection::Selection(size_t startFrame, size_t endFrame) :
Chris@8 19 m_startFrame(startFrame),
Chris@8 20 m_endFrame(endFrame)
Chris@8 21 {
Chris@8 22 if (m_startFrame > m_endFrame) {
Chris@8 23 size_t tmp = m_endFrame;
Chris@8 24 m_endFrame = m_startFrame;
Chris@8 25 m_startFrame = tmp;
Chris@8 26 }
Chris@8 27 }
Chris@8 28
Chris@8 29 Selection::Selection(const Selection &s) :
Chris@8 30 m_startFrame(s.m_startFrame),
Chris@8 31 m_endFrame(s.m_endFrame)
Chris@8 32 {
Chris@8 33 }
Chris@8 34
Chris@8 35 Selection &
Chris@8 36 Selection::operator=(const Selection &s)
Chris@8 37 {
Chris@8 38 if (this != &s) {
Chris@8 39 m_startFrame = s.m_startFrame;
Chris@8 40 m_endFrame = s.m_endFrame;
Chris@8 41 }
Chris@8 42 return *this;
Chris@8 43 }
Chris@8 44
Chris@8 45 Selection::~Selection()
Chris@8 46 {
Chris@8 47 }
Chris@8 48
Chris@8 49 bool
Chris@8 50 Selection::isEmpty() const
Chris@8 51 {
Chris@8 52 return m_startFrame == m_endFrame;
Chris@8 53 }
Chris@8 54
Chris@8 55 size_t
Chris@8 56 Selection::getStartFrame() const
Chris@8 57 {
Chris@8 58 return m_startFrame;
Chris@8 59 }
Chris@8 60
Chris@8 61 size_t
Chris@8 62 Selection::getEndFrame() const
Chris@8 63 {
Chris@8 64 return m_endFrame;
Chris@8 65 }
Chris@8 66
Chris@8 67 bool
Chris@9 68 Selection::contains(size_t frame) const
Chris@9 69 {
Chris@9 70 return (frame >= m_startFrame) && (frame < m_endFrame);
Chris@9 71 }
Chris@9 72
Chris@9 73 bool
Chris@8 74 Selection::operator<(const Selection &s) const
Chris@8 75 {
Chris@9 76 if (isEmpty()) {
Chris@9 77 if (s.isEmpty()) return false;
Chris@9 78 else return true;
Chris@9 79 } else {
Chris@9 80 if (s.isEmpty()) return false;
Chris@9 81 else return (m_startFrame < s.m_startFrame);
Chris@9 82 }
Chris@8 83 }
Chris@8 84
Chris@8 85 bool
Chris@8 86 Selection::operator==(const Selection &s) const
Chris@8 87 {
Chris@9 88 if (isEmpty()) return s.isEmpty();
Chris@9 89
Chris@8 90 return (m_startFrame == s.m_startFrame &&
Chris@8 91 m_endFrame == s.m_endFrame);
Chris@8 92 }
Chris@8 93
Chris@24 94
Chris@24 95 MultiSelection::MultiSelection()
Chris@24 96 {
Chris@24 97 }
Chris@24 98
Chris@24 99 MultiSelection::~MultiSelection()
Chris@24 100 {
Chris@24 101 }
Chris@24 102
Chris@24 103 const MultiSelection::SelectionList &
Chris@24 104 MultiSelection::getSelections() const
Chris@24 105 {
Chris@24 106 return m_selections;
Chris@24 107 }
Chris@24 108
Chris@24 109 void
Chris@24 110 MultiSelection::setSelection(const Selection &selection)
Chris@24 111 {
Chris@24 112 clearSelections();
Chris@24 113 addSelection(selection);
Chris@24 114 }
Chris@24 115
Chris@24 116 void
Chris@24 117 MultiSelection::addSelection(const Selection &selection)
Chris@24 118 {
Chris@24 119 m_selections.insert(selection);
Chris@24 120
Chris@24 121 // Cope with a sitation where the new selection overlaps one or
Chris@24 122 // more existing ones. This is a terribly inefficient way to do
Chris@24 123 // this, but that probably isn't significant in real life.
Chris@24 124
Chris@24 125 // It's essential for the correct operation of
Chris@24 126 // getContainingSelection that the selections do not overlap, so
Chris@24 127 // this is not just a frill.
Chris@24 128
Chris@24 129 for (SelectionList::iterator i = m_selections.begin();
Chris@24 130 i != m_selections.end(); ) {
Chris@24 131
Chris@24 132 SelectionList::iterator j = i;
Chris@24 133 if (++j == m_selections.end()) break;
Chris@24 134
Chris@24 135 if (i->getEndFrame() >= j->getStartFrame()) {
Chris@24 136 Selection merged(i->getStartFrame(),
Chris@24 137 std::max(i->getEndFrame(), j->getEndFrame()));
Chris@24 138 m_selections.erase(i);
Chris@24 139 m_selections.erase(j);
Chris@24 140 m_selections.insert(merged);
Chris@24 141 i = m_selections.begin();
Chris@24 142 } else {
Chris@24 143 ++i;
Chris@24 144 }
Chris@24 145 }
Chris@24 146 }
Chris@24 147
Chris@24 148 void
Chris@24 149 MultiSelection::removeSelection(const Selection &selection)
Chris@24 150 {
Chris@24 151 //!!! Likewise this needs to cope correctly with the situation
Chris@24 152 //where selection is not one of the original selection set but
Chris@24 153 //simply overlaps one of them (cutting down the original selection
Chris@24 154 //appropriately)
Chris@24 155
Chris@24 156 if (m_selections.find(selection) != m_selections.end()) {
Chris@24 157 m_selections.erase(selection);
Chris@24 158 }
Chris@24 159 }
Chris@24 160
Chris@24 161 void
Chris@24 162 MultiSelection::clearSelections()
Chris@24 163 {
Chris@24 164 if (!m_selections.empty()) {
Chris@24 165 m_selections.clear();
Chris@24 166 }
Chris@24 167 }
Chris@24 168
Chris@24 169 Selection
Chris@24 170 MultiSelection::getContainingSelection(size_t frame, bool defaultToFollowing)
Chris@24 171 {
Chris@24 172 // This scales very badly with the number of selections, but it's
Chris@24 173 // more efficient for very small numbers of selections than a more
Chris@24 174 // scalable method, and I think that may be what we need
Chris@24 175
Chris@24 176 for (SelectionList::const_iterator i = m_selections.begin();
Chris@24 177 i != m_selections.end(); ++i) {
Chris@24 178
Chris@24 179 if (i->contains(frame)) return *i;
Chris@24 180
Chris@24 181 if (i->getStartFrame() > frame) {
Chris@24 182 if (defaultToFollowing) return *i;
Chris@24 183 else return Selection();
Chris@24 184 }
Chris@24 185 }
Chris@24 186
Chris@24 187 return Selection();
Chris@24 188 }