annotate framework/TransformUserConfigurator.cpp @ 626:51ecc3e2d71c

Don't resample an incoming audio file to match the main model's rate, if the aim of importing is to replace the main model anyway
author Chris Cannam
date Tue, 09 Oct 2018 15:55:16 +0100
parents b23bebfdfaba
children e2715204feaa
rev   line source
Chris@205 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@205 2
Chris@205 3 /*
Chris@205 4 Sonic Visualiser
Chris@205 5 An audio file viewer and annotation editor.
Chris@205 6 Centre for Digital Music, Queen Mary, University of London.
Chris@205 7
Chris@205 8 This program is free software; you can redistribute it and/or
Chris@205 9 modify it under the terms of the GNU General Public License as
Chris@205 10 published by the Free Software Foundation; either version 2 of the
Chris@205 11 License, or (at your option) any later version. See the file
Chris@205 12 COPYING included with this distribution for more information.
Chris@205 13 */
Chris@205 14
Chris@205 15 #include "TransformUserConfigurator.h"
Chris@205 16
Chris@205 17 #include "transform/TransformFactory.h"
Chris@205 18
Chris@205 19 #include "widgets/PluginParameterDialog.h"
Chris@205 20
Chris@205 21 #include "plugin/FeatureExtractionPluginFactory.h"
Chris@205 22 #include "plugin/RealTimePluginFactory.h"
Chris@205 23 #include "plugin/RealTimePluginInstance.h"
Chris@205 24
Chris@205 25 #include "data/model/DenseTimeValueModel.h"
Chris@205 26
Chris@205 27 #include <vamp-hostsdk/Plugin.h>
Chris@205 28
Chris@205 29 #include <QStringList>
Chris@205 30
Chris@205 31 #include <typeinfo>
Chris@205 32
Chris@395 33 static QWidget *parentWidget = 0;
Chris@395 34
Chris@395 35 void
Chris@395 36 TransformUserConfigurator::setParentWidget(QWidget *w)
Chris@395 37 {
Chris@395 38 parentWidget = w;
Chris@395 39 }
Chris@395 40
Chris@205 41 bool
Chris@205 42 TransformUserConfigurator::getChannelRange(TransformId identifier,
Chris@595 43 Vamp::PluginBase *plugin,
Chris@595 44 int &minChannels, int &maxChannels)
Chris@205 45 {
Chris@205 46 if (plugin && plugin->getType() == "Feature Extraction Plugin") {
Chris@595 47 Vamp::Plugin *vp = static_cast<Vamp::Plugin *>(plugin);
Chris@595 48 SVDEBUG << "TransformUserConfigurator::getChannelRange: is a Vamp plugin" << endl;
Chris@436 49 minChannels = int(vp->getMinChannelCount());
Chris@436 50 maxChannels = int(vp->getMaxChannelCount());
Chris@205 51 return true;
Chris@205 52 } else {
Chris@595 53 SVDEBUG << "TransformUserConfigurator::getChannelRange: is not a Vamp plugin" << endl;
Chris@205 54 return TransformFactory::getInstance()->
Chris@205 55 getTransformChannelRange(identifier, minChannels, maxChannels);
Chris@205 56 }
Chris@205 57 }
Chris@205 58
Chris@205 59 bool
Chris@205 60 TransformUserConfigurator::configure(ModelTransformer::Input &input,
Chris@595 61 Transform &transform,
Chris@595 62 Vamp::PluginBase *plugin,
Chris@214 63 Model *&inputModel,
Chris@595 64 AudioPlaySource *source,
Chris@595 65 sv_frame_t startFrame,
Chris@595 66 sv_frame_t duration,
Chris@595 67 const QMap<QString, Model *> &modelMap,
Chris@595 68 QStringList candidateModelNames,
Chris@595 69 QString defaultModelName)
Chris@205 70 {
Chris@205 71 bool ok = false;
Chris@205 72 QString id = transform.getPluginIdentifier();
Chris@205 73 QString output = transform.getOutput();
Chris@205 74 QString outputLabel = "";
Chris@205 75 QString outputDescription = "";
Chris@205 76
Chris@205 77 bool frequency = false;
Chris@205 78 bool effect = false;
Chris@205 79 bool generator = false;
Chris@205 80
Chris@205 81 if (!plugin) return false;
Chris@205 82
Chris@536 83 SVDEBUG << "TransformUserConfigurator::configure: identifier " << id << endl;
Chris@536 84
Chris@529 85 if (RealTimePluginFactory::instanceFor(id)) {
Chris@205 86
Chris@205 87 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id);
Chris@205 88 const RealTimePluginDescriptor *desc = factory->getPluginDescriptor(id);
Chris@205 89
Chris@205 90 if (desc->audioInputPortCount > 0 &&
Chris@205 91 desc->audioOutputPortCount > 0 &&
Chris@205 92 !desc->isSynth) {
Chris@205 93 effect = true;
Chris@205 94 }
Chris@205 95
Chris@205 96 if (desc->audioInputPortCount == 0) {
Chris@205 97 generator = true;
Chris@205 98 }
Chris@205 99
Chris@205 100 if (output != "A") {
Chris@205 101 int outputNo = output.toInt();
Chris@205 102 if (outputNo >= 0 && outputNo < int(desc->controlOutputPortCount)) {
Chris@205 103 outputLabel = desc->controlOutputPortNames[outputNo].c_str();
Chris@205 104 }
Chris@205 105 }
Chris@205 106
Chris@205 107 RealTimePluginInstance *rtp =
Chris@205 108 static_cast<RealTimePluginInstance *>(plugin);
Chris@205 109
Chris@205 110 if (effect && source) {
Chris@595 111 SVDEBUG << "Setting auditioning effect" << endl;
Chris@205 112 source->setAuditioningEffect(rtp);
Chris@205 113 }
Chris@529 114
Chris@529 115 } else {
Chris@529 116
Chris@529 117 Vamp::Plugin *vp = static_cast<Vamp::Plugin *>(plugin);
Chris@529 118
Chris@595 119 frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain);
Chris@529 120
Chris@595 121 std::vector<Vamp::Plugin::OutputDescriptor> od =
Chris@595 122 vp->getOutputDescriptors();
Chris@529 123
Chris@595 124 // cerr << "configure: looking for output: " << output << endl;
Chris@529 125
Chris@595 126 if (od.size() > 1) {
Chris@595 127 for (size_t i = 0; i < od.size(); ++i) {
Chris@595 128 if (od[i].identifier == output.toStdString()) {
Chris@595 129 outputLabel = od[i].name.c_str();
Chris@595 130 outputDescription = od[i].description.c_str();
Chris@595 131 break;
Chris@595 132 }
Chris@595 133 }
Chris@529 134 }
Chris@205 135 }
Chris@529 136
Chris@205 137 int sourceChannels = 1;
Chris@205 138 if (dynamic_cast<DenseTimeValueModel *>(inputModel)) {
Chris@595 139 sourceChannels = dynamic_cast<DenseTimeValueModel *>(inputModel)
Chris@595 140 ->getChannelCount();
Chris@205 141 }
Chris@205 142
Chris@205 143 int minChannels = 1, maxChannels = sourceChannels;
Chris@205 144 getChannelRange(transform.getIdentifier(), plugin,
Chris@595 145 minChannels, maxChannels);
Chris@205 146
Chris@205 147 int targetChannels = sourceChannels;
Chris@205 148 if (!effect) {
Chris@595 149 if (sourceChannels < minChannels) targetChannels = minChannels;
Chris@595 150 if (sourceChannels > maxChannels) targetChannels = maxChannels;
Chris@205 151 }
Chris@205 152
Chris@205 153 int defaultChannel = -1; //!!! no longer saved! [was context.channel]
Chris@205 154
Chris@395 155 PluginParameterDialog *dialog = new PluginParameterDialog
Chris@395 156 (plugin, parentWidget);
Chris@205 157
Chris@205 158 dialog->setMoreInfoUrl(TransformFactory::getInstance()->
Chris@595 159 getTransformInfoUrl(transform.getIdentifier()));
Chris@205 160
Chris@205 161 if (candidateModelNames.size() > 1 && !generator) {
Chris@595 162 dialog->setCandidateInputModels(candidateModelNames,
Chris@595 163 defaultModelName);
Chris@205 164 }
Chris@205 165
Chris@205 166 if (startFrame != 0 || duration != 0) {
Chris@595 167 dialog->setShowSelectionOnlyOption(true);
Chris@205 168 }
Chris@205 169
Chris@205 170 if (targetChannels > 0) {
Chris@595 171 dialog->setChannelArrangement(sourceChannels, targetChannels,
Chris@595 172 defaultChannel);
Chris@205 173 }
Chris@205 174
Chris@205 175 dialog->setOutputLabel(outputLabel, outputDescription);
Chris@205 176
Chris@205 177 dialog->setShowProcessingOptions(true, frequency);
Chris@205 178
Chris@205 179 if (dialog->exec() == QDialog::Accepted) {
Chris@595 180 ok = true;
Chris@205 181 }
Chris@205 182
Chris@205 183 QString selectedInput = dialog->getInputModel();
Chris@205 184 if (selectedInput != "") {
Chris@595 185 if (modelMap.contains(selectedInput)) {
Chris@595 186 inputModel = modelMap.value(selectedInput);
Chris@595 187 SVDEBUG << "Found selected input \"" << selectedInput << "\" in model map, result is " << inputModel << endl;
Chris@595 188 } else {
Chris@595 189 SVDEBUG << "Failed to find selected input \"" << selectedInput << "\" in model map" << endl;
Chris@595 190 }
Chris@205 191 } else {
Chris@595 192 SVDEBUG << "Selected input empty: \"" << selectedInput << "\"" << endl;
Chris@205 193 }
Chris@205 194
Chris@205 195 // Write parameters back to transform object
Chris@205 196 TransformFactory::getInstance()->
Chris@595 197 setParametersFromPlugin(transform, plugin);
Chris@205 198
Chris@205 199 input.setChannel(dialog->getChannel());
Chris@205 200
Chris@205 201 //!!! The dialog ought to be taking & returning transform
Chris@205 202 //objects and input objects and stuff rather than passing
Chris@205 203 //around all this misc stuff, but that's for tomorrow
Chris@205 204 //(whenever that may be)
Chris@205 205
Chris@205 206 if (startFrame != 0 || duration != 0) {
Chris@595 207 if (dialog->getSelectionOnly()) {
Chris@595 208 transform.setStartTime(RealTime::frame2RealTime
Chris@595 209 (startFrame, inputModel->getSampleRate()));
Chris@595 210 transform.setDuration(RealTime::frame2RealTime
Chris@595 211 (duration, inputModel->getSampleRate()));
Chris@595 212 }
Chris@205 213 }
Chris@205 214
Chris@366 215 int stepSize = 0, blockSize = 0;
Chris@205 216 WindowType windowType = HanningWindow;
Chris@205 217
Chris@205 218 dialog->getProcessingParameters(stepSize,
Chris@595 219 blockSize,
Chris@595 220 windowType);
Chris@205 221
Chris@205 222 transform.setStepSize(stepSize);
Chris@205 223 transform.setBlockSize(blockSize);
Chris@205 224 transform.setWindowType(windowType);
Chris@205 225
Chris@205 226 delete dialog;
Chris@205 227
Chris@205 228 if (effect && source) {
Chris@595 229 source->setAuditioningEffect(0);
Chris@205 230 }
Chris@205 231
Chris@205 232 return ok;
Chris@205 233 }
Chris@205 234