comparison sv/transform/RealTimePluginTransform.cpp @ 0:fc9323a41f5a

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