comparison data/model/AlignmentModel.cpp @ 297:c022976d18e8

* Merge from sv-match-alignment branch (excluding alignment-specific document). - add aggregate wave model (not yet complete enough to be added as a true model in a layer, but there's potential) - add play solo mode - add alignment model -- unused in plain SV - fix two plugin leaks - add m3u playlist support (opens all files at once, potentially hazardous) - fix retrieval of pre-encoded URLs - add ability to resample audio files on import, so as to match rates with other files previously loaded; add preference for same - add preliminary support in transform code for range and rate of transform input - reorganise preferences dialog, move dark-background option to preferences, add option for temporary directory location
author Chris Cannam
date Fri, 28 Sep 2007 13:56:38 +0000
parents
children df707a61b23f
comparison
equal deleted inserted replaced
296:2b6c99b607f1 297:c022976d18e8
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 "AlignmentModel.h"
17
18 #include "SparseTimeValueModel.h"
19
20 AlignmentModel::AlignmentModel(Model *reference,
21 Model *aligned,
22 Model *inputModel,
23 SparseTimeValueModel *path) :
24 m_reference(reference),
25 m_aligned(aligned),
26 m_inputModel(inputModel),
27 m_path(path),
28 m_reversePath(0),
29 m_pathComplete(false)
30 {
31 connect(m_path, SIGNAL(modelChanged()),
32 this, SLOT(pathChanged()));
33
34 connect(m_path, SIGNAL(modelChanged(size_t, size_t)),
35 this, SLOT(pathChanged(size_t, size_t)));
36
37 connect(m_path, SIGNAL(completionChanged()),
38 this, SLOT(pathCompletionChanged()));
39
40 constructReversePath();
41 }
42
43 AlignmentModel::~AlignmentModel()
44 {
45 delete m_inputModel;
46 delete m_path;
47 delete m_reversePath;
48 }
49
50 bool
51 AlignmentModel::isOK() const
52 {
53 return m_path->isOK();
54 }
55
56 size_t
57 AlignmentModel::getStartFrame() const
58 {
59 //!!! do we care about distinct rates?
60 size_t a = m_reference->getStartFrame();
61 size_t b = m_aligned->getStartFrame();
62 return std::min(a, b);
63 }
64
65 size_t
66 AlignmentModel::getEndFrame() const
67 {
68 //!!! do we care about distinct rates?
69 size_t a = m_reference->getEndFrame();
70 size_t b = m_aligned->getEndFrame();
71 return std::max(a, b);
72 }
73
74 size_t
75 AlignmentModel::getSampleRate() const
76 {
77 return m_reference->getSampleRate();
78 }
79
80 Model *
81 AlignmentModel::clone() const
82 {
83 return new AlignmentModel
84 (m_reference, m_aligned,
85 m_inputModel ? m_inputModel->clone() : 0,
86 m_path ? static_cast<SparseTimeValueModel *>(m_path->clone()) : 0);
87 }
88
89 bool
90 AlignmentModel::isReady(int *completion) const
91 {
92 return m_path->isReady(completion);
93 }
94
95 const ZoomConstraint *
96 AlignmentModel::getZoomConstraint() const
97 {
98 return m_path->getZoomConstraint();
99 }
100
101 const Model *
102 AlignmentModel::getReferenceModel() const
103 {
104 return m_reference;
105 }
106
107 const Model *
108 AlignmentModel::getAlignedModel() const
109 {
110 return m_aligned;
111 }
112
113 size_t
114 AlignmentModel::toReference(size_t frame) const
115 {
116 // std::cerr << "AlignmentModel::toReference(" << frame << ")" << std::endl;
117 if (!m_reversePath) constructReversePath();
118 return align(m_reversePath, frame);
119 }
120
121 size_t
122 AlignmentModel::fromReference(size_t frame) const
123 {
124 // std::cerr << "AlignmentModel::fromReference(" << frame << ")" << std::endl;
125 return align(m_path, frame);
126 }
127
128 void
129 AlignmentModel::pathChanged()
130 {
131 }
132
133 void
134 AlignmentModel::pathChanged(size_t, size_t)
135 {
136 if (!m_pathComplete) return;
137 constructReversePath();
138 }
139
140 void
141 AlignmentModel::pathCompletionChanged()
142 {
143 if (!m_pathComplete) {
144 int completion = 0;
145 m_path->isReady(&completion);
146 std::cerr << "AlignmentModel::pathCompletionChanged: completion = "
147 << completion << std::endl;
148 m_pathComplete = (completion == 100); //!!! a bit of a hack
149 if (m_pathComplete) {
150 constructReversePath();
151 delete m_inputModel;
152 m_inputModel = 0;
153 }
154 }
155 emit completionChanged();
156 }
157
158 void
159 AlignmentModel::constructReversePath() const
160 {
161 if (!m_reversePath) {
162 m_reversePath = new SparseTimeValueModel
163 (m_path->getSampleRate(), m_path->getResolution(), false);
164 }
165
166 m_reversePath->clear();
167
168 SparseTimeValueModel::PointList points = m_path->getPoints();
169
170 for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
171 i != points.end(); ++i) {
172 long frame = i->frame;
173 float value = i->value;
174 long rframe = lrintf(value * m_aligned->getSampleRate());
175 float rvalue = (float)frame / (float)m_reference->getSampleRate();
176 m_reversePath->addPoint
177 (SparseTimeValueModel::Point(rframe, rvalue, ""));
178 }
179
180 std::cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points" << std::endl;
181 }
182
183 size_t
184 AlignmentModel::align(SparseTimeValueModel *path, size_t frame) const
185 {
186 // The path consists of a series of points, each with x (time)
187 // equal to the time on the source model and y (value) equal to
188 // the time on the target model. Times and values are both
189 // monotonically increasing.
190
191 const SparseTimeValueModel::PointList &points = path->getPoints();
192
193 if (points.empty()) {
194 // std::cerr << "AlignmentModel::align: No points" << std::endl;
195 return frame;
196 }
197
198 SparseTimeValueModel::Point point(frame);
199 SparseTimeValueModel::PointList::const_iterator i = points.lower_bound(point);
200 if (i == points.end()) --i;
201 float time = i->value;
202 size_t rv = lrintf(time * getSampleRate());
203
204 //!!! interpolate!
205
206 // std::cerr << "AlignmentModel::align: rv = " << rv << std::endl;
207
208 return rv;
209 }
210