annotate align/Align.h @ 778:83a7b10b7415

Merge from branch pitch-align
author Chris Cannam
date Fri, 26 Jun 2020 13:48:52 +0100
parents 32e66fcc4cb7
children b651dc5ff555
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@767 118
Chris@423 119 /**
Chris@423 120 * Align the "other" model to the reference, attaching an
Chris@423 121 * AlignmentModel to it. Alignment is carried out by the method
Chris@776 122 * configured in the user preferences (see
Chris@776 123 * getAlignmentPreference() etc) and is done asynchronously.
Chris@423 124 *
Chris@761 125 * Any errors are reported by firing the alignmentFailed
Chris@761 126 * signal. Note that the signal may be fired during the call to
Chris@761 127 * this function, if the aligner fails to start at all.
Chris@761 128 *
Chris@761 129 * If alignment starts successfully, then an AlignmentModel has
Chris@670 130 * been constructed and attached to the toAlign model, and you can
Chris@670 131 * query that model to discover the alignment progress, eventual
Chris@761 132 * outcome, and also (separately from the alignmentFailed signal
Chris@761 133 * here) any error message generated during alignment.
Chris@670 134 *
Chris@423 135 * A single Align object may carry out many simultanous alignment
Chris@423 136 * calls -- you do not need to create a new Align object each
Chris@423 137 * time, nor to wait for an alignment to be complete before
Chris@423 138 * starting a new one.
Chris@423 139 *
Chris@423 140 * The Align object must survive after this call, for at least as
Chris@428 141 * long as the alignment takes. The usual expectation is that the
Chris@428 142 * Align object will simply share the process or document
Chris@428 143 * lifespan.
Chris@423 144 */
Chris@761 145 void alignModel(Document *doc,
Chris@683 146 ModelId reference,
Chris@761 147 ModelId toAlign);
Chris@420 148
Chris@428 149 /**
Chris@761 150 * As alignModel, except that the alignment does not begin
Chris@761 151 * immediately, but is instead placed behind an event callback
Chris@761 152 * with a small delay. Useful to avoid an unresponsive GUI when
Chris@761 153 * firing off alignments while doing something else as well. Any
Chris@761 154 * error is reported by firing the alignmentFailed signal.
Chris@761 155 *
Chris@761 156 * Scheduled alignments are not queued or serialised - many could
Chris@761 157 * happen at once. They are just delayed a little for UI
Chris@761 158 * responsiveness.
Chris@761 159 */
Chris@761 160 void scheduleAlignment(Document *doc,
Chris@761 161 ModelId reference,
Chris@761 162 ModelId toAlign);
Chris@761 163
Chris@761 164 /**
Chris@776 165 * Return true if the preferred alignment facility is available
Chris@776 166 * (relevant plugin installed, etc).
Chris@428 167 */
Chris@428 168 static bool canAlign();
Chris@428 169
Chris@428 170 signals:
Chris@428 171 /**
Chris@428 172 * Emitted when an alignment is successfully completed. The
Chris@428 173 * reference and other models can be queried from the alignment
Chris@428 174 * model.
Chris@428 175 */
Chris@683 176 void alignmentComplete(ModelId alignmentModel); // an AlignmentModel
Chris@428 177
Chris@761 178 /**
Chris@761 179 * Emitted when an alignment fails. The model is the toAlign model
Chris@761 180 * that was passed to the call to alignModel or scheduleAlignment.
Chris@761 181 */
Chris@761 182 void alignmentFailed(ModelId toAlign, QString errorText);
Chris@761 183
Chris@423 184 private slots:
Chris@753 185 void alignerComplete(ModelId alignmentModel); // an AlignmentModel
Chris@761 186 void alignerFailed(ModelId toAlign, QString errorText);
Chris@423 187
Chris@420 188 private:
Chris@670 189 QMutex m_mutex;
Chris@671 190
Chris@753 191 // maps toAlign -> aligner for ongoing alignment - note that
Chris@753 192 // although we can calculate alignments with different references,
Chris@753 193 // we can only have one alignment on any given toAlign model, so
Chris@753 194 // we don't key this on the whole (reference, toAlign) pair
Chris@753 195 std::map<ModelId, std::shared_ptr<Aligner>> m_aligners;
Chris@671 196
Chris@767 197 bool addAligner(Document *doc, ModelId reference, ModelId toAlign);
Chris@761 198 void removeAligner(QObject *);
Chris@420 199 };
Chris@420 200
Chris@420 201 #endif
Chris@420 202