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 {