annotate transform/RealTimePluginTransform.cpp @ 45:6b6bca31ad53

* When setting a new model on a layer, don't delete the old one until after the new one has been set (a layer's setModel may want to compare against the old one, as WaveformLayer does)
author Chris Cannam
date Thu, 05 Oct 2006 11:00:59 +0000
parents 5a72bf7490ae
children 527598e2fa10
rev   line source
Chris@0 1
Chris@0 2 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 3
Chris@0 4 /*
Chris@0 5 Sonic Visualiser
Chris@0 6 An audio file viewer and annotation editor.
Chris@0 7 Centre for Digital Music, Queen Mary, University of London.
Chris@0 8 This file copyright 2006 Chris Cannam.
Chris@0 9
Chris@0 10 This program is free software; you can redistribute it and/or
Chris@0 11 modify it under the terms of the GNU General Public License as
Chris@0 12 published by the Free Software Foundation; either version 2 of the
Chris@0 13 License, or (at your option) any later version. See the file
Chris@0 14 COPYING included with this distribution for more information.
Chris@0 15 */
Chris@0 16
Chris@0 17 #include "RealTimePluginTransform.h"
Chris@0 18
Chris@0 19 #include "plugin/RealTimePluginFactory.h"
Chris@0 20 #include "plugin/RealTimePluginInstance.h"
Chris@0 21 #include "plugin/PluginXml.h"
Chris@0 22
Chris@1 23 #include "data/model/Model.h"
Chris@1 24 #include "data/model/SparseTimeValueModel.h"
Chris@1 25 #include "data/model/DenseTimeValueModel.h"
Chris@39 26 #include "data/model/WritableWaveFileModel.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@39 78 WritableWaveFileModel *model = new WritableWaveFileModel
Chris@39 79 (input->getSampleRate(), input->getChannelCount()); //!!!
Chris@39 80
Chris@39 81 m_output = model;
Chris@34 82
Chris@34 83 } else {
Chris@0 84
Chris@34 85 SparseTimeValueModel *model = new SparseTimeValueModel
Chris@34 86 (input->getSampleRate(), m_context.blockSize, 0.0, 0.0, false);
Chris@0 87
Chris@34 88 if (units != "") model->setScaleUnits(units);
Chris@0 89
Chris@34 90 m_output = model;
Chris@34 91 }
Chris@0 92 }
Chris@0 93
Chris@0 94 RealTimePluginTransform::~RealTimePluginTransform()
Chris@0 95 {
Chris@0 96 delete m_plugin;
Chris@0 97 }
Chris@0 98
Chris@0 99 DenseTimeValueModel *
Chris@0 100 RealTimePluginTransform::getInput()
Chris@0 101 {
Chris@0 102 DenseTimeValueModel *dtvm =
Chris@0 103 dynamic_cast<DenseTimeValueModel *>(getInputModel());
Chris@0 104 if (!dtvm) {
Chris@0 105 std::cerr << "RealTimePluginTransform::getInput: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl;
Chris@0 106 }
Chris@0 107 return dtvm;
Chris@0 108 }
Chris@0 109
Chris@0 110 void
Chris@0 111 RealTimePluginTransform::run()
Chris@0 112 {
Chris@0 113 DenseTimeValueModel *input = getInput();
Chris@0 114 if (!input) return;
Chris@0 115
Chris@39 116 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>(m_output);
Chris@39 117 WritableWaveFileModel *wwfm = dynamic_cast<WritableWaveFileModel *>(m_output);
Chris@39 118 if (!stvm && !wwfm) return;
Chris@0 119
Chris@39 120 if (stvm && (m_outputNo >= m_plugin->getControlOutputCount())) return;
Chris@0 121
Chris@0 122 size_t sampleRate = input->getSampleRate();
Chris@0 123 int channelCount = input->getChannelCount();
Chris@44 124 if (!wwfm && m_context.channel != -1) channelCount = 1;
Chris@0 125
Chris@0 126 size_t blockSize = m_plugin->getBufferSize();
Chris@0 127
Chris@0 128 float **buffers = m_plugin->getAudioInputBuffers();
Chris@0 129
Chris@0 130 size_t startFrame = m_input->getStartFrame();
Chris@0 131 size_t endFrame = m_input->getEndFrame();
Chris@0 132 size_t blockFrame = startFrame;
Chris@0 133
Chris@0 134 size_t prevCompletion = 0;
Chris@0 135
Chris@39 136 size_t latency = m_plugin->getLatency();
Chris@39 137
Chris@0 138 int i = 0;
Chris@0 139
Chris@0 140 while (blockFrame < endFrame) {
Chris@0 141
Chris@0 142 size_t completion =
Chris@0 143 (((blockFrame - startFrame) / blockSize) * 99) /
Chris@0 144 ( (endFrame - startFrame) / blockSize);
Chris@0 145
Chris@0 146 size_t got = 0;
Chris@0 147
Chris@0 148 if (channelCount == 1) {
Chris@40 149 if (buffers && buffers[0]) {
Chris@40 150 got = input->getValues
Chris@40 151 (m_context.channel, blockFrame, blockFrame + blockSize, buffers[0]);
Chris@40 152 while (got < blockSize) {
Chris@40 153 buffers[0][got++] = 0.0;
Chris@0 154 }
Chris@40 155 if (m_context.channel == -1 && channelCount > 1) {
Chris@40 156 // use mean instead of sum, as plugin input
Chris@40 157 for (size_t i = 0; i < got; ++i) {
Chris@40 158 buffers[0][i] /= channelCount;
Chris@40 159 }
Chris@40 160 }
Chris@40 161 }
Chris@0 162 } else {
Chris@0 163 for (size_t ch = 0; ch < channelCount; ++ch) {
Chris@40 164 if (buffers && buffers[ch]) {
Chris@40 165 got = input->getValues
Chris@40 166 (ch, blockFrame, blockFrame + blockSize, buffers[ch]);
Chris@40 167 while (got < blockSize) {
Chris@40 168 buffers[ch][got++] = 0.0;
Chris@40 169 }
Chris@40 170 }
Chris@0 171 }
Chris@0 172 }
Chris@0 173
Chris@0 174 m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
Chris@0 175
Chris@39 176 if (stvm) {
Chris@0 177
Chris@39 178 float value = m_plugin->getControlOutputValue(m_outputNo);
Chris@39 179
Chris@39 180 size_t pointFrame = blockFrame;
Chris@39 181 if (pointFrame > latency) pointFrame -= latency;
Chris@39 182 else pointFrame = 0;
Chris@39 183
Chris@39 184 stvm->addPoint(SparseTimeValueModel::Point
Chris@39 185 (pointFrame, value, ""));
Chris@39 186
Chris@39 187 } else if (wwfm) {
Chris@39 188
Chris@39 189 float **buffers = m_plugin->getAudioOutputBuffers();
Chris@39 190
Chris@40 191 if (buffers) {
Chris@40 192
Chris@40 193 //!!! This will fail if any buffers[c] is null or
Chris@40 194 //uninitialised. The plugin instance should ensure
Chris@40 195 //that that can't happen -- but it doesn't
Chris@40 196
Chris@40 197 if (blockFrame >= latency) {
Chris@40 198 wwfm->addSamples(buffers, blockSize);
Chris@40 199 } else if (blockFrame + blockSize >= latency) {
Chris@40 200 size_t offset = latency - blockFrame;
Chris@40 201 size_t count = blockSize - offset;
Chris@40 202 float **tmp = new float *[channelCount];
Chris@40 203 for (size_t c = 0; c < channelCount; ++c) {
Chris@40 204 tmp[c] = buffers[c] + offset;
Chris@40 205 }
Chris@40 206 wwfm->addSamples(tmp, count);
Chris@40 207 delete[] tmp;
Chris@39 208 }
Chris@39 209 }
Chris@39 210 }
Chris@0 211
Chris@0 212 if (blockFrame == startFrame || completion > prevCompletion) {
Chris@39 213 if (stvm) stvm->setCompletion(completion);
Chris@0 214 prevCompletion = completion;
Chris@0 215 }
Chris@0 216
Chris@0 217 blockFrame += blockSize;
Chris@0 218 }
Chris@0 219
Chris@39 220 if (stvm) stvm->setCompletion(100);
Chris@39 221 if (wwfm) wwfm->sync();
Chris@0 222 }
Chris@0 223