comparison align/Align.cpp @ 767:dd742e566e60 pitch-align

Make a start on further alignment methods
author Chris Cannam
date Thu, 21 May 2020 16:21:57 +0100
parents 6429a164b7e1
children 1b1960009be6
comparison
equal deleted inserted replaced
761:6429a164b7e1 767:dd742e566e60
11 License, or (at your option) any later version. See the file 11 License, or (at your option) any later version. See the file
12 COPYING included with this distribution for more information. 12 COPYING included with this distribution for more information.
13 */ 13 */
14 14
15 #include "Align.h" 15 #include "Align.h"
16
17 #include "LinearAligner.h"
16 #include "TransformAligner.h" 18 #include "TransformAligner.h"
19 #include "TransformDTWAligner.h"
17 #include "ExternalProgramAligner.h" 20 #include "ExternalProgramAligner.h"
21
18 #include "framework/Document.h" 22 #include "framework/Document.h"
23
24 #include "transform/Transform.h"
25 #include "transform/TransformFactory.h"
19 26
20 #include <QSettings> 27 #include <QSettings>
21 #include <QTimer> 28 #include <QTimer>
29
30 using std::make_shared;
31
32 QString
33 Align::getAlignmentTypeTag(AlignmentType type)
34 {
35 switch (type) {
36 case NoAlignment:
37 default:
38 return "no-alignment";
39 case LinearAlignment:
40 return "linear-alignment";
41 case TrimmedLinearAlignment:
42 return "trimmed-linear-alignment";
43 case MATCHAlignment:
44 return "match-alignment";
45 case MATCHAlignmentWithPitchCompare:
46 return "match-alignment-with-pitch";
47 case SungPitchContourAlignment:
48 return "sung-pitch-alignment";
49 case TransformDrivenDTWAlignment:
50 return "transform-driven-alignment";
51 case ExternalProgramAlignment:
52 return "external-program-alignment";
53 }
54 }
55
56 Align::AlignmentType
57 Align::getAlignmentTypeForTag(QString tag)
58 {
59 for (int i = 0; i <= int(LastAlignmentType); ++i) {
60 if (tag == getAlignmentTypeTag(AlignmentType(i))) {
61 return AlignmentType(i);
62 }
63 }
64 return NoAlignment;
65 }
22 66
23 void 67 void
24 Align::alignModel(Document *doc, 68 Align::alignModel(Document *doc,
25 ModelId reference, 69 ModelId reference,
26 ModelId toAlign) 70 ModelId toAlign)
27 { 71 {
28 addAligner(doc, reference, toAlign); 72 if (addAligner(doc, reference, toAlign)) {
29 m_aligners[toAlign]->begin(); 73 m_aligners[toAlign]->begin();
74 }
30 } 75 }
31 76
32 void 77 void
33 Align::scheduleAlignment(Document *doc, 78 Align::scheduleAlignment(Document *doc,
34 ModelId reference, 79 ModelId reference,
35 ModelId toAlign) 80 ModelId toAlign)
36 { 81 {
37 addAligner(doc, reference, toAlign); 82 int delay = 700 * int(m_aligners.size());
38 int delay = 500 + 500 * int(m_aligners.size());
39 if (delay > 3500) { 83 if (delay > 3500) {
40 delay = 3500; 84 delay = 3500;
41 } 85 }
86 if (!addAligner(doc, reference, toAlign)) {
87 return;
88 }
42 SVCERR << "Align::scheduleAlignment: delaying " << delay << "ms" << endl; 89 SVCERR << "Align::scheduleAlignment: delaying " << delay << "ms" << endl;
43 QTimer::singleShot(delay, m_aligners[toAlign].get(), SLOT(begin())); 90 QTimer::singleShot(delay, m_aligners[toAlign].get(), SLOT(begin()));
44 } 91 }
45 92
46 void 93 bool
47 Align::addAligner(Document *doc, 94 Align::addAligner(Document *doc,
48 ModelId reference, 95 ModelId reference,
49 ModelId toAlign) 96 ModelId toAlign)
50 { 97 {
51 bool useProgram; 98 QString additionalData;
52 QString program; 99 AlignmentType type = getAlignmentPreference(additionalData);
53 getAlignerPreference(useProgram, program);
54 100
55 std::shared_ptr<Aligner> aligner; 101 std::shared_ptr<Aligner> aligner;
56 102
57 { 103 {
58 // Replace the aligner with a new one. This also stops any 104 // Replace the aligner with a new one. This also stops any
59 // previously-running alignment, when the old entry is 105 // previously-running alignment, when the old entry is
60 // replaced and its aligner destroyed. 106 // replaced and its aligner destroyed.
61 107
62 QMutexLocker locker(&m_mutex); 108 QMutexLocker locker(&m_mutex);
63 109
64 if (useProgram && (program != "")) { 110 switch (type) {
65 m_aligners[toAlign] = 111
66 std::make_shared<ExternalProgramAligner>(doc, 112 case NoAlignment:
67 reference, 113 return false;
68 toAlign, 114
69 program); 115 case LinearAlignment:
70 } else { 116 case TrimmedLinearAlignment: {
71 m_aligners[toAlign] = 117 bool trimmed = (type == TrimmedLinearAlignment);
72 std::make_shared<TransformAligner>(doc, 118 aligner = make_shared<LinearAligner>(doc,
73 reference, 119 reference,
74 toAlign); 120 toAlign,
75 } 121 trimmed);
76 122 break;
77 aligner = m_aligners[toAlign]; 123 }
124
125 case MATCHAlignment:
126 case MATCHAlignmentWithPitchCompare: {
127
128 bool withTuningDifference =
129 (type == MATCHAlignmentWithPitchCompare);
130
131 aligner = make_shared<TransformAligner>(doc,
132 reference,
133 toAlign,
134 withTuningDifference);
135 break;
136 }
137
138 case SungPitchContourAlignment:
139 {
140 auto refModel = ModelById::get(reference);
141 if (!refModel) return false;
142
143 Transform transform = TransformFactory::getInstance()->
144 getDefaultTransformFor("vamp:pyin:pyin:smoothedpitchtrack",
145 refModel->getSampleRate());
146
147 transform.setParameter("outputunvoiced", 2.f);
148
149 aligner = make_shared<TransformDTWAligner>
150 (doc,
151 reference,
152 toAlign,
153 transform,
154 TransformDTWAligner::RiseFall);
155 break;
156 }
157
158 case TransformDrivenDTWAlignment:
159 throw std::logic_error("Not yet implemented"); //!!!
160
161 case ExternalProgramAlignment: {
162 aligner = make_shared<ExternalProgramAligner>(doc,
163 reference,
164 toAlign,
165 additionalData);
166 }
167 }
168
169 m_aligners[toAlign] = aligner;
78 } 170 }
79 171
80 connect(aligner.get(), SIGNAL(complete(ModelId)), 172 connect(aligner.get(), SIGNAL(complete(ModelId)),
81 this, SLOT(alignerComplete(ModelId))); 173 this, SLOT(alignerComplete(ModelId)));
82 174
83 connect(aligner.get(), SIGNAL(failed(ModelId, QString)), 175 connect(aligner.get(), SIGNAL(failed(ModelId, QString)),
84 this, SLOT(alignerFailed(ModelId, QString))); 176 this, SLOT(alignerFailed(ModelId, QString)));
85 } 177
86 178 return true;
87 void 179 }
88 Align::getAlignerPreference(bool &useProgram, QString &program) 180
181 Align::AlignmentType
182 Align::getAlignmentPreference(QString &additionalData)
89 { 183 {
90 QSettings settings; 184 QSettings settings;
91 settings.beginGroup("Preferences"); 185 settings.beginGroup("Alignment");
92 useProgram = settings.value("use-external-alignment", false).toBool(); 186
93 program = settings.value("external-alignment-program", "").toString(); 187 QString tag = settings.value
188 ("alignment-type", getAlignmentTypeTag(MATCHAlignment)).toString();
189
190 AlignmentType type = getAlignmentTypeForTag(tag);
191
192 if (type == TransformDrivenDTWAlignment) {
193 additionalData = settings.value("alignment-transform", "").toString();
194 } else if (type == ExternalProgramAlignment) {
195 additionalData = settings.value("alignment-program", "").toString();
196 }
197
198 settings.endGroup();
199 return type;
200 }
201
202 void
203 Align::setAlignmentPreference(AlignmentType type, QString additionalData)
204 {
205 QSettings settings;
206 settings.beginGroup("Alignment");
207
208 QString tag = getAlignmentTypeTag(type);
209 settings.setValue("alignment-type", tag);
210
211 if (type == TransformDrivenDTWAlignment) {
212 settings.setValue("alignment-transform", additionalData);
213 } else if (type == ExternalProgramAlignment) {
214 settings.setValue("alignment-program", additionalData);
215 }
216
94 settings.endGroup(); 217 settings.endGroup();
95 } 218 }
96 219
97 bool 220 bool
98 Align::canAlign() 221 Align::canAlign()
99 { 222 {
100 bool useProgram; 223 QString additionalData;
101 QString program; 224 AlignmentType type = getAlignmentPreference(additionalData);
102 getAlignerPreference(useProgram, program); 225
103 226 if (type == ExternalProgramAlignment) {
104 if (useProgram) { 227 return ExternalProgramAligner::isAvailable(additionalData);
105 return ExternalProgramAligner::isAvailable(program);
106 } else { 228 } else {
107 return TransformAligner::isAvailable(); 229 return TransformAligner::isAvailable();
108 } 230 }
109 } 231 }
110 232