annotate sv/transform/RealTimePluginTransform.cpp @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents fc9323a41f5a
children
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7 This file copyright 2006 Chris Cannam and QMUL.
lbajardsilogic@0 8
lbajardsilogic@0 9 This program is free software; you can redistribute it and/or
lbajardsilogic@0 10 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 11 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 12 License, or (at your option) any later version. See the file
lbajardsilogic@0 13 COPYING included with this distribution for more information.
lbajardsilogic@0 14 */
lbajardsilogic@0 15
lbajardsilogic@0 16 #include "RealTimePluginTransform.h"
lbajardsilogic@0 17
lbajardsilogic@0 18 #include "plugin/RealTimePluginFactory.h"
lbajardsilogic@0 19 #include "plugin/RealTimePluginInstance.h"
lbajardsilogic@0 20 #include "plugin/PluginXml.h"
lbajardsilogic@0 21
lbajardsilogic@0 22 #include "data/model/Model.h"
lbajardsilogic@0 23 #include "data/model/SparseTimeValueModel.h"
lbajardsilogic@0 24 #include "data/model/DenseTimeValueModel.h"
lbajardsilogic@0 25 #include "data/model/WritableWaveFileModel.h"
lbajardsilogic@0 26 #include "data/model/WaveFileModel.h"
lbajardsilogic@0 27
lbajardsilogic@0 28 #include <iostream>
lbajardsilogic@0 29
lbajardsilogic@0 30 RealTimePluginTransform::RealTimePluginTransform(Model *inputModel,
lbajardsilogic@0 31 QString pluginId,
lbajardsilogic@0 32 const ExecutionContext &context,
lbajardsilogic@0 33 QString configurationXml,
lbajardsilogic@0 34 QString units,
lbajardsilogic@0 35 int output) :
lbajardsilogic@0 36 PluginTransform(inputModel, context),
lbajardsilogic@0 37 m_pluginId(pluginId),
lbajardsilogic@0 38 m_configurationXml(configurationXml),
lbajardsilogic@0 39 m_units(units),
lbajardsilogic@0 40 m_plugin(0),
lbajardsilogic@0 41 m_outputNo(output)
lbajardsilogic@0 42 {
lbajardsilogic@0 43 if (!m_context.blockSize) m_context.blockSize = 1024;
lbajardsilogic@0 44
lbajardsilogic@0 45 // std::cerr << "RealTimePluginTransform::RealTimePluginTransform: plugin " << pluginId.toStdString() << ", output " << output << std::endl;
lbajardsilogic@0 46
lbajardsilogic@0 47 RealTimePluginFactory *factory =
lbajardsilogic@0 48 RealTimePluginFactory::instanceFor(pluginId);
lbajardsilogic@0 49
lbajardsilogic@0 50 if (!factory) {
lbajardsilogic@0 51 std::cerr << "RealTimePluginTransform: No factory available for plugin id \""
lbajardsilogic@0 52 << pluginId.toStdString() << "\"" << std::endl;
lbajardsilogic@0 53 return;
lbajardsilogic@0 54 }
lbajardsilogic@0 55
lbajardsilogic@0 56 DenseTimeValueModel *input = getInput();
lbajardsilogic@0 57 if (!input) return;
lbajardsilogic@0 58
lbajardsilogic@0 59 m_plugin = factory->instantiatePlugin(pluginId, 0, 0,
lbajardsilogic@0 60 m_input->getSampleRate(),
lbajardsilogic@0 61 m_context.blockSize,
lbajardsilogic@0 62 input->getChannelCount());
lbajardsilogic@0 63
lbajardsilogic@0 64 if (!m_plugin) {
lbajardsilogic@0 65 std::cerr << "RealTimePluginTransform: Failed to instantiate plugin \""
lbajardsilogic@0 66 << pluginId.toStdString() << "\"" << std::endl;
lbajardsilogic@0 67 return;
lbajardsilogic@0 68 }
lbajardsilogic@0 69
lbajardsilogic@0 70 if (configurationXml != "") {
lbajardsilogic@0 71 PluginXml(m_plugin).setParametersFromXml(configurationXml);
lbajardsilogic@0 72 }
lbajardsilogic@0 73
lbajardsilogic@0 74 if (m_outputNo >= 0 &&
lbajardsilogic@0 75 m_outputNo >= int(m_plugin->getControlOutputCount())) {
lbajardsilogic@0 76 std::cerr << "RealTimePluginTransform: Plugin has fewer than desired " << m_outputNo << " control outputs" << std::endl;
lbajardsilogic@0 77 return;
lbajardsilogic@0 78 }
lbajardsilogic@0 79
lbajardsilogic@0 80 if (m_outputNo == -1) {
lbajardsilogic@0 81
lbajardsilogic@0 82 size_t outputChannels = m_plugin->getAudioOutputCount();
lbajardsilogic@0 83 if (outputChannels > input->getChannelCount()) {
lbajardsilogic@0 84 outputChannels = input->getChannelCount();
lbajardsilogic@0 85 }
lbajardsilogic@0 86
lbajardsilogic@0 87 WritableWaveFileModel *model = new WritableWaveFileModel
lbajardsilogic@0 88 (input->getSampleRate(), outputChannels);
lbajardsilogic@0 89
lbajardsilogic@0 90 m_output = model;
lbajardsilogic@0 91
lbajardsilogic@0 92 } else {
lbajardsilogic@0 93
lbajardsilogic@0 94 SparseTimeValueModel *model = new SparseTimeValueModel
lbajardsilogic@0 95 (input->getSampleRate(), m_context.blockSize, 0.0, 0.0, false);
lbajardsilogic@0 96
lbajardsilogic@0 97 if (units != "") model->setScaleUnits(units);
lbajardsilogic@0 98
lbajardsilogic@0 99 m_output = model;
lbajardsilogic@0 100 }
lbajardsilogic@0 101 }
lbajardsilogic@0 102
lbajardsilogic@0 103 RealTimePluginTransform::~RealTimePluginTransform()
lbajardsilogic@0 104 {
lbajardsilogic@0 105 delete m_plugin;
lbajardsilogic@0 106 }
lbajardsilogic@0 107
lbajardsilogic@0 108 DenseTimeValueModel *
lbajardsilogic@0 109 RealTimePluginTransform::getInput()
lbajardsilogic@0 110 {
lbajardsilogic@0 111 DenseTimeValueModel *dtvm =
lbajardsilogic@0 112 dynamic_cast<DenseTimeValueModel *>(getInputModel());
lbajardsilogic@0 113 if (!dtvm) {
lbajardsilogic@0 114 std::cerr << "RealTimePluginTransform::getInput: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl;
lbajardsilogic@0 115 }
lbajardsilogic@0 116 return dtvm;
lbajardsilogic@0 117 }
lbajardsilogic@0 118
lbajardsilogic@0 119 void
lbajardsilogic@0 120 RealTimePluginTransform::run()
lbajardsilogic@0 121 {
lbajardsilogic@0 122 DenseTimeValueModel *input = getInput();
lbajardsilogic@0 123 if (!input) return;
lbajardsilogic@0 124
lbajardsilogic@0 125 while (!input->isReady()) {
lbajardsilogic@0 126 if (dynamic_cast<WaveFileModel *>(input)) break; // no need to wait
lbajardsilogic@0 127 std::cerr << "RealTimePluginTransform::run: Waiting for input model to be ready..." << std::endl;
lbajardsilogic@0 128 sleep(1);
lbajardsilogic@0 129 }
lbajardsilogic@0 130
lbajardsilogic@0 131 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>(m_output);
lbajardsilogic@0 132 WritableWaveFileModel *wwfm = dynamic_cast<WritableWaveFileModel *>(m_output);
lbajardsilogic@0 133 if (!stvm && !wwfm) return;
lbajardsilogic@0 134
lbajardsilogic@0 135 if (stvm && (m_outputNo >= int(m_plugin->getControlOutputCount()))) return;
lbajardsilogic@0 136
lbajardsilogic@0 137 size_t sampleRate = input->getSampleRate();
lbajardsilogic@0 138 size_t channelCount = input->getChannelCount();
lbajardsilogic@0 139 if (!wwfm && m_context.channel != -1) channelCount = 1;
lbajardsilogic@0 140
lbajardsilogic@0 141 size_t blockSize = m_plugin->getBufferSize();
lbajardsilogic@0 142
lbajardsilogic@0 143 float **inbufs = m_plugin->getAudioInputBuffers();
lbajardsilogic@0 144
lbajardsilogic@0 145 size_t startFrame = m_input->getStartFrame();
lbajardsilogic@0 146 size_t endFrame = m_input->getEndFrame();
lbajardsilogic@0 147 size_t blockFrame = startFrame;
lbajardsilogic@0 148
lbajardsilogic@0 149 size_t prevCompletion = 0;
lbajardsilogic@0 150
lbajardsilogic@0 151 size_t latency = m_plugin->getLatency();
lbajardsilogic@0 152
lbajardsilogic@0 153 while (blockFrame < endFrame && !m_abandoned) {
lbajardsilogic@0 154
lbajardsilogic@0 155 size_t completion =
lbajardsilogic@0 156 (((blockFrame - startFrame) / blockSize) * 99) /
lbajardsilogic@0 157 ( (endFrame - startFrame) / blockSize);
lbajardsilogic@0 158
lbajardsilogic@0 159 size_t got = 0;
lbajardsilogic@0 160
lbajardsilogic@0 161 if (channelCount == 1) {
lbajardsilogic@0 162 if (inbufs && inbufs[0]) {
lbajardsilogic@0 163 got = input->getValues
lbajardsilogic@0 164 (m_context.channel, blockFrame, blockFrame + blockSize, inbufs[0]);
lbajardsilogic@0 165 while (got < blockSize) {
lbajardsilogic@0 166 inbufs[0][got++] = 0.0;
lbajardsilogic@0 167 }
lbajardsilogic@0 168 }
lbajardsilogic@0 169 for (size_t ch = 1; ch < m_plugin->getAudioInputCount(); ++ch) {
lbajardsilogic@0 170 for (size_t i = 0; i < blockSize; ++i) {
lbajardsilogic@0 171 inbufs[ch][i] = inbufs[0][i];
lbajardsilogic@0 172 }
lbajardsilogic@0 173 }
lbajardsilogic@0 174 } else {
lbajardsilogic@0 175 for (size_t ch = 0; ch < channelCount; ++ch) {
lbajardsilogic@0 176 if (inbufs && inbufs[ch]) {
lbajardsilogic@0 177 got = input->getValues
lbajardsilogic@0 178 (ch, blockFrame, blockFrame + blockSize, inbufs[ch]);
lbajardsilogic@0 179 while (got < blockSize) {
lbajardsilogic@0 180 inbufs[ch][got++] = 0.0;
lbajardsilogic@0 181 }
lbajardsilogic@0 182 }
lbajardsilogic@0 183 }
lbajardsilogic@0 184 for (size_t ch = channelCount; ch < m_plugin->getAudioInputCount(); ++ch) {
lbajardsilogic@0 185 for (size_t i = 0; i < blockSize; ++i) {
lbajardsilogic@0 186 inbufs[ch][i] = inbufs[ch % channelCount][i];
lbajardsilogic@0 187 }
lbajardsilogic@0 188 }
lbajardsilogic@0 189 }
lbajardsilogic@0 190
lbajardsilogic@0 191 /*
lbajardsilogic@0 192 std::cerr << "Input for plugin: " << m_plugin->getAudioInputCount() << " channels "<< std::endl;
lbajardsilogic@0 193
lbajardsilogic@0 194 for (size_t ch = 0; ch < m_plugin->getAudioInputCount(); ++ch) {
lbajardsilogic@0 195 std::cerr << "Input channel " << ch << std::endl;
lbajardsilogic@0 196 for (size_t i = 0; i < 100; ++i) {
lbajardsilogic@0 197 std::cerr << inbufs[ch][i] << " ";
lbajardsilogic@0 198 if (isnan(inbufs[ch][i])) {
lbajardsilogic@0 199 std::cerr << "\n\nWARNING: NaN in audio input" << std::endl;
lbajardsilogic@0 200 }
lbajardsilogic@0 201 }
lbajardsilogic@0 202 }
lbajardsilogic@0 203 */
lbajardsilogic@0 204
lbajardsilogic@0 205 m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
lbajardsilogic@0 206
lbajardsilogic@0 207 if (stvm) {
lbajardsilogic@0 208
lbajardsilogic@0 209 float value = m_plugin->getControlOutputValue(m_outputNo);
lbajardsilogic@0 210
lbajardsilogic@0 211 size_t pointFrame = blockFrame;
lbajardsilogic@0 212 if (pointFrame > latency) pointFrame -= latency;
lbajardsilogic@0 213 else pointFrame = 0;
lbajardsilogic@0 214
lbajardsilogic@0 215 stvm->addPoint(SparseTimeValueModel::Point
lbajardsilogic@0 216 (pointFrame, value, ""));
lbajardsilogic@0 217
lbajardsilogic@0 218 } else if (wwfm) {
lbajardsilogic@0 219
lbajardsilogic@0 220 float **outbufs = m_plugin->getAudioOutputBuffers();
lbajardsilogic@0 221
lbajardsilogic@0 222 if (outbufs) {
lbajardsilogic@0 223
lbajardsilogic@0 224 if (blockFrame >= latency) {
lbajardsilogic@0 225 wwfm->addSamples(outbufs, blockSize);
lbajardsilogic@0 226 } else if (blockFrame + blockSize >= latency) {
lbajardsilogic@0 227 size_t offset = latency - blockFrame;
lbajardsilogic@0 228 size_t count = blockSize - offset;
lbajardsilogic@0 229 float **tmp = new float *[channelCount];
lbajardsilogic@0 230 for (size_t c = 0; c < channelCount; ++c) {
lbajardsilogic@0 231 tmp[c] = outbufs[c] + offset;
lbajardsilogic@0 232 }
lbajardsilogic@0 233 wwfm->addSamples(tmp, count);
lbajardsilogic@0 234 delete[] tmp;
lbajardsilogic@0 235 }
lbajardsilogic@0 236 }
lbajardsilogic@0 237 }
lbajardsilogic@0 238
lbajardsilogic@0 239 if (blockFrame == startFrame || completion > prevCompletion) {
lbajardsilogic@0 240 if (stvm) stvm->setCompletion(completion);
lbajardsilogic@0 241 if (wwfm) wwfm->setCompletion(completion);
lbajardsilogic@0 242 prevCompletion = completion;
lbajardsilogic@0 243 }
lbajardsilogic@0 244
lbajardsilogic@0 245 blockFrame += blockSize;
lbajardsilogic@0 246 }
lbajardsilogic@0 247
lbajardsilogic@0 248 if (m_abandoned) return;
lbajardsilogic@0 249
lbajardsilogic@0 250 if (stvm) stvm->setCompletion(100);
lbajardsilogic@0 251 if (wwfm) wwfm->setCompletion(100);
lbajardsilogic@0 252 }
lbajardsilogic@0 253