annotate transform/RealTimePluginTransform.cpp @ 88:51be0daa1386

Several changes related to referring to remote URLs for sessions and files: * Pull file dialog wrapper functions out from MainWindow into FileFinder * If a file referred to in a session is not found at its expected location, try a few other alternatives (same location as the session file or same location as the last audio file) before asking the user to locate it * Allow user to give a URL when locating an audio file, not just locate on the filesystem * Make wave file models remember the "original" location (e.g. URL) of the audio file, not just the actual location from which the data was loaded (e.g. local copy of that URL) -- when saving a session, use the original location so as not to refer to a temporary file * Clean up incompletely-downloaded local copies of files
author Chris Cannam
date Thu, 11 Jan 2007 13:29:58 +0000
parents bedc7517b6e8
children d25ea0c2af5c
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 Sonic Visualiser
Chris@0 5 An audio file viewer and annotation editor.
Chris@0 6 Centre for Digital Music, Queen Mary, University of London.
Chris@77 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@0 9 This program is free software; you can redistribute it and/or
Chris@0 10 modify it under the terms of the GNU General Public License as
Chris@0 11 published by the Free Software Foundation; either version 2 of the
Chris@0 12 License, or (at your option) any later version. See the file
Chris@0 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "RealTimePluginTransform.h"
Chris@0 17
Chris@0 18 #include "plugin/RealTimePluginFactory.h"
Chris@0 19 #include "plugin/RealTimePluginInstance.h"
Chris@0 20 #include "plugin/PluginXml.h"
Chris@0 21
Chris@1 22 #include "data/model/Model.h"
Chris@1 23 #include "data/model/SparseTimeValueModel.h"
Chris@1 24 #include "data/model/DenseTimeValueModel.h"
Chris@39 25 #include "data/model/WritableWaveFileModel.h"
Chris@55 26 #include "data/model/WaveFileModel.h"
Chris@0 27
Chris@0 28 #include <iostream>
Chris@0 29
Chris@0 30 RealTimePluginTransform::RealTimePluginTransform(Model *inputModel,
Chris@0 31 QString pluginId,
Chris@27 32 const ExecutionContext &context,
Chris@0 33 QString configurationXml,
Chris@0 34 QString units,
Chris@27 35 int output) :
Chris@27 36 PluginTransform(inputModel, context),
Chris@0 37 m_plugin(0),
Chris@27 38 m_outputNo(output)
Chris@0 39 {
Chris@27 40 if (!m_context.blockSize) m_context.blockSize = 1024;
Chris@26 41
Chris@0 42 std::cerr << "RealTimePluginTransform::RealTimePluginTransform: plugin " << pluginId.toStdString() << ", output " << output << std::endl;
Chris@0 43
Chris@0 44 RealTimePluginFactory *factory =
Chris@0 45 RealTimePluginFactory::instanceFor(pluginId);
Chris@0 46
Chris@0 47 if (!factory) {
Chris@0 48 std::cerr << "RealTimePluginTransform: No factory available for plugin id \""
Chris@0 49 << pluginId.toStdString() << "\"" << std::endl;
Chris@0 50 return;
Chris@0 51 }
Chris@0 52
Chris@0 53 DenseTimeValueModel *input = getInput();
Chris@0 54 if (!input) return;
Chris@0 55
Chris@44 56 m_plugin = factory->instantiatePlugin(pluginId, 0, 0,
Chris@44 57 m_input->getSampleRate(),
Chris@27 58 m_context.blockSize,
Chris@0 59 input->getChannelCount());
Chris@0 60
Chris@0 61 if (!m_plugin) {
Chris@0 62 std::cerr << "RealTimePluginTransform: Failed to instantiate plugin \""
Chris@0 63 << pluginId.toStdString() << "\"" << std::endl;
Chris@0 64 return;
Chris@0 65 }
Chris@0 66
Chris@0 67 if (configurationXml != "") {
Chris@0 68 PluginXml(m_plugin).setParametersFromXml(configurationXml);
Chris@0 69 }
Chris@0 70
Chris@34 71 if (m_outputNo >= 0 && m_outputNo >= m_plugin->getControlOutputCount()) {
Chris@0 72 std::cerr << "RealTimePluginTransform: Plugin has fewer than desired " << m_outputNo << " control outputs" << std::endl;
Chris@0 73 return;
Chris@0 74 }
Chris@34 75
Chris@34 76 if (m_outputNo == -1) {
Chris@34 77
Chris@52 78 size_t outputChannels = m_plugin->getAudioOutputCount();
Chris@52 79 if (outputChannels > input->getChannelCount()) {
Chris@52 80 outputChannels = input->getChannelCount();
Chris@52 81 }
Chris@52 82
Chris@39 83 WritableWaveFileModel *model = new WritableWaveFileModel
Chris@52 84 (input->getSampleRate(), outputChannels);
Chris@39 85
Chris@39 86 m_output = model;
Chris@34 87
Chris@34 88 } else {
Chris@0 89
Chris@34 90 SparseTimeValueModel *model = new SparseTimeValueModel
Chris@34 91 (input->getSampleRate(), m_context.blockSize, 0.0, 0.0, false);
Chris@0 92
Chris@34 93 if (units != "") model->setScaleUnits(units);
Chris@0 94
Chris@34 95 m_output = model;
Chris@34 96 }
Chris@0 97 }
Chris@0 98
Chris@0 99 RealTimePluginTransform::~RealTimePluginTransform()
Chris@0 100 {
Chris@0 101 delete m_plugin;
Chris@0 102 }
Chris@0 103
Chris@0 104 DenseTimeValueModel *
Chris@0 105 RealTimePluginTransform::getInput()
Chris@0 106 {
Chris@0 107 DenseTimeValueModel *dtvm =
Chris@0 108 dynamic_cast<DenseTimeValueModel *>(getInputModel());
Chris@0 109 if (!dtvm) {
Chris@0 110 std::cerr << "RealTimePluginTransform::getInput: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl;
Chris@0 111 }
Chris@0 112 return dtvm;
Chris@0 113 }
Chris@0 114
Chris@0 115 void
Chris@0 116 RealTimePluginTransform::run()
Chris@0 117 {
Chris@0 118 DenseTimeValueModel *input = getInput();
Chris@0 119 if (!input) return;
Chris@0 120
Chris@55 121 while (!input->isReady()) {
Chris@55 122 if (dynamic_cast<WaveFileModel *>(input)) break; // no need to wait
Chris@55 123 std::cerr << "FeatureExtractionPluginTransform::run: Waiting for input model to be ready..." << std::endl;
Chris@55 124 sleep(1);
Chris@55 125 }
Chris@55 126
Chris@39 127 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>(m_output);
Chris@39 128 WritableWaveFileModel *wwfm = dynamic_cast<WritableWaveFileModel *>(m_output);
Chris@39 129 if (!stvm && !wwfm) return;
Chris@0 130
Chris@39 131 if (stvm && (m_outputNo >= m_plugin->getControlOutputCount())) return;
Chris@0 132
Chris@0 133 size_t sampleRate = input->getSampleRate();
Chris@0 134 int channelCount = input->getChannelCount();
Chris@44 135 if (!wwfm && m_context.channel != -1) channelCount = 1;
Chris@0 136
Chris@0 137 size_t blockSize = m_plugin->getBufferSize();
Chris@0 138
Chris@0 139 float **buffers = m_plugin->getAudioInputBuffers();
Chris@0 140
Chris@0 141 size_t startFrame = m_input->getStartFrame();
Chris@0 142 size_t endFrame = m_input->getEndFrame();
Chris@0 143 size_t blockFrame = startFrame;
Chris@0 144
Chris@0 145 size_t prevCompletion = 0;
Chris@0 146
Chris@39 147 size_t latency = m_plugin->getLatency();
Chris@39 148
Chris@0 149 int i = 0;
Chris@0 150
Chris@0 151 while (blockFrame < endFrame) {
Chris@0 152
Chris@0 153 size_t completion =
Chris@0 154 (((blockFrame - startFrame) / blockSize) * 99) /
Chris@0 155 ( (endFrame - startFrame) / blockSize);
Chris@0 156
Chris@0 157 size_t got = 0;
Chris@0 158
Chris@0 159 if (channelCount == 1) {
Chris@40 160 if (buffers && buffers[0]) {
Chris@40 161 got = input->getValues
Chris@40 162 (m_context.channel, blockFrame, blockFrame + blockSize, buffers[0]);
Chris@40 163 while (got < blockSize) {
Chris@40 164 buffers[0][got++] = 0.0;
Chris@0 165 }
Chris@40 166 if (m_context.channel == -1 && channelCount > 1) {
Chris@40 167 // use mean instead of sum, as plugin input
Chris@40 168 for (size_t i = 0; i < got; ++i) {
Chris@40 169 buffers[0][i] /= channelCount;
Chris@40 170 }
Chris@40 171 }
Chris@40 172 }
Chris@0 173 } else {
Chris@0 174 for (size_t ch = 0; ch < channelCount; ++ch) {
Chris@40 175 if (buffers && buffers[ch]) {
Chris@40 176 got = input->getValues
Chris@40 177 (ch, blockFrame, blockFrame + blockSize, buffers[ch]);
Chris@40 178 while (got < blockSize) {
Chris@40 179 buffers[ch][got++] = 0.0;
Chris@40 180 }
Chris@40 181 }
Chris@0 182 }
Chris@0 183 }
Chris@0 184
Chris@0 185 m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
Chris@0 186
Chris@39 187 if (stvm) {
Chris@0 188
Chris@39 189 float value = m_plugin->getControlOutputValue(m_outputNo);
Chris@39 190
Chris@39 191 size_t pointFrame = blockFrame;
Chris@39 192 if (pointFrame > latency) pointFrame -= latency;
Chris@39 193 else pointFrame = 0;
Chris@39 194
Chris@39 195 stvm->addPoint(SparseTimeValueModel::Point
Chris@39 196 (pointFrame, value, ""));
Chris@39 197
Chris@39 198 } else if (wwfm) {
Chris@39 199
Chris@39 200 float **buffers = m_plugin->getAudioOutputBuffers();
Chris@39 201
Chris@40 202 if (buffers) {
Chris@40 203
Chris@40 204 if (blockFrame >= latency) {
Chris@40 205 wwfm->addSamples(buffers, blockSize);
Chris@40 206 } else if (blockFrame + blockSize >= latency) {
Chris@40 207 size_t offset = latency - blockFrame;
Chris@40 208 size_t count = blockSize - offset;
Chris@40 209 float **tmp = new float *[channelCount];
Chris@40 210 for (size_t c = 0; c < channelCount; ++c) {
Chris@40 211 tmp[c] = buffers[c] + offset;
Chris@40 212 }
Chris@40 213 wwfm->addSamples(tmp, count);
Chris@40 214 delete[] tmp;
Chris@39 215 }
Chris@39 216 }
Chris@39 217 }
Chris@0 218
Chris@0 219 if (blockFrame == startFrame || completion > prevCompletion) {
Chris@39 220 if (stvm) stvm->setCompletion(completion);
Chris@55 221 if (wwfm) wwfm->setCompletion(completion);
Chris@0 222 prevCompletion = completion;
Chris@0 223 }
Chris@0 224
Chris@0 225 blockFrame += blockSize;
Chris@0 226 }
Chris@0 227
Chris@39 228 if (stvm) stvm->setCompletion(100);
Chris@55 229 if (wwfm) wwfm->setCompletion(100);
Chris@0 230 }
Chris@0 231