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@636
|
33 static QWidget *parentWidget = nullptr;
|
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@636
|
229 source->setAuditioningEffect(nullptr);
|
Chris@205
|
230 }
|
Chris@205
|
231
|
Chris@205
|
232 return ok;
|
Chris@205
|
233 }
|
Chris@205
|
234
|