annotate align/Align.h @ 781:b651dc5ff555

Add subsequence option all over the place
author Chris Cannam
date Thu, 16 Jul 2020 18:01:50 +0100
parents 32e66fcc4cb7
children e136dd3bb5c6
rev   line source
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@776 83 * Get the external program associated with the
Chris@776 84 * ExternalProgramAlignment type, if any is set (an empty string
Chris@776 85 * otherwise). Note that this will return a value if any has ever
Chris@776 86 * been set, regardless of whether ExternalProgramAlignment is the
Chris@776 87 * currently chosen alignment type or not.
Chris@776 88 */
Chris@776 89 static QString getPreferredAlignmentProgram();
Chris@776 90
Chris@776 91 /**
Chris@776 92 * Set the external program associated with the
Chris@776 93 * ExternalProgramAlignment type. It is not necessary for the
Chris@776 94 * current preferred alignment type actually to be
Chris@776 95 * ExternalProgramAlignment in order to change this setting. No
Chris@776 96 * validation is carried out on the argument - we don't verify
Chris@776 97 * that it actually is the path of a program, or anything else.
Chris@776 98 */
Chris@776 99 static void setPreferredAlignmentProgram(QString program);
Chris@776 100
Chris@776 101 /**
Chris@776 102 * Get the transform associated with the
Chris@776 103 * TransformDrivenDTWAlignment type, if any is set (a default
Chris@776 104 * constructed Transform otherwise). Note that this will return a
Chris@776 105 * value if any has ever been set, regardless of whether
Chris@776 106 * TransformDrivenDTWAlignment is the currently chosen alignment
Chris@776 107 * type or not.
Chris@776 108 */
Chris@776 109 static Transform getPreferredAlignmentTransform();
Chris@776 110
Chris@776 111 /**
Chris@776 112 * Set the transform associated with the
Chris@776 113 * TransformDrivenDTWAlignment type. It is not necessary for the
Chris@776 114 * current preferred alignment type actually to be
Chris@776 115 * TransformDrivenDTWAlignment in order to change this setting.
Chris@776 116 */
Chris@776 117 static void setPreferredAlignmentTransform(Transform transform);
Chris@781 118
Chris@781 119 /**
Chris@781 120 * Return true if subsequence alignment is preferred. In this case
Chris@781 121 * the toAlign model is aligned to the best-matching subsequence
Chris@781 122 * of the reference model rather than to the whole reference. This
Chris@781 123 * is only possible for the true built-in alignment types - it's
Chris@781 124 * meaningless for linear or trimmed linear alignment, and for
Chris@781 125 * external program alignment. The default is false.
Chris@781 126 */
Chris@781 127 static bool getUseSubsequenceAlignment();
Chris@781 128
Chris@781 129 /**
Chris@781 130 * Set whether subsequence alignment is to be preferred.
Chris@781 131 */
Chris@781 132 static void setUseSubsequenceAlignment(bool subsequence);
Chris@767 133
Chris@423 134 /**
Chris@423 135 * Align the "other" model to the reference, attaching an
Chris@423 136 * AlignmentModel to it. Alignment is carried out by the method
Chris@776 137 * configured in the user preferences (see
Chris@776 138 * getAlignmentPreference() etc) and is done asynchronously.
Chris@423 139 *
Chris@761 140 * Any errors are reported by firing the alignmentFailed
Chris@761 141 * signal. Note that the signal may be fired during the call to
Chris@761 142 * this function, if the aligner fails to start at all.
Chris@761 143 *
Chris@761 144 * If alignment starts successfully, then an AlignmentModel has
Chris@670 145 * been constructed and attached to the toAlign model, and you can
Chris@670 146 * query that model to discover the alignment progress, eventual
Chris@761 147 * outcome, and also (separately from the alignmentFailed signal
Chris@761 148 * here) any error message generated during alignment.
Chris@670 149 *
Chris@423 150 * A single Align object may carry out many simultanous alignment
Chris@423 151 * calls -- you do not need to create a new Align object each
Chris@423 152 * time, nor to wait for an alignment to be complete before
Chris@423 153 * starting a new one.
Chris@423 154 *
Chris@423 155 * The Align object must survive after this call, for at least as
Chris@428 156 * long as the alignment takes. The usual expectation is that the
Chris@428 157 * Align object will simply share the process or document
Chris@428 158 * lifespan.
Chris@423 159 */
Chris@761 160 void alignModel(Document *doc,
Chris@683 161 ModelId reference,
Chris@761 162 ModelId toAlign);
Chris@420 163
Chris@428 164 /**
Chris@761 165 * As alignModel, except that the alignment does not begin
Chris@761 166 * immediately, but is instead placed behind an event callback
Chris@761 167 * with a small delay. Useful to avoid an unresponsive GUI when
Chris@761 168 * firing off alignments while doing something else as well. Any
Chris@761 169 * error is reported by firing the alignmentFailed signal.
Chris@761 170 *
Chris@761 171 * Scheduled alignments are not queued or serialised - many could
Chris@761 172 * happen at once. They are just delayed a little for UI
Chris@761 173 * responsiveness.
Chris@761 174 */
Chris@761 175 void scheduleAlignment(Document *doc,
Chris@761 176 ModelId reference,
Chris@761 177 ModelId toAlign);
Chris@761 178
Chris@761 179 /**
Chris@776 180 * Return true if the preferred alignment facility is available
Chris@776 181 * (relevant plugin installed, etc).
Chris@428 182 */
Chris@428 183 static bool canAlign();
Chris@428 184
Chris@428 185 signals:
Chris@428 186 /**
Chris@428 187 * Emitted when an alignment is successfully completed. The
Chris@428 188 * reference and other models can be queried from the alignment
Chris@428 189 * model.
Chris@428 190 */
Chris@683 191 void alignmentComplete(ModelId alignmentModel); // an AlignmentModel
Chris@428 192
Chris@761 193 /**
Chris@761 194 * Emitted when an alignment fails. The model is the toAlign model
Chris@761 195 * that was passed to the call to alignModel or scheduleAlignment.
Chris@761 196 */
Chris@761 197 void alignmentFailed(ModelId toAlign, QString errorText);
Chris@761 198
Chris@423 199 private slots:
Chris@753 200 void alignerComplete(ModelId alignmentModel); // an AlignmentModel
Chris@761 201 void alignerFailed(ModelId toAlign, QString errorText);
Chris@423 202
Chris@420 203 private:
Chris@670 204 QMutex m_mutex;
Chris@671 205
Chris@753 206 // maps toAlign -> aligner for ongoing alignment - note that
Chris@753 207 // although we can calculate alignments with different references,
Chris@753 208 // we can only have one alignment on any given toAlign model, so
Chris@753 209 // we don't key this on the whole (reference, toAlign) pair
Chris@753 210 std::map<ModelId, std::shared_ptr<Aligner>> m_aligners;
Chris@671 211
Chris@767 212 bool addAligner(Document *doc, ModelId reference, ModelId toAlign);
Chris@761 213 void removeAligner(QObject *);
Chris@420 214 };
Chris@420 215
Chris@420 216 #endif
Chris@420 217