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@205
|
33 bool
|
Chris@205
|
34 TransformUserConfigurator::getChannelRange(TransformId identifier,
|
Chris@205
|
35 Vamp::PluginBase *plugin,
|
Chris@205
|
36 int &minChannels, int &maxChannels)
|
Chris@205
|
37 {
|
Chris@205
|
38 if (plugin && plugin->getType() == "Feature Extraction Plugin") {
|
Chris@205
|
39 Vamp::Plugin *vp = static_cast<Vamp::Plugin *>(plugin);
|
Chris@233
|
40 SVDEBUG << "TransformUserConfigurator::getChannelRange: is a VP" << endl;
|
Chris@205
|
41 minChannels = vp->getMinChannelCount();
|
Chris@205
|
42 maxChannels = vp->getMaxChannelCount();
|
Chris@205
|
43 return true;
|
Chris@205
|
44 } else {
|
Chris@233
|
45 SVDEBUG << "TransformUserConfigurator::getChannelRange: is not a VP" << endl;
|
Chris@205
|
46 return TransformFactory::getInstance()->
|
Chris@205
|
47 getTransformChannelRange(identifier, minChannels, maxChannels);
|
Chris@205
|
48 }
|
Chris@205
|
49 }
|
Chris@205
|
50
|
Chris@205
|
51 bool
|
Chris@205
|
52 TransformUserConfigurator::configure(ModelTransformer::Input &input,
|
Chris@205
|
53 Transform &transform,
|
Chris@205
|
54 Vamp::PluginBase *plugin,
|
Chris@214
|
55 Model *&inputModel,
|
Chris@205
|
56 AudioPlaySource *source,
|
Chris@205
|
57 size_t startFrame,
|
Chris@205
|
58 size_t duration,
|
Chris@205
|
59 const QMap<QString, Model *> &modelMap,
|
Chris@205
|
60 QStringList candidateModelNames,
|
Chris@205
|
61 QString defaultModelName)
|
Chris@205
|
62 {
|
Chris@205
|
63 bool ok = false;
|
Chris@205
|
64 QString id = transform.getPluginIdentifier();
|
Chris@205
|
65 QString output = transform.getOutput();
|
Chris@205
|
66 QString outputLabel = "";
|
Chris@205
|
67 QString outputDescription = "";
|
Chris@205
|
68
|
Chris@205
|
69 bool frequency = false;
|
Chris@205
|
70 bool effect = false;
|
Chris@205
|
71 bool generator = false;
|
Chris@205
|
72
|
Chris@205
|
73 if (!plugin) return false;
|
Chris@205
|
74
|
Chris@205
|
75 if (FeatureExtractionPluginFactory::instanceFor(id)) {
|
Chris@205
|
76
|
Chris@205
|
77 Vamp::Plugin *vp = static_cast<Vamp::Plugin *>(plugin);
|
Chris@205
|
78
|
Chris@205
|
79 frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain);
|
Chris@205
|
80
|
Chris@205
|
81 std::vector<Vamp::Plugin::OutputDescriptor> od =
|
Chris@205
|
82 vp->getOutputDescriptors();
|
Chris@205
|
83
|
Chris@293
|
84 cerr << "configure: looking for output: " << output << endl;
|
Chris@205
|
85
|
Chris@205
|
86 if (od.size() > 1) {
|
Chris@205
|
87 for (size_t i = 0; i < od.size(); ++i) {
|
Chris@205
|
88 if (od[i].identifier == output.toStdString()) {
|
Chris@205
|
89 outputLabel = od[i].name.c_str();
|
Chris@205
|
90 outputDescription = od[i].description.c_str();
|
Chris@205
|
91 break;
|
Chris@205
|
92 }
|
Chris@205
|
93 }
|
Chris@205
|
94 }
|
Chris@205
|
95
|
Chris@205
|
96 } else if (RealTimePluginFactory::instanceFor(id)) {
|
Chris@205
|
97
|
Chris@205
|
98 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id);
|
Chris@205
|
99 const RealTimePluginDescriptor *desc = factory->getPluginDescriptor(id);
|
Chris@205
|
100
|
Chris@205
|
101 if (desc->audioInputPortCount > 0 &&
|
Chris@205
|
102 desc->audioOutputPortCount > 0 &&
|
Chris@205
|
103 !desc->isSynth) {
|
Chris@205
|
104 effect = true;
|
Chris@205
|
105 }
|
Chris@205
|
106
|
Chris@205
|
107 if (desc->audioInputPortCount == 0) {
|
Chris@205
|
108 generator = true;
|
Chris@205
|
109 }
|
Chris@205
|
110
|
Chris@205
|
111 if (output != "A") {
|
Chris@205
|
112 int outputNo = output.toInt();
|
Chris@205
|
113 if (outputNo >= 0 && outputNo < int(desc->controlOutputPortCount)) {
|
Chris@205
|
114 outputLabel = desc->controlOutputPortNames[outputNo].c_str();
|
Chris@205
|
115 }
|
Chris@205
|
116 }
|
Chris@205
|
117
|
Chris@205
|
118 RealTimePluginInstance *rtp =
|
Chris@205
|
119 static_cast<RealTimePluginInstance *>(plugin);
|
Chris@205
|
120
|
Chris@205
|
121 if (effect && source) {
|
Chris@233
|
122 SVDEBUG << "Setting auditioning effect" << endl;
|
Chris@205
|
123 source->setAuditioningEffect(rtp);
|
Chris@205
|
124 }
|
Chris@205
|
125 }
|
Chris@205
|
126
|
Chris@205
|
127 int sourceChannels = 1;
|
Chris@205
|
128 if (dynamic_cast<DenseTimeValueModel *>(inputModel)) {
|
Chris@205
|
129 sourceChannels = dynamic_cast<DenseTimeValueModel *>(inputModel)
|
Chris@205
|
130 ->getChannelCount();
|
Chris@205
|
131 }
|
Chris@205
|
132
|
Chris@205
|
133 int minChannels = 1, maxChannels = sourceChannels;
|
Chris@205
|
134 getChannelRange(transform.getIdentifier(), plugin,
|
Chris@205
|
135 minChannels, maxChannels);
|
Chris@205
|
136
|
Chris@205
|
137 int targetChannels = sourceChannels;
|
Chris@205
|
138 if (!effect) {
|
Chris@205
|
139 if (sourceChannels < minChannels) targetChannels = minChannels;
|
Chris@205
|
140 if (sourceChannels > maxChannels) targetChannels = maxChannels;
|
Chris@205
|
141 }
|
Chris@205
|
142
|
Chris@205
|
143 int defaultChannel = -1; //!!! no longer saved! [was context.channel]
|
Chris@205
|
144
|
Chris@205
|
145 PluginParameterDialog *dialog = new PluginParameterDialog(plugin);
|
Chris@205
|
146
|
Chris@205
|
147 dialog->setMoreInfoUrl(TransformFactory::getInstance()->
|
Chris@205
|
148 getTransformInfoUrl(transform.getIdentifier()));
|
Chris@205
|
149
|
Chris@205
|
150 if (candidateModelNames.size() > 1 && !generator) {
|
Chris@205
|
151 dialog->setCandidateInputModels(candidateModelNames,
|
Chris@205
|
152 defaultModelName);
|
Chris@205
|
153 }
|
Chris@205
|
154
|
Chris@205
|
155 if (startFrame != 0 || duration != 0) {
|
Chris@205
|
156 dialog->setShowSelectionOnlyOption(true);
|
Chris@205
|
157 }
|
Chris@205
|
158
|
Chris@205
|
159 if (targetChannels > 0) {
|
Chris@205
|
160 dialog->setChannelArrangement(sourceChannels, targetChannels,
|
Chris@205
|
161 defaultChannel);
|
Chris@205
|
162 }
|
Chris@205
|
163
|
Chris@205
|
164 dialog->setOutputLabel(outputLabel, outputDescription);
|
Chris@205
|
165
|
Chris@205
|
166 dialog->setShowProcessingOptions(true, frequency);
|
Chris@205
|
167
|
Chris@205
|
168 if (dialog->exec() == QDialog::Accepted) {
|
Chris@205
|
169 ok = true;
|
Chris@205
|
170 }
|
Chris@205
|
171
|
Chris@205
|
172 QString selectedInput = dialog->getInputModel();
|
Chris@205
|
173 if (selectedInput != "") {
|
Chris@205
|
174 if (modelMap.contains(selectedInput)) {
|
Chris@205
|
175 inputModel = modelMap.value(selectedInput);
|
Chris@293
|
176 cerr << "Found selected input \"" << selectedInput << "\" in model map, result is " << inputModel << endl;
|
Chris@205
|
177 } else {
|
Chris@293
|
178 cerr << "Failed to find selected input \"" << selectedInput << "\" in model map" << endl;
|
Chris@205
|
179 }
|
Chris@205
|
180 } else {
|
Chris@293
|
181 cerr << "Selected input empty: \"" << selectedInput << "\"" << endl;
|
Chris@205
|
182 }
|
Chris@205
|
183
|
Chris@205
|
184 // Write parameters back to transform object
|
Chris@205
|
185 TransformFactory::getInstance()->
|
Chris@205
|
186 setParametersFromPlugin(transform, plugin);
|
Chris@205
|
187
|
Chris@205
|
188 input.setChannel(dialog->getChannel());
|
Chris@205
|
189
|
Chris@205
|
190 //!!! The dialog ought to be taking & returning transform
|
Chris@205
|
191 //objects and input objects and stuff rather than passing
|
Chris@205
|
192 //around all this misc stuff, but that's for tomorrow
|
Chris@205
|
193 //(whenever that may be)
|
Chris@205
|
194
|
Chris@205
|
195 if (startFrame != 0 || duration != 0) {
|
Chris@205
|
196 if (dialog->getSelectionOnly()) {
|
Chris@205
|
197 transform.setStartTime(RealTime::frame2RealTime
|
Chris@205
|
198 (startFrame, inputModel->getSampleRate()));
|
Chris@205
|
199 transform.setDuration(RealTime::frame2RealTime
|
Chris@205
|
200 (duration, inputModel->getSampleRate()));
|
Chris@205
|
201 }
|
Chris@205
|
202 }
|
Chris@205
|
203
|
Chris@205
|
204 size_t stepSize = 0, blockSize = 0;
|
Chris@205
|
205 WindowType windowType = HanningWindow;
|
Chris@205
|
206
|
Chris@205
|
207 dialog->getProcessingParameters(stepSize,
|
Chris@205
|
208 blockSize,
|
Chris@205
|
209 windowType);
|
Chris@205
|
210
|
Chris@205
|
211 transform.setStepSize(stepSize);
|
Chris@205
|
212 transform.setBlockSize(blockSize);
|
Chris@205
|
213 transform.setWindowType(windowType);
|
Chris@205
|
214
|
Chris@205
|
215 delete dialog;
|
Chris@205
|
216
|
Chris@205
|
217 if (effect && source) {
|
Chris@205
|
218 source->setAuditioningEffect(0);
|
Chris@205
|
219 }
|
Chris@205
|
220
|
Chris@205
|
221 return ok;
|
Chris@205
|
222 }
|
Chris@205
|
223
|