Chris@420
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@420
|
2
|
Chris@420
|
3 /*
|
Chris@420
|
4 Sonic Visualiser
|
Chris@420
|
5 An audio file viewer and annotation editor.
|
Chris@420
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@420
|
7
|
Chris@420
|
8 This program is free software; you can redistribute it and/or
|
Chris@420
|
9 modify it under the terms of the GNU General Public License as
|
Chris@420
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@420
|
11 License, or (at your option) any later version. See the file
|
Chris@420
|
12 COPYING included with this distribution for more information.
|
Chris@420
|
13 */
|
Chris@420
|
14
|
Chris@754
|
15 #ifndef SV_ALIGN_H
|
Chris@754
|
16 #define SV_ALIGN_H
|
Chris@420
|
17
|
Chris@420
|
18 #include <QString>
|
Chris@423
|
19 #include <QObject>
|
Chris@423
|
20 #include <QProcess>
|
Chris@670
|
21 #include <QMutex>
|
Chris@423
|
22 #include <set>
|
Chris@420
|
23
|
Chris@753
|
24 #include "Aligner.h"
|
Chris@683
|
25
|
Chris@776
|
26 #include "transform/Transform.h"
|
Chris@776
|
27
|
Chris@423
|
28 class AlignmentModel;
|
Chris@664
|
29 class Document;
|
Chris@420
|
30
|
Chris@423
|
31 class Align : public QObject
|
Chris@420
|
32 {
|
Chris@423
|
33 Q_OBJECT
|
Chris@423
|
34
|
Chris@420
|
35 public:
|
Chris@670
|
36 Align() { }
|
Chris@420
|
37
|
Chris@767
|
38 enum AlignmentType {
|
Chris@767
|
39 NoAlignment,
|
Chris@767
|
40 LinearAlignment,
|
Chris@767
|
41 TrimmedLinearAlignment,
|
Chris@767
|
42 MATCHAlignment,
|
Chris@767
|
43 MATCHAlignmentWithPitchCompare,
|
Chris@771
|
44 SungNoteContourAlignment,
|
Chris@767
|
45 TransformDrivenDTWAlignment,
|
Chris@767
|
46 ExternalProgramAlignment,
|
Chris@767
|
47
|
Chris@767
|
48 LastAlignmentType = ExternalProgramAlignment
|
Chris@767
|
49 };
|
Chris@767
|
50
|
Chris@776
|
51 /**
|
Chris@776
|
52 * Convert an alignment type to a stable machine-readable string.
|
Chris@776
|
53 */
|
Chris@767
|
54 static QString getAlignmentTypeTag(AlignmentType type);
|
Chris@776
|
55
|
Chris@776
|
56 /**
|
Chris@776
|
57 * Convert an alignment type back from a stable machine-readable
|
Chris@776
|
58 * string.
|
Chris@776
|
59 */
|
Chris@767
|
60 static AlignmentType getAlignmentTypeForTag(QString tag);
|
Chris@767
|
61
|
Chris@776
|
62 /**
|
Chris@776
|
63 * Get the currently set alignment preference from the global
|
Chris@776
|
64 * application settings. If the returned preference is
|
Chris@776
|
65 * TransformDrivenDTWAlignment or ExternalProgramAlignment, then
|
Chris@776
|
66 * it will also be necessary to query
|
Chris@776
|
67 * getPreferredAlignmentTransform() or
|
Chris@776
|
68 * getPreferredAlignmentProgram() respectively in order to get the
|
Chris@776
|
69 * information needed to perform an alignment.
|
Chris@776
|
70 */
|
Chris@776
|
71 static AlignmentType getAlignmentPreference();
|
Chris@776
|
72
|
Chris@776
|
73 /**
|
Chris@776
|
74 * Set the alignment preference to the global application
|
Chris@776
|
75 * settings. If the preference is TransformDrivenDTWAlignment or
|
Chris@776
|
76 * ExternalProgramAlignment, you may also wish to call
|
Chris@776
|
77 * setPreferredAlignmentTransform() or
|
Chris@776
|
78 * setPreferredAlignmentProgram() respectively.
|
Chris@776
|
79 */
|
Chris@776
|
80 static void setAlignmentPreference(AlignmentType type);
|
Chris@776
|
81
|
Chris@776
|
82 /**
|
Chris@785
|
83 * Set the default alignment preference. That is, if no alignment
|
Chris@785
|
84 * preference has been set by the user yet, set it to this.
|
Chris@785
|
85 */
|
Chris@785
|
86 static void setDefaultAlignmentPreference(AlignmentType type);
|
Chris@785
|
87
|
Chris@785
|
88 /**
|
Chris@776
|
89 * Get the external program associated with the
|
Chris@776
|
90 * ExternalProgramAlignment type, if any is set (an empty string
|
Chris@776
|
91 * otherwise). Note that this will return a value if any has ever
|
Chris@776
|
92 * been set, regardless of whether ExternalProgramAlignment is the
|
Chris@776
|
93 * currently chosen alignment type or not.
|
Chris@776
|
94 */
|
Chris@776
|
95 static QString getPreferredAlignmentProgram();
|
Chris@776
|
96
|
Chris@776
|
97 /**
|
Chris@776
|
98 * Set the external program associated with the
|
Chris@776
|
99 * ExternalProgramAlignment type. It is not necessary for the
|
Chris@776
|
100 * current preferred alignment type actually to be
|
Chris@776
|
101 * ExternalProgramAlignment in order to change this setting. No
|
Chris@776
|
102 * validation is carried out on the argument - we don't verify
|
Chris@776
|
103 * that it actually is the path of a program, or anything else.
|
Chris@776
|
104 */
|
Chris@776
|
105 static void setPreferredAlignmentProgram(QString program);
|
Chris@776
|
106
|
Chris@776
|
107 /**
|
Chris@776
|
108 * Get the transform associated with the
|
Chris@776
|
109 * TransformDrivenDTWAlignment type, if any is set (a default
|
Chris@776
|
110 * constructed Transform otherwise). Note that this will return a
|
Chris@776
|
111 * value if any has ever been set, regardless of whether
|
Chris@776
|
112 * TransformDrivenDTWAlignment is the currently chosen alignment
|
Chris@776
|
113 * type or not.
|
Chris@776
|
114 */
|
Chris@776
|
115 static Transform getPreferredAlignmentTransform();
|
Chris@776
|
116
|
Chris@776
|
117 /**
|
Chris@776
|
118 * Set the transform associated with the
|
Chris@776
|
119 * TransformDrivenDTWAlignment type. It is not necessary for the
|
Chris@776
|
120 * current preferred alignment type actually to be
|
Chris@776
|
121 * TransformDrivenDTWAlignment in order to change this setting.
|
Chris@776
|
122 */
|
Chris@776
|
123 static void setPreferredAlignmentTransform(Transform transform);
|
Chris@781
|
124
|
Chris@781
|
125 /**
|
Chris@781
|
126 * Return true if subsequence alignment is preferred. In this case
|
Chris@781
|
127 * the toAlign model is aligned to the best-matching subsequence
|
Chris@781
|
128 * of the reference model rather than to the whole reference. This
|
Chris@781
|
129 * is only possible for the true built-in alignment types - it's
|
Chris@781
|
130 * meaningless for linear or trimmed linear alignment, and for
|
Chris@781
|
131 * external program alignment. The default is false.
|
Chris@781
|
132 */
|
Chris@781
|
133 static bool getUseSubsequenceAlignment();
|
Chris@781
|
134
|
Chris@781
|
135 /**
|
Chris@781
|
136 * Set whether subsequence alignment is to be preferred.
|
Chris@781
|
137 */
|
Chris@781
|
138 static void setUseSubsequenceAlignment(bool subsequence);
|
Chris@767
|
139
|
Chris@423
|
140 /**
|
Chris@423
|
141 * Align the "other" model to the reference, attaching an
|
Chris@423
|
142 * AlignmentModel to it. Alignment is carried out by the method
|
Chris@776
|
143 * configured in the user preferences (see
|
Chris@776
|
144 * getAlignmentPreference() etc) and is done asynchronously.
|
Chris@423
|
145 *
|
Chris@761
|
146 * Any errors are reported by firing the alignmentFailed
|
Chris@761
|
147 * signal. Note that the signal may be fired during the call to
|
Chris@761
|
148 * this function, if the aligner fails to start at all.
|
Chris@761
|
149 *
|
Chris@761
|
150 * If alignment starts successfully, then an AlignmentModel has
|
Chris@670
|
151 * been constructed and attached to the toAlign model, and you can
|
Chris@670
|
152 * query that model to discover the alignment progress, eventual
|
Chris@761
|
153 * outcome, and also (separately from the alignmentFailed signal
|
Chris@761
|
154 * here) any error message generated during alignment.
|
Chris@670
|
155 *
|
Chris@423
|
156 * A single Align object may carry out many simultanous alignment
|
Chris@423
|
157 * calls -- you do not need to create a new Align object each
|
Chris@423
|
158 * time, nor to wait for an alignment to be complete before
|
Chris@423
|
159 * starting a new one.
|
Chris@423
|
160 *
|
Chris@423
|
161 * The Align object must survive after this call, for at least as
|
Chris@428
|
162 * long as the alignment takes. The usual expectation is that the
|
Chris@428
|
163 * Align object will simply share the process or document
|
Chris@428
|
164 * lifespan.
|
Chris@423
|
165 */
|
Chris@761
|
166 void alignModel(Document *doc,
|
Chris@683
|
167 ModelId reference,
|
Chris@761
|
168 ModelId toAlign);
|
Chris@420
|
169
|
Chris@428
|
170 /**
|
Chris@761
|
171 * As alignModel, except that the alignment does not begin
|
Chris@761
|
172 * immediately, but is instead placed behind an event callback
|
Chris@761
|
173 * with a small delay. Useful to avoid an unresponsive GUI when
|
Chris@761
|
174 * firing off alignments while doing something else as well. Any
|
Chris@761
|
175 * error is reported by firing the alignmentFailed signal.
|
Chris@761
|
176 *
|
Chris@761
|
177 * Scheduled alignments are not queued or serialised - many could
|
Chris@761
|
178 * happen at once. They are just delayed a little for UI
|
Chris@761
|
179 * responsiveness.
|
Chris@761
|
180 */
|
Chris@761
|
181 void scheduleAlignment(Document *doc,
|
Chris@761
|
182 ModelId reference,
|
Chris@761
|
183 ModelId toAlign);
|
Chris@761
|
184
|
Chris@761
|
185 /**
|
Chris@776
|
186 * Return true if the preferred alignment facility is available
|
Chris@776
|
187 * (relevant plugin installed, etc).
|
Chris@428
|
188 */
|
Chris@428
|
189 static bool canAlign();
|
Chris@428
|
190
|
Chris@428
|
191 signals:
|
Chris@428
|
192 /**
|
Chris@428
|
193 * Emitted when an alignment is successfully completed. The
|
Chris@428
|
194 * reference and other models can be queried from the alignment
|
Chris@428
|
195 * model.
|
Chris@428
|
196 */
|
Chris@683
|
197 void alignmentComplete(ModelId alignmentModel); // an AlignmentModel
|
Chris@428
|
198
|
Chris@761
|
199 /**
|
Chris@761
|
200 * Emitted when an alignment fails. The model is the toAlign model
|
Chris@761
|
201 * that was passed to the call to alignModel or scheduleAlignment.
|
Chris@761
|
202 */
|
Chris@761
|
203 void alignmentFailed(ModelId toAlign, QString errorText);
|
Chris@761
|
204
|
Chris@423
|
205 private slots:
|
Chris@753
|
206 void alignerComplete(ModelId alignmentModel); // an AlignmentModel
|
Chris@761
|
207 void alignerFailed(ModelId toAlign, QString errorText);
|
Chris@423
|
208
|
Chris@420
|
209 private:
|
Chris@670
|
210 QMutex m_mutex;
|
Chris@671
|
211
|
Chris@753
|
212 // maps toAlign -> aligner for ongoing alignment - note that
|
Chris@753
|
213 // although we can calculate alignments with different references,
|
Chris@753
|
214 // we can only have one alignment on any given toAlign model, so
|
Chris@753
|
215 // we don't key this on the whole (reference, toAlign) pair
|
Chris@753
|
216 std::map<ModelId, std::shared_ptr<Aligner>> m_aligners;
|
Chris@671
|
217
|
Chris@767
|
218 bool addAligner(Document *doc, ModelId reference, ModelId toAlign);
|
Chris@761
|
219 void removeAligner(QObject *);
|
Chris@420
|
220 };
|
Chris@420
|
221
|
Chris@420
|
222 #endif
|
Chris@420
|
223
|