Mercurial > hg > svcore
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 |