Mercurial > hg > svapp
comparison framework/Align.cpp @ 671:b6cafe05017d tuning-difference
Make a completion figure available to alignment, + a couple of other fixes
author | Chris Cannam |
---|---|
date | Thu, 16 May 2019 15:55:46 +0100 |
parents | 0960e27c3232 |
children | ae7584dbd668 |
comparison
equal
deleted
inserted
replaced
670:0960e27c3232 | 671:b6cafe05017d |
---|---|
66 QSettings settings; | 66 QSettings settings; |
67 settings.beginGroup("Alignment"); | 67 settings.beginGroup("Alignment"); |
68 bool performPitchCompensation = | 68 bool performPitchCompensation = |
69 settings.value("align-pitch-aware", false).toBool(); | 69 settings.value("align-pitch-aware", false).toBool(); |
70 QString id = ""; | 70 QString id = ""; |
71 //!!! if (performPitchCompensation) { | 71 if (performPitchCompensation) { |
72 id = settings.value | 72 id = settings.value |
73 ("tuning-difference-transform-id", | 73 ("tuning-difference-transform-id", |
74 "vamp:tuning-difference:tuning-difference:tuningfreq") | 74 "vamp:tuning-difference:tuning-difference:tuningfreq") |
75 .toString(); | 75 .toString(); |
76 // } | 76 } |
77 settings.endGroup(); | 77 settings.endGroup(); |
78 return id; | 78 return id; |
79 } | 79 } |
80 | 80 |
81 bool | 81 bool |
143 doc->addAggregateModel(aggregateModel); | 143 doc->addAggregateModel(aggregateModel); |
144 | 144 |
145 AlignmentModel *alignmentModel = | 145 AlignmentModel *alignmentModel = |
146 new AlignmentModel(reference, other, nullptr); | 146 new AlignmentModel(reference, other, nullptr); |
147 | 147 |
148 connect(alignmentModel, SIGNAL(completionChanged()), | |
149 this, SLOT(alignmentCompletionChanged())); | |
150 | |
151 TransformId tdId = getTuningDifferenceTransformName(); | 148 TransformId tdId = getTuningDifferenceTransformName(); |
152 | 149 |
153 if (tdId == "") { | 150 if (tdId == "") { |
154 | 151 |
155 if (beginTransformDrivenAlignment(aggregateModel, alignmentModel)) { | 152 if (beginTransformDrivenAlignment(aggregateModel, alignmentModel)) { |
168 TransformFactory *tf = TransformFactory::getInstance(); | 165 TransformFactory *tf = TransformFactory::getInstance(); |
169 | 166 |
170 Transform transform = tf->getDefaultTransformFor | 167 Transform transform = tf->getDefaultTransformFor |
171 (tdId, aggregateModel->getSampleRate()); | 168 (tdId, aggregateModel->getSampleRate()); |
172 | 169 |
170 transform.setParameter("maxduration", 50); | |
171 transform.setParameter("maxrange", 5); | |
172 | |
173 SVDEBUG << "Align::alignModel: Tuning difference transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl; | 173 SVDEBUG << "Align::alignModel: Tuning difference transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl; |
174 | 174 |
175 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); | 175 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); |
176 | 176 |
177 QString message; | 177 QString message; |
190 rm->setAlignment(alignmentModel); | 190 rm->setAlignment(alignmentModel); |
191 | 191 |
192 connect(tdout, SIGNAL(completionChanged()), | 192 connect(tdout, SIGNAL(completionChanged()), |
193 this, SLOT(tuningDifferenceCompletionChanged())); | 193 this, SLOT(tuningDifferenceCompletionChanged())); |
194 | 194 |
195 m_pendingTuningDiffs[tdout] = | 195 TuningDiffRec rec; |
196 std::pair<AggregateWaveModel *, AlignmentModel *> | 196 rec.input = aggregateModel; |
197 (aggregateModel, alignmentModel); | 197 rec.alignment = alignmentModel; |
198 } | 198 |
199 | 199 // This model exists only so that the AlignmentModel can get a |
200 return true; | 200 // completion value from somewhere while the tuning difference |
201 } | 201 // calculation is going on |
202 | 202 rec.preparatory = new SparseTimeValueModel |
203 bool | 203 (aggregateModel->getSampleRate(), 1);; |
204 Align::beginTransformDrivenAlignment(AggregateWaveModel *aggregateModel, | 204 rec.preparatory->setCompletion(0); |
205 AlignmentModel *alignmentModel, | 205 alignmentModel->setPathFrom(rec.preparatory); |
206 float tuningFrequency) | 206 |
207 { | 207 m_pendingTuningDiffs[tdout] = rec; |
208 TransformId id = getAlignmentTransformName(); | 208 } |
209 | |
210 TransformFactory *tf = TransformFactory::getInstance(); | |
211 | |
212 Transform transform = tf->getDefaultTransformFor | |
213 (id, aggregateModel->getSampleRate()); | |
214 | |
215 transform.setStepSize(transform.getBlockSize()/2); | |
216 transform.setParameter("serialise", 1); | |
217 transform.setParameter("smooth", 0); | |
218 | |
219 if (tuningFrequency != 0.f) { | |
220 transform.setParameter("freq2", tuningFrequency); | |
221 } | |
222 | |
223 SVDEBUG << "Align::alignModel: Alignment transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl; | |
224 | |
225 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); | |
226 | |
227 QString message; | |
228 Model *transformOutput = mtf->transform | |
229 (transform, aggregateModel, message); | |
230 | |
231 if (!transformOutput) { | |
232 transform.setStepSize(0); | |
233 transformOutput = mtf->transform | |
234 (transform, aggregateModel, message); | |
235 } | |
236 | |
237 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> | |
238 (transformOutput); | |
239 | |
240 //!!! callers will need to be updated to get error from | |
241 //!!! alignment model after initial call | |
242 | |
243 if (!path) { | |
244 SVCERR << "Align::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << endl; | |
245 delete transformOutput; | |
246 alignmentModel->setError(message); | |
247 return false; | |
248 } | |
249 | |
250 path->setCompletion(0); | |
251 alignmentModel->setPathFrom(path); | |
252 | |
253 connect(alignmentModel, SIGNAL(completionChanged()), | |
254 this, SLOT(alignmentCompletionChanged())); | |
255 | 209 |
256 return true; | 210 return true; |
257 } | 211 } |
258 | 212 |
259 void | 213 void |
261 { | 215 { |
262 QMutexLocker locker (&m_mutex); | 216 QMutexLocker locker (&m_mutex); |
263 | 217 |
264 SparseTimeValueModel *td = qobject_cast<SparseTimeValueModel *>(sender()); | 218 SparseTimeValueModel *td = qobject_cast<SparseTimeValueModel *>(sender()); |
265 if (!td) return; | 219 if (!td) return; |
266 if (!td->isReady()) return; | |
267 | |
268 disconnect(td, SIGNAL(completionChanged()), | |
269 this, SLOT(alignmentCompletionChanged())); | |
270 | 220 |
271 if (m_pendingTuningDiffs.find(td) == m_pendingTuningDiffs.end()) { | 221 if (m_pendingTuningDiffs.find(td) == m_pendingTuningDiffs.end()) { |
272 SVCERR << "ERROR: Align::tuningDifferenceCompletionChanged: Model " | 222 SVCERR << "ERROR: Align::tuningDifferenceCompletionChanged: Model " |
273 << td << " not found in pending tuning diff map!" << endl; | 223 << td << " not found in pending tuning diff map!" << endl; |
274 return; | 224 return; |
275 } | 225 } |
276 | 226 |
277 std::pair<AggregateWaveModel *, AlignmentModel *> models = | 227 TuningDiffRec rec = m_pendingTuningDiffs[td]; |
278 m_pendingTuningDiffs[td]; | 228 |
229 int completion = 0; | |
230 bool done = td->isReady(&completion); | |
231 | |
232 SVCERR << "Align::tuningDifferenceCompletionChanged: done = " << done << ", completion = " << completion << endl; | |
233 | |
234 if (!done) { | |
235 // This will be the completion the alignment model reports, | |
236 // before the alignment actually begins. It goes up from 0 to | |
237 // 99 (not 100!) and then back to 0 again when we start | |
238 // calculating the actual path in the following phase | |
239 int clamped = (completion == 100 ? 99 : completion); | |
240 SVCERR << "Align::tuningDifferenceCompletionChanged: setting rec.preparatory completion to " << clamped << endl; | |
241 rec.preparatory->setCompletion(clamped); | |
242 return; | |
243 } | |
279 | 244 |
280 float tuningFrequency = 440.f; | 245 float tuningFrequency = 440.f; |
281 | 246 |
282 if (!td->isEmpty()) { | 247 if (!td->isEmpty()) { |
283 tuningFrequency = td->getAllEvents()[0].getValue(); | 248 tuningFrequency = td->getAllEvents()[0].getValue(); |
285 } else { | 250 } else { |
286 SVCERR << "Align::tuningDifferenceCompletionChanged: No tuning frequency reported" << endl; | 251 SVCERR << "Align::tuningDifferenceCompletionChanged: No tuning frequency reported" << endl; |
287 } | 252 } |
288 | 253 |
289 m_pendingTuningDiffs.erase(td); | 254 m_pendingTuningDiffs.erase(td); |
255 td->aboutToDelete(); | |
256 delete td; | |
257 | |
258 rec.alignment->setPathFrom(nullptr); | |
290 | 259 |
291 beginTransformDrivenAlignment | 260 beginTransformDrivenAlignment |
292 (models.first, models.second, tuningFrequency); | 261 (rec.input, rec.alignment, tuningFrequency); |
262 } | |
263 | |
264 bool | |
265 Align::beginTransformDrivenAlignment(AggregateWaveModel *aggregateModel, | |
266 AlignmentModel *alignmentModel, | |
267 float tuningFrequency) | |
268 { | |
269 TransformId id = getAlignmentTransformName(); | |
270 | |
271 TransformFactory *tf = TransformFactory::getInstance(); | |
272 | |
273 Transform transform = tf->getDefaultTransformFor | |
274 (id, aggregateModel->getSampleRate()); | |
275 | |
276 transform.setStepSize(transform.getBlockSize()/2); | |
277 transform.setParameter("serialise", 1); | |
278 transform.setParameter("smooth", 0); | |
279 | |
280 if (tuningFrequency != 0.f) { | |
281 transform.setParameter("freq2", tuningFrequency); | |
282 } | |
283 | |
284 SVDEBUG << "Align::alignModel: Alignment transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl; | |
285 | |
286 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); | |
287 | |
288 QString message; | |
289 Model *transformOutput = mtf->transform | |
290 (transform, aggregateModel, message); | |
291 | |
292 if (!transformOutput) { | |
293 transform.setStepSize(0); | |
294 transformOutput = mtf->transform | |
295 (transform, aggregateModel, message); | |
296 } | |
297 | |
298 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> | |
299 (transformOutput); | |
300 | |
301 //!!! callers will need to be updated to get error from | |
302 //!!! alignment model after initial call | |
303 | |
304 if (!path) { | |
305 SVCERR << "Align::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << endl; | |
306 delete transformOutput; | |
307 alignmentModel->setError(message); | |
308 return false; | |
309 } | |
310 | |
311 path->setCompletion(0); | |
312 alignmentModel->setPathFrom(path); | |
313 | |
314 connect(alignmentModel, SIGNAL(completionChanged()), | |
315 this, SLOT(alignmentCompletionChanged())); | |
316 | |
317 return true; | |
293 } | 318 } |
294 | 319 |
295 void | 320 void |
296 Align::alignmentCompletionChanged() | 321 Align::alignmentCompletionChanged() |
297 { | 322 { |