00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "ModelTransformerFactory.h"
00017
00018 #include "FeatureExtractionModelTransformer.h"
00019 #include "RealTimeEffectModelTransformer.h"
00020
00021 #include "TransformFactory.h"
00022
00023 #include "plugin/FeatureExtractionPluginFactory.h"
00024 #include "plugin/RealTimePluginFactory.h"
00025 #include "plugin/PluginXml.h"
00026
00027 #include "widgets/PluginParameterDialog.h"
00028
00029 #include "data/model/DenseTimeValueModel.h"
00030
00031 #include "vamp-sdk/PluginHostAdapter.h"
00032
00033 #include "audioio/AudioCallbackPlaySource.h"
00034
00035 #include <iostream>
00036 #include <set>
00037
00038 #include <QRegExp>
00039
00040 ModelTransformerFactory *
00041 ModelTransformerFactory::m_instance = new ModelTransformerFactory;
00042
00043 ModelTransformerFactory *
00044 ModelTransformerFactory::getInstance()
00045 {
00046 return m_instance;
00047 }
00048
00049 ModelTransformerFactory::~ModelTransformerFactory()
00050 {
00051 }
00052
00053 bool
00054 ModelTransformerFactory::getChannelRange(TransformId identifier,
00055 Vamp::PluginBase *plugin,
00056 int &minChannels, int &maxChannels)
00057 {
00058 Vamp::Plugin *vp = 0;
00059 if ((vp = dynamic_cast<Vamp::Plugin *>(plugin)) ||
00060 (vp = dynamic_cast<Vamp::PluginHostAdapter *>(plugin))) {
00061 minChannels = vp->getMinChannelCount();
00062 maxChannels = vp->getMaxChannelCount();
00063 return true;
00064 } else {
00065 return TransformFactory::getInstance()->
00066 getTransformChannelRange(identifier, minChannels, maxChannels);
00067 }
00068 }
00069
00070 ModelTransformer::Input
00071 ModelTransformerFactory::getConfigurationForTransform(Transform &transform,
00072 const std::vector<Model *> &candidateInputModels,
00073 Model *defaultInputModel,
00074 AudioCallbackPlaySource *source,
00075 size_t startFrame,
00076 size_t duration)
00077 {
00078 ModelTransformer::Input input(0);
00079
00080 if (candidateInputModels.empty()) return input;
00081
00083
00084
00085 Model *inputModel = candidateInputModels[0];
00086 QStringList candidateModelNames;
00087 QString defaultModelName;
00088 std::map<QString, Model *> modelMap;
00089 for (size_t i = 0; i < candidateInputModels.size(); ++i) {
00090 QString modelName = candidateInputModels[i]->objectName();
00091 QString origModelName = modelName;
00092 int dupcount = 1;
00093 while (modelMap.find(modelName) != modelMap.end()) {
00094 modelName = tr("%1 <%2>").arg(origModelName).arg(++dupcount);
00095 }
00096 modelMap[modelName] = candidateInputModels[i];
00097 candidateModelNames.push_back(modelName);
00098 if (candidateInputModels[i] == defaultInputModel) {
00099 defaultModelName = modelName;
00100 }
00101 }
00102
00103 QString id = transform.getPluginIdentifier();
00104 QString output = transform.getOutput();
00105 QString outputLabel = "";
00106 QString outputDescription = "";
00107
00108 bool ok = false;
00109 QString configurationXml = m_lastConfigurations[transform.getIdentifier()];
00110
00111 std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl;
00112
00113 Vamp::PluginBase *plugin = 0;
00114
00115 bool frequency = false;
00116 bool effect = false;
00117 bool generator = false;
00118
00119 if (FeatureExtractionPluginFactory::instanceFor(id)) {
00120
00121 std::cerr << "getConfigurationForTransform: instantiating Vamp plugin" << std::endl;
00122
00123 Vamp::Plugin *vp =
00124 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin
00125 (id, inputModel->getSampleRate());
00126
00127 if (vp) {
00128
00129 plugin = vp;
00130 frequency = (vp->getInputDomain() == Vamp::Plugin::FrequencyDomain);
00131
00132 std::vector<Vamp::Plugin::OutputDescriptor> od =
00133 vp->getOutputDescriptors();
00134 if (od.size() > 1) {
00135 for (size_t i = 0; i < od.size(); ++i) {
00136 if (od[i].identifier == output.toStdString()) {
00137 outputLabel = od[i].name.c_str();
00138 outputDescription = od[i].description.c_str();
00139 break;
00140 }
00141 }
00142 }
00143 }
00144
00145 } else if (RealTimePluginFactory::instanceFor(id)) {
00146
00147 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id);
00148 const RealTimePluginDescriptor *desc = factory->getPluginDescriptor(id);
00149
00150 if (desc->audioInputPortCount > 0 &&
00151 desc->audioOutputPortCount > 0 &&
00152 !desc->isSynth) {
00153 effect = true;
00154 }
00155
00156 if (desc->audioInputPortCount == 0) {
00157 generator = true;
00158 }
00159
00160 if (output != "A") {
00161 int outputNo = output.toInt();
00162 if (outputNo >= 0 && outputNo < int(desc->controlOutputPortCount)) {
00163 outputLabel = desc->controlOutputPortNames[outputNo].c_str();
00164 }
00165 }
00166
00167 size_t sampleRate = inputModel->getSampleRate();
00168 size_t blockSize = 1024;
00169 size_t channels = 1;
00170 if (effect && source) {
00171 sampleRate = source->getTargetSampleRate();
00172 blockSize = source->getTargetBlockSize();
00173 channels = source->getTargetChannelCount();
00174 }
00175
00176 RealTimePluginInstance *rtp = factory->instantiatePlugin
00177 (id, 0, 0, sampleRate, blockSize, channels);
00178
00179 plugin = rtp;
00180
00181 if (effect && source && rtp) {
00182 source->setAuditioningPlugin(rtp);
00183 }
00184 }
00185
00186 if (plugin) {
00187
00188
00189 TransformFactory::getInstance()->
00190 makeContextConsistentWithPlugin(transform, plugin);
00191
00192
00193
00194 TransformFactory::getInstance()->
00195 setPluginParameters(transform, plugin);
00196
00197
00198
00199 PluginXml(plugin).setParametersFromXml(configurationXml);
00200
00201 int sourceChannels = 1;
00202 if (dynamic_cast<DenseTimeValueModel *>(inputModel)) {
00203 sourceChannels = dynamic_cast<DenseTimeValueModel *>(inputModel)
00204 ->getChannelCount();
00205 }
00206
00207 int minChannels = 1, maxChannels = sourceChannels;
00208 getChannelRange(transform.getIdentifier(), plugin,
00209 minChannels, maxChannels);
00210
00211 int targetChannels = sourceChannels;
00212 if (!effect) {
00213 if (sourceChannels < minChannels) targetChannels = minChannels;
00214 if (sourceChannels > maxChannels) targetChannels = maxChannels;
00215 }
00216
00217 int defaultChannel = -1;
00218
00219 PluginParameterDialog *dialog = new PluginParameterDialog(plugin);
00220
00221 if (candidateModelNames.size() > 1 && !generator) {
00222 dialog->setCandidateInputModels(candidateModelNames,
00223 defaultModelName);
00224 }
00225
00226 if (startFrame != 0 || duration != 0) {
00227 dialog->setShowSelectionOnlyOption(true);
00228 }
00229
00230 if (targetChannels > 0) {
00231 dialog->setChannelArrangement(sourceChannels, targetChannels,
00232 defaultChannel);
00233 }
00234
00235 dialog->setOutputLabel(outputLabel, outputDescription);
00236
00237 dialog->setShowProcessingOptions(true, frequency);
00238
00239 if (dialog->exec() == QDialog::Accepted) {
00240 ok = true;
00241 }
00242
00243 QString selectedInput = dialog->getInputModel();
00244 if (selectedInput != "") {
00245 if (modelMap.find(selectedInput) != modelMap.end()) {
00246 inputModel = modelMap[selectedInput];
00247 std::cerr << "Found selected input \"" << selectedInput.toStdString() << "\" in model map, result is " << inputModel << std::endl;
00248 } else {
00249 std::cerr << "Failed to find selected input \"" << selectedInput.toStdString() << "\" in model map" << std::endl;
00250 }
00251 } else {
00252 std::cerr << "Selected input empty: \"" << selectedInput.toStdString() << "\"" << std::endl;
00253 }
00254
00255
00256 TransformFactory::getInstance()->
00257 setParametersFromPlugin(transform, plugin);
00258
00259 input.setChannel(dialog->getChannel());
00260
00262
00263
00264
00265
00266 if (startFrame != 0 || duration != 0) {
00267 if (dialog->getSelectionOnly()) {
00268 transform.setStartTime(RealTime::frame2RealTime
00269 (startFrame, inputModel->getSampleRate()));
00270 transform.setDuration(RealTime::frame2RealTime
00271 (duration, inputModel->getSampleRate()));
00272 }
00273 }
00274
00275 size_t stepSize = 0, blockSize = 0;
00276 WindowType windowType = HanningWindow;
00277
00278 dialog->getProcessingParameters(stepSize,
00279 blockSize,
00280 windowType);
00281
00282 transform.setStepSize(stepSize);
00283 transform.setBlockSize(blockSize);
00284 transform.setWindowType(windowType);
00285
00286 TransformFactory::getInstance()->
00287 makeContextConsistentWithPlugin(transform, plugin);
00288
00289 configurationXml = PluginXml(plugin).toXmlString();
00290
00291 delete dialog;
00292
00293 if (effect && source) {
00294 source->setAuditioningPlugin(0);
00295 } else {
00296 delete plugin;
00297 }
00298 }
00299
00300 if (ok) {
00301 m_lastConfigurations[transform.getIdentifier()] = configurationXml;
00302 input.setModel(inputModel);
00303 }
00304
00305 return input;
00306 }
00331 ModelTransformer *
00332 ModelTransformerFactory::createTransformer(const Transform &transform,
00333 const ModelTransformer::Input &input)
00334 {
00335 ModelTransformer *transformer = 0;
00336
00337 QString id = transform.getPluginIdentifier();
00338
00339 if (FeatureExtractionPluginFactory::instanceFor(id)) {
00340
00341 transformer =
00342 new FeatureExtractionModelTransformer(input, transform);
00343
00344 } else if (RealTimePluginFactory::instanceFor(id)) {
00345
00346 transformer =
00347 new RealTimeEffectModelTransformer(input, transform);
00348
00349 } else {
00350 std::cerr << "ModelTransformerFactory::createTransformer: Unknown transform \""
00351 << transform.getIdentifier().toStdString() << "\"" << std::endl;
00352 return transformer;
00353 }
00354
00355 if (transformer) transformer->setObjectName(transform.getIdentifier());
00356 return transformer;
00357 }
00358
00359 Model *
00360 ModelTransformerFactory::transform(const Transform &transform,
00361 const ModelTransformer::Input &input,
00362 QString &message)
00363 {
00364 ModelTransformer *t = createTransformer(transform, input);
00365 if (!t) return 0;
00366
00367 connect(t, SIGNAL(finished()), this, SLOT(transformerFinished()));
00368
00369 m_runningTransformers.insert(t);
00370
00371 t->start();
00372 Model *model = t->detachOutputModel();
00373
00374 if (model) {
00375 QString imn = input.getModel()->objectName();
00376 QString trn =
00377 TransformFactory::getInstance()->getTransformFriendlyName
00378 (transform.getIdentifier());
00379 if (imn != "") {
00380 if (trn != "") {
00381 model->setObjectName(tr("%1: %2").arg(imn).arg(trn));
00382 } else {
00383 model->setObjectName(imn);
00384 }
00385 } else if (trn != "") {
00386 model->setObjectName(trn);
00387 }
00388 } else {
00389 t->wait();
00390 }
00391
00392 message = t->getMessage();
00393
00394 return model;
00395 }
00396
00397 void
00398 ModelTransformerFactory::transformerFinished()
00399 {
00400 QObject *s = sender();
00401 ModelTransformer *transformer = dynamic_cast<ModelTransformer *>(s);
00402
00403 std::cerr << "ModelTransformerFactory::transformerFinished(" << transformer << ")" << std::endl;
00404
00405 if (!transformer) {
00406 std::cerr << "WARNING: ModelTransformerFactory::transformerFinished: sender is not a transformer" << std::endl;
00407 return;
00408 }
00409
00410 if (m_runningTransformers.find(transformer) == m_runningTransformers.end()) {
00411 std::cerr << "WARNING: ModelTransformerFactory::transformerFinished("
00412 << transformer
00413 << "): I have no record of this transformer running!"
00414 << std::endl;
00415 }
00416
00417 m_runningTransformers.erase(transformer);
00418
00419 transformer->wait();
00420 delete transformer;
00421 }
00422
00423 void
00424 ModelTransformerFactory::modelAboutToBeDeleted(Model *m)
00425 {
00426 TransformerSet affected;
00427
00428 for (TransformerSet::iterator i = m_runningTransformers.begin();
00429 i != m_runningTransformers.end(); ++i) {
00430
00431 ModelTransformer *t = *i;
00432
00433 if (t->getInputModel() == m || t->getOutputModel() == m) {
00434 affected.insert(t);
00435 }
00436 }
00437
00438 for (TransformerSet::iterator i = affected.begin();
00439 i != affected.end(); ++i) {
00440
00441 ModelTransformer *t = *i;
00442
00443 t->abandon();
00444
00445 t->wait();
00446
00447
00448 }
00449 }
00450