view align/TransformDTWAligner.h @ 771:1d6cca5a5621 pitch-align

Allow use of proper sparse models (i.e. retaining event time info) in alignment; use this to switch to note alignment, which is what we have most recently been doing in the external program. Not currently producing correct results, though
author Chris Cannam
date Fri, 29 May 2020 17:39:02 +0100
parents 1b1960009be6
children b651dc5ff555
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */

/*
    Sonic Visualiser
    An audio file viewer and annotation editor.
    Centre for Digital Music, Queen Mary, University of London.
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.  See the file
    COPYING included with this distribution for more information.
*/

#ifndef SV_TRANSFORM_DTW_ALIGNER_H
#define SV_TRANSFORM_DTW_ALIGNER_H

#include "Aligner.h"
#include "DTW.h"

#include "transform/Transform.h"
#include "svcore/data/model/Path.h"

#include <functional>

#include <QMutex>

class AlignmentModel;
class Document;

class TransformDTWAligner : public Aligner
{
    Q_OBJECT

public:
    enum DTWType {
        Magnitude,
        RiseFall
    };

    /**
     * Create a TransformDTWAligner that runs the given transform on
     * both models and feeds the resulting values into the given DTW
     * type. If DTWType is Magnitude, the transform output values are
     * used unmodified; if RiseFall, the deltas between consecutive
     * values are used.
     */
    TransformDTWAligner(Document *doc,
                        ModelId reference,
                        ModelId toAlign,
                        Transform transform,
                        DTWType dtwType);

    typedef std::function<double(double)> MagnitudePreprocessor;

    /**
     * Create a TransformDTWAligner that runs the given transform on
     * both models, applies the supplied output preprocessor, and
     * feeds the resulting values into a Magnitude DTW type.
     */
    TransformDTWAligner(Document *doc,
                        ModelId reference,
                        ModelId toAlign,
                        Transform transform,
                        MagnitudePreprocessor outputPreprocessor);

    typedef std::function<RiseFallDTW::Value(double prev, double curr)>
        RiseFallPreprocessor;

    /**
     * Create a TransformDTWAligner that runs the given transform on
     * both models, applies the supplied output preprocessor, and
     * feeds the resulting values into a RiseFall DTW type.
     */
    TransformDTWAligner(Document *doc,
                        ModelId reference,
                        ModelId toAlign,
                        Transform transform,
                        RiseFallPreprocessor outputPreprocessor);

    // Destroy the aligner, cleanly cancelling any ongoing alignment
    ~TransformDTWAligner();

    void begin() override;

    static bool isAvailable();

private slots:
    void completionChanged(ModelId);

private:
    bool performAlignment();
    bool performAlignmentMagnitude();
    bool performAlignmentRiseFall();

    bool getValuesFrom(ModelId modelId,
                       std::vector<sv_frame_t> &frames,
                       std::vector<double> &values,
                       sv_frame_t &resolution);

    Path makePath(const std::vector<size_t> &alignment,
                  const std::vector<sv_frame_t> &refFrames,
                  const std::vector<sv_frame_t> &otherFrames,
                  sv_samplerate_t sampleRate,
                  sv_frame_t resolution);
    
    Document *m_document;
    ModelId m_reference;
    ModelId m_toAlign;
    ModelId m_referenceOutputModel;
    ModelId m_toAlignOutputModel;
    ModelId m_alignmentModel;
    Transform m_transform;
    DTWType m_dtwType;
    bool m_incomplete;
    MagnitudePreprocessor m_magnitudePreprocessor;
    RiseFallPreprocessor m_riseFallPreprocessor;

    static QMutex m_dtwMutex;
};

#endif