annotate main/Analyser.h @ 698:ee97c742d184 tip

Default branch is now named default on git as well as hg, in case we ever want to switch to mirroring in the other direction
author Chris Cannam
date Thu, 27 Aug 2020 15:58:43 +0100
parents 90ee5448c205
children
rev   line source
Chris@6 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@6 2
Chris@6 3 /*
Chris@6 4 Tony
Chris@6 5 An intonation analysis and annotation tool
Chris@6 6 Centre for Digital Music, Queen Mary, University of London.
Chris@6 7 This file copyright 2006-2012 Chris Cannam and QMUL.
Chris@6 8
Chris@6 9 This program is free software; you can redistribute it and/or
Chris@6 10 modify it under the terms of the GNU General Public License as
Chris@6 11 published by the Free Software Foundation; either version 2 of the
Chris@6 12 License, or (at your option) any later version. See the file
Chris@6 13 COPYING included with this distribution for more information.
Chris@6 14 */
Chris@6 15
Chris@6 16 #ifndef ANALYSER_H
Chris@6 17 #define ANALYSER_H
Chris@6 18
Chris@6 19 #include <QObject>
Chris@191 20 #include <QRect>
Chris@341 21 #include <QMutex>
Chris@6 22
Chris@128 23 #include <map>
Chris@163 24 #include <vector>
Chris@163 25
Chris@163 26 #include "framework/Document.h"
Chris@164 27 #include "base/Selection.h"
Chris@194 28 #include "base/Clipboard.h"
Chris@572 29 #include "data/model/WaveFileModel.h"
Chris@6 30
Chris@6 31 class Pane;
Chris@6 32 class PaneStack;
Chris@6 33 class Layer;
Chris@128 34 class TimeValueLayer;
Chris@128 35 class Layer;
Chris@6 36
Chris@163 37 class Analyser : public QObject,
Chris@163 38 public Document::LayerCreationHandler
Chris@6 39 {
Chris@6 40 Q_OBJECT
Chris@6 41
Chris@6 42 public:
Chris@6 43 Analyser();
Chris@6 44 virtual ~Analyser();
Chris@6 45
Chris@572 46 // Process new main model, add derived layers; return "" on
Chris@572 47 // success or error string on failure
Chris@572 48 QString newFileLoaded(Document *newDocument,
Chris@572 49 ModelId model,
Chris@572 50 PaneStack *paneStack,
Chris@572 51 Pane *pane);
Chris@226 52
Chris@572 53 // Remove any derived layers, process the main model, add derived
Chris@572 54 // layers; return "" on success or error string on failure
Chris@325 55 QString analyseExistingFile();
Chris@325 56
Chris@226 57 // Discard any layers etc associated with the current document
Chris@226 58 void fileClosed();
gyorgyf@45 59
gyorgyf@45 60 void setIntelligentActions(bool);
Chris@6 61
Chris@399 62 bool getDisplayFrequencyExtents(double &min, double &max);
Chris@399 63 bool setDisplayFrequencyExtents(double min, double max);
Chris@227 64
Chris@314 65 // Return completion %age for initial analysis -- 100 means it's done
Chris@314 66 int getInitialAnalysisCompletion();
Chris@314 67
Chris@128 68 enum Component {
Chris@242 69 Audio = 0,
Chris@242 70 PitchTrack = 1,
Chris@242 71 Notes = 2,
Chris@242 72 Spectrogram = 3,
Chris@128 73 };
Chris@128 74
Chris@128 75 bool isVisible(Component c) const;
Chris@128 76 void setVisible(Component c, bool v);
Chris@144 77 void toggleVisible(Component c) { setVisible(c, !isVisible(c)); }
Chris@128 78
Chris@128 79 bool isAudible(Component c) const;
Chris@128 80 void setAudible(Component c, bool v);
Chris@144 81 void toggleAudible(Component c) { setAudible(c, !isAudible(c)); }
Chris@128 82
Chris@128 83 void cycleStatus(Component c) {
Chris@128 84 if (isVisible(c)) {
Chris@128 85 if (isAudible(c)) {
Chris@128 86 setVisible(c, false);
Chris@128 87 setAudible(c, false);
Chris@128 88 } else {
Chris@128 89 setAudible(c, true);
Chris@128 90 }
Chris@128 91 } else {
Chris@128 92 setVisible(c, true);
Chris@128 93 setAudible(c, false);
Chris@128 94 }
Chris@128 95 }
Chris@128 96
Chris@572 97 ModelId getMainModelId() const {
Chris@260 98 return m_fileModel;
Chris@260 99 }
Chris@572 100 std::shared_ptr<WaveFileModel> getMainModel() const {
Chris@572 101 return ModelById::getAs<WaveFileModel>(m_fileModel);
Chris@572 102 }
Chris@260 103
Chris@158 104 float getGain(Component c) const;
Chris@158 105 void setGain(Component c, float gain);
Chris@158 106
Chris@158 107 float getPan(Component c) const;
Chris@158 108 void setPan(Component c, float pan);
Chris@158 109
Chris@399 110 void getEnclosingSelectionScope(sv_frame_t f, sv_frame_t &f0, sv_frame_t &f1);
Chris@139 111
Chris@192 112 struct FrequencyRange {
Chris@192 113 FrequencyRange() : min(0), max(0) { }
Chris@399 114 FrequencyRange(double min_, double max_) : min(min_), max(max_) { }
Chris@192 115 bool isConstrained() const { return min != max; }
Chris@399 116 double min;
Chris@399 117 double max;
Chris@396 118 bool operator==(const FrequencyRange &r) {
Chris@396 119 return min == r.min && max == r.max;
Chris@396 120 }
Chris@192 121 };
Chris@192 122
Chris@164 123 /**
Chris@673 124 * Return the QSettings keys, and their default values, that
Chris@673 125 * affect analysis behaviour. These all live within the Analyser
Chris@673 126 * group in QSettings.
Chris@673 127 */
Chris@673 128 static std::map<QString, QVariant> getAnalysisSettings();
Chris@673 129
Chris@673 130 /**
Chris@165 131 * Analyse the selection and schedule asynchronous adds of
Chris@165 132 * candidate layers for the region it contains. Returns "" on
Chris@192 133 * success or a user-readable error string on failure. If the
Chris@192 134 * frequency range isConstrained(), analysis will be constrained
Chris@192 135 * to that range.
Chris@164 136 */
Chris@192 137 QString reAnalyseSelection(Selection sel, FrequencyRange range);
Chris@164 138
Chris@167 139 /**
Chris@184 140 * Return true if the analysed pitch candidates are currently
Chris@199 141 * visible (they are hidden from the call to reAnalyseSelection
Chris@199 142 * until they are requested through showPitchCandidates()). Note
Chris@199 143 * that this may return true even when no pitch candidate layers
Chris@199 144 * actually exist yet, because they are constructed
Chris@199 145 * asynchronously. If that is the case, then the layers will
Chris@199 146 * appear when they are created (otherwise they will remain hidden
Chris@199 147 * after creation).
Chris@184 148 */
Chris@184 149 bool arePitchCandidatesShown() const;
Chris@184 150
Chris@184 151 /**
Chris@199 152 * Show or hide the analysed pitch candidate layers. This is reset
Chris@199 153 * (to "hide") with each new call to reAnalyseSelection. Because
Chris@199 154 * the layers are created asynchronously, setting this to true
Chris@199 155 * does not guarantee that they appear immediately, only that they
Chris@199 156 * will appear once they have been created.
Chris@184 157 */
Chris@184 158 void showPitchCandidates(bool shown);
Chris@184 159
Chris@184 160 /**
Chris@167 161 * If a re-analysis has been activated, switch the selected area
Chris@167 162 * of the main pitch track to a different candidate from the
Chris@167 163 * analysis results.
Chris@167 164 */
Chris@167 165 void switchPitchCandidate(Selection sel, bool up);
Chris@167 166
Chris@167 167 /**
Chris@199 168 * Return true if it is possible to switch up to another pitch
Chris@199 169 * candidate. This may mean that the currently selected pitch
Chris@199 170 * candidate is not the highest, or it may mean that no alternate
Chris@199 171 * pitch candidate has been selected at all yet (but some are
Chris@199 172 * available).
Chris@199 173 */
Chris@199 174 bool haveHigherPitchCandidate() const;
Chris@199 175
Chris@199 176 /**
Chris@199 177 * Return true if it is possible to switch down to another pitch
Chris@199 178 * candidate. This may mean that the currently selected pitch
Chris@199 179 * candidate is not the lowest, or it may mean that no alternate
Chris@199 180 * pitch candidate has been selected at all yet (but some are
Chris@199 181 * available).
Chris@199 182 */
Chris@199 183 bool haveLowerPitchCandidate() const;
Chris@199 184
Chris@199 185 /**
Chris@184 186 * Delete the pitch estimates from the selected area of the main
Chris@168 187 * pitch track.
Chris@168 188 */
Chris@184 189 void deletePitches(Selection sel);
Chris@168 190
Chris@168 191 /**
Chris@168 192 * Move the main pitch track and any active analysis candidate
Chris@168 193 * tracks up or down an octave in the selected area.
Chris@168 194 */
Chris@168 195 void shiftOctave(Selection sel, bool up);
Chris@168 196
Chris@168 197 /**
Chris@199 198 * Remove any re-analysis layers and also reset the pitch track in
Chris@194 199 * the given selection to its state prior to the last re-analysis,
Chris@199 200 * abandoning any changes made since then. No re-analysis layers
Chris@199 201 * will be available until after the next call to
Chris@199 202 * reAnalyseSelection.
Chris@167 203 */
Chris@199 204 void abandonReAnalysis(Selection sel);
Chris@167 205
Chris@174 206 /**
Chris@269 207 * Remove any re-analysis layers, without any expectation of
Chris@269 208 * adding them later, unlike showPitchCandidates(false), and
Chris@269 209 * without changing the current pitch track, unlike
Chris@269 210 * abandonReAnalysis().
Chris@269 211 */
Chris@269 212 void clearReAnalysis();
Chris@269 213
Chris@269 214 /**
Chris@174 215 * Import the pitch track from the given layer into our
Chris@174 216 * pitch-track layer.
Chris@174 217 */
Chris@174 218 void takePitchTrackFrom(Layer *layer);
Chris@174 219
Chris@174 220 Pane *getPane() {
Chris@174 221 return m_pane;
Chris@174 222 }
Chris@174 223
Chris@174 224 Layer *getLayer(Component type) {
Chris@174 225 return m_layers[type];
Chris@174 226 }
Chris@174 227
Chris@128 228 signals:
Chris@128 229 void layersChanged();
Chris@314 230 void initialAnalysisCompleted();
Chris@128 231
Chris@242 232 protected slots:
Chris@242 233 void layerAboutToBeDeleted(Layer *);
Chris@576 234 void layerCompletionChanged(ModelId);
Chris@403 235 void reAnalyseRegion(sv_frame_t, sv_frame_t, float, float);
Chris@398 236 void materialiseReAnalysis();
Chris@242 237
Chris@6 238 protected:
Chris@6 239 Document *m_document;
Chris@572 240 ModelId m_fileModel;
Chris@133 241 PaneStack *m_paneStack;
Chris@6 242 Pane *m_pane;
Chris@165 243
Chris@128 244 mutable std::map<Component, Layer *> m_layers;
Chris@132 245
Chris@194 246 Clipboard m_preAnalysis;
Chris@165 247 Selection m_reAnalysingSelection;
Chris@396 248 FrequencyRange m_reAnalysingRange;
Chris@165 249 std::vector<Layer *> m_reAnalysisCandidates;
Chris@167 250 int m_currentCandidate;
Chris@184 251 bool m_candidatesVisible;
Chris@341 252 Document::LayerCreationAsyncHandle m_currentAsyncHandle;
Chris@341 253 QMutex m_asyncMutex;
Chris@165 254
Chris@326 255 QString doAllAnalyses(bool withPitchTrack);
Chris@325 256
Chris@161 257 QString addVisualisations();
Chris@161 258 QString addWaveform();
Chris@161 259 QString addAnalyses();
Chris@161 260
Chris@199 261 void discardPitchCandidates();
Chris@260 262
Chris@260 263 void stackLayers();
Chris@199 264
Chris@163 265 // Document::LayerCreationHandler method
Chris@341 266 void layersCreated(Document::LayerCreationAsyncHandle,
Chris@341 267 std::vector<Layer *>, std::vector<Layer *>);
Chris@163 268
Chris@132 269 void saveState(Component c) const;
Chris@132 270 void loadState(Component c);
Chris@6 271 };
Chris@6 272
Chris@6 273 #endif