Mercurial > hg > svapp
diff align/Align.cpp @ 767:dd742e566e60 pitch-align
Make a start on further alignment methods
author | Chris Cannam |
---|---|
date | Thu, 21 May 2020 16:21:57 +0100 |
parents | 6429a164b7e1 |
children | 1b1960009be6 |
line wrap: on
line diff
--- a/align/Align.cpp Wed May 06 11:45:27 2020 +0100 +++ b/align/Align.cpp Thu May 21 16:21:57 2020 +0100 @@ -13,20 +13,65 @@ */ #include "Align.h" + +#include "LinearAligner.h" #include "TransformAligner.h" +#include "TransformDTWAligner.h" #include "ExternalProgramAligner.h" + #include "framework/Document.h" +#include "transform/Transform.h" +#include "transform/TransformFactory.h" + #include <QSettings> #include <QTimer> +using std::make_shared; + +QString +Align::getAlignmentTypeTag(AlignmentType type) +{ + switch (type) { + case NoAlignment: + default: + return "no-alignment"; + case LinearAlignment: + return "linear-alignment"; + case TrimmedLinearAlignment: + return "trimmed-linear-alignment"; + case MATCHAlignment: + return "match-alignment"; + case MATCHAlignmentWithPitchCompare: + return "match-alignment-with-pitch"; + case SungPitchContourAlignment: + return "sung-pitch-alignment"; + case TransformDrivenDTWAlignment: + return "transform-driven-alignment"; + case ExternalProgramAlignment: + return "external-program-alignment"; + } +} + +Align::AlignmentType +Align::getAlignmentTypeForTag(QString tag) +{ + for (int i = 0; i <= int(LastAlignmentType); ++i) { + if (tag == getAlignmentTypeTag(AlignmentType(i))) { + return AlignmentType(i); + } + } + return NoAlignment; +} + void Align::alignModel(Document *doc, ModelId reference, ModelId toAlign) { - addAligner(doc, reference, toAlign); - m_aligners[toAlign]->begin(); + if (addAligner(doc, reference, toAlign)) { + m_aligners[toAlign]->begin(); + } } void @@ -34,23 +79,24 @@ ModelId reference, ModelId toAlign) { - addAligner(doc, reference, toAlign); - int delay = 500 + 500 * int(m_aligners.size()); + int delay = 700 * int(m_aligners.size()); if (delay > 3500) { delay = 3500; } + if (!addAligner(doc, reference, toAlign)) { + return; + } SVCERR << "Align::scheduleAlignment: delaying " << delay << "ms" << endl; QTimer::singleShot(delay, m_aligners[toAlign].get(), SLOT(begin())); } -void +bool Align::addAligner(Document *doc, ModelId reference, ModelId toAlign) { - bool useProgram; - QString program; - getAlignerPreference(useProgram, program); + QString additionalData; + AlignmentType type = getAlignmentPreference(additionalData); std::shared_ptr<Aligner> aligner; @@ -60,21 +106,67 @@ // replaced and its aligner destroyed. QMutexLocker locker(&m_mutex); - - if (useProgram && (program != "")) { - m_aligners[toAlign] = - std::make_shared<ExternalProgramAligner>(doc, - reference, - toAlign, - program); - } else { - m_aligners[toAlign] = - std::make_shared<TransformAligner>(doc, - reference, - toAlign); + + switch (type) { + + case NoAlignment: + return false; + + case LinearAlignment: + case TrimmedLinearAlignment: { + bool trimmed = (type == TrimmedLinearAlignment); + aligner = make_shared<LinearAligner>(doc, + reference, + toAlign, + trimmed); + break; } - aligner = m_aligners[toAlign]; + case MATCHAlignment: + case MATCHAlignmentWithPitchCompare: { + + bool withTuningDifference = + (type == MATCHAlignmentWithPitchCompare); + + aligner = make_shared<TransformAligner>(doc, + reference, + toAlign, + withTuningDifference); + break; + } + + case SungPitchContourAlignment: + { + auto refModel = ModelById::get(reference); + if (!refModel) return false; + + Transform transform = TransformFactory::getInstance()-> + getDefaultTransformFor("vamp:pyin:pyin:smoothedpitchtrack", + refModel->getSampleRate()); + + transform.setParameter("outputunvoiced", 2.f); + + aligner = make_shared<TransformDTWAligner> + (doc, + reference, + toAlign, + transform, + TransformDTWAligner::RiseFall); + break; + } + + case TransformDrivenDTWAlignment: + throw std::logic_error("Not yet implemented"); //!!! + + case ExternalProgramAlignment: { + aligner = make_shared<ExternalProgramAligner>(doc, + reference, + toAlign, + additionalData); + } + } + + m_aligners[toAlign] = aligner; } connect(aligner.get(), SIGNAL(complete(ModelId)), @@ -82,27 +174,57 @@ connect(aligner.get(), SIGNAL(failed(ModelId, QString)), this, SLOT(alignerFailed(ModelId, QString))); + + return true; +} + +Align::AlignmentType +Align::getAlignmentPreference(QString &additionalData) +{ + QSettings settings; + settings.beginGroup("Alignment"); + + QString tag = settings.value + ("alignment-type", getAlignmentTypeTag(MATCHAlignment)).toString(); + + AlignmentType type = getAlignmentTypeForTag(tag); + + if (type == TransformDrivenDTWAlignment) { + additionalData = settings.value("alignment-transform", "").toString(); + } else if (type == ExternalProgramAlignment) { + additionalData = settings.value("alignment-program", "").toString(); + } + + settings.endGroup(); + return type; } void -Align::getAlignerPreference(bool &useProgram, QString &program) +Align::setAlignmentPreference(AlignmentType type, QString additionalData) { QSettings settings; - settings.beginGroup("Preferences"); - useProgram = settings.value("use-external-alignment", false).toBool(); - program = settings.value("external-alignment-program", "").toString(); + settings.beginGroup("Alignment"); + + QString tag = getAlignmentTypeTag(type); + settings.setValue("alignment-type", tag); + + if (type == TransformDrivenDTWAlignment) { + settings.setValue("alignment-transform", additionalData); + } else if (type == ExternalProgramAlignment) { + settings.setValue("alignment-program", additionalData); + } + settings.endGroup(); } bool Align::canAlign() { - bool useProgram; - QString program; - getAlignerPreference(useProgram, program); + QString additionalData; + AlignmentType type = getAlignmentPreference(additionalData); - if (useProgram) { - return ExternalProgramAligner::isAvailable(program); + if (type == ExternalProgramAlignment) { + return ExternalProgramAligner::isAvailable(additionalData); } else { return TransformAligner::isAvailable(); }