svcore  1.9
RealTimeEffectModelTransformer.cpp
Go to the documentation of this file.
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 
17 
20 #include "plugin/PluginXml.h"
21 
22 #include "data/model/Model.h"
27 
28 #include "TransformFactory.h"
29 
30 #include <iostream>
31 
33  const Transform &t) :
34  ModelTransformer(in, t),
35  m_plugin(0)
36 {
37  Transform transform(t);
38  if (!transform.getBlockSize()) {
39  transform.setBlockSize(1024);
40  m_transforms[0] = transform;
41  }
42 
44  (transform.getIdentifier());
45  m_outputNo =
46  (transform.getOutput() == "A") ? -1 : transform.getOutput().toInt();
47 
48  QString pluginId = transform.getPluginIdentifier();
49 
50 // SVDEBUG << "RealTimeEffectModelTransformer::RealTimeEffectModelTransformer: plugin " << pluginId << ", output " << output << endl;
51 
52  RealTimePluginFactory *factory =
54 
55  if (!factory) {
56  cerr << "RealTimeEffectModelTransformer: No factory available for plugin id \""
57  << pluginId << "\"" << endl;
58  return;
59  }
60 
62  if (!input) return;
63 
64  m_plugin = factory->instantiatePlugin(pluginId, 0, 0,
65  input->getSampleRate(),
66  transform.getBlockSize(),
67  input->getChannelCount());
68 
69  if (!m_plugin) {
70  cerr << "RealTimeEffectModelTransformer: Failed to instantiate plugin \""
71  << pluginId << "\"" << endl;
72  return;
73  }
74 
76 
77  if (m_outputNo >= 0 &&
79  cerr << "RealTimeEffectModelTransformer: Plugin has fewer than desired " << m_outputNo << " control outputs" << endl;
80  return;
81  }
82 
83  if (m_outputNo == -1) {
84 
85  int outputChannels = m_plugin->getAudioOutputCount();
86  if (outputChannels > input->getChannelCount()) {
87  outputChannels = input->getChannelCount();
88  }
89 
91  (input->getSampleRate(), outputChannels);
92 
93  m_outputs.push_back(model);
94 
95  } else {
96 
98  (input->getSampleRate(), transform.getBlockSize(), 0.0, 0.0, false);
99 
100  if (m_units != "") model->setScaleUnits(m_units);
101 
102  m_outputs.push_back(model);
103  }
104 }
105 
107 {
108  delete m_plugin;
109 }
110 
113 {
114  DenseTimeValueModel *dtvm =
115  dynamic_cast<DenseTimeValueModel *>(getInputModel());
116  if (!dtvm) {
117  SVDEBUG << "RealTimeEffectModelTransformer::getConformingInput: WARNING: Input model is not conformable to DenseTimeValueModel" << endl;
118  }
119  return dtvm;
120 }
121 
122 void
124 {
126  if (!input) return;
127 
128  while (!input->isReady() && !m_abandoned) {
129  SVDEBUG << "RealTimeEffectModelTransformer::run: Waiting for input model to be ready..." << endl;
130  usleep(500000);
131  }
132  if (m_abandoned) return;
133 
134  SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>(m_outputs[0]);
135  WritableWaveFileModel *wwfm = dynamic_cast<WritableWaveFileModel *>(m_outputs[0]);
136  if (!stvm && !wwfm) return;
137 
138  if (stvm && (m_outputNo >= int(m_plugin->getControlOutputCount()))) return;
139 
140  int sampleRate = input->getSampleRate();
141  int channelCount = input->getChannelCount();
142  if (!wwfm && m_input.getChannel() != -1) channelCount = 1;
143 
144  long blockSize = m_plugin->getBufferSize();
145 
146  float **inbufs = m_plugin->getAudioInputBuffers();
147 
148  long startFrame = m_input.getModel()->getStartFrame();
149  long endFrame = m_input.getModel()->getEndFrame();
150 
151  Transform transform = m_transforms[0];
152 
153  RealTime contextStartRT = transform.getStartTime();
154  RealTime contextDurationRT = transform.getDuration();
155 
156  long contextStart =
157  RealTime::realTime2Frame(contextStartRT, sampleRate);
158 
159  long contextDuration =
160  RealTime::realTime2Frame(contextDurationRT, sampleRate);
161 
162  if (contextStart == 0 || contextStart < startFrame) {
163  contextStart = startFrame;
164  }
165 
166  if (contextDuration == 0) {
167  contextDuration = endFrame - contextStart;
168  }
169  if (contextStart + contextDuration > endFrame) {
170  contextDuration = endFrame - contextStart;
171  }
172 
173  if (wwfm) {
174  wwfm->setStartFrame(contextStart);
175  }
176 
177  long blockFrame = contextStart;
178 
179  long prevCompletion = 0;
180 
181  long latency = m_plugin->getLatency();
182 
183  while (blockFrame < contextStart + contextDuration + latency &&
184  !m_abandoned) {
185 
186  long completion =
187  (((blockFrame - contextStart) / blockSize) * 99) /
188  (1 + ((contextDuration) / blockSize));
189 
190  long got = 0;
191 
192  if (channelCount == 1) {
193  if (inbufs && inbufs[0]) {
194  got = input->getData
195  (m_input.getChannel(), blockFrame, blockSize, inbufs[0]);
196  while (got < blockSize) {
197  inbufs[0][got++] = 0.0;
198  }
199  for (int ch = 1; ch < (int)m_plugin->getAudioInputCount(); ++ch) {
200  for (long i = 0; i < blockSize; ++i) {
201  inbufs[ch][i] = inbufs[0][i];
202  }
203  }
204  }
205  } else {
206  if (inbufs && inbufs[0]) {
207  got = input->getData(0, channelCount - 1,
208  blockFrame, blockSize,
209  inbufs);
210  while (got < blockSize) {
211  for (int ch = 0; ch < channelCount; ++ch) {
212  inbufs[ch][got] = 0.0;
213  }
214  ++got;
215  }
216  for (int ch = channelCount; ch < (int)m_plugin->getAudioInputCount(); ++ch) {
217  for (long i = 0; i < blockSize; ++i) {
218  inbufs[ch][i] = inbufs[ch % channelCount][i];
219  }
220  }
221  }
222  }
223 
224 /*
225  cerr << "Input for plugin: " << m_plugin->getAudioInputCount() << " channels "<< endl;
226 
227  for (int ch = 0; ch < m_plugin->getAudioInputCount(); ++ch) {
228  cerr << "Input channel " << ch << endl;
229  for (int i = 0; i < 100; ++i) {
230  cerr << inbufs[ch][i] << " ";
231  if (isnan(inbufs[ch][i])) {
232  cerr << "\n\nWARNING: NaN in audio input" << endl;
233  }
234  }
235  }
236 */
237 
238  m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
239 
240  if (stvm) {
241 
242  float value = m_plugin->getControlOutputValue(m_outputNo);
243 
244  long pointFrame = blockFrame;
245  if (pointFrame > latency) pointFrame -= latency;
246  else pointFrame = 0;
247 
249  (pointFrame, value, ""));
250 
251  } else if (wwfm) {
252 
253  float **outbufs = m_plugin->getAudioOutputBuffers();
254 
255  if (outbufs) {
256 
257  if (blockFrame >= latency) {
258  long writeSize = std::min
259  (blockSize,
260  contextStart + contextDuration + latency - blockFrame);
261  wwfm->addSamples(outbufs, writeSize);
262  } else if (blockFrame + blockSize >= latency) {
263  long offset = latency - blockFrame;
264  long count = blockSize - offset;
265  float **tmp = new float *[channelCount];
266  for (int c = 0; c < channelCount; ++c) {
267  tmp[c] = outbufs[c] + offset;
268  }
269  wwfm->addSamples(tmp, count);
270  delete[] tmp;
271  }
272  }
273  }
274 
275  if (blockFrame == contextStart || completion > prevCompletion) {
276  if (stvm) stvm->setCompletion(completion);
277  if (wwfm) wwfm->setCompletion(completion);
278  prevCompletion = completion;
279  }
280 
281  blockFrame += blockSize;
282  }
283 
284  if (m_abandoned) return;
285 
286  if (stvm) stvm->setCompletion(100);
287  if (wwfm) wwfm->setCompletion(100);
288 }
289 
virtual int getChannelCount() const =0
Return the number of distinct channels for this model.
Model * getModel() const
virtual size_t getAudioInputCount() const =0
virtual size_t getLatency()=0
virtual size_t getAudioOutputCount() const =0
virtual sample_t ** getAudioOutputBuffers()=0
static RealTimePluginFactory * instanceFor(QString identifier)
virtual int getStartFrame() const =0
Return the first audio frame spanned by the model.
virtual size_t getControlOutputCount() const =0
virtual int getData(int channel, int start, int count, float *buffer) const =0
Get the specified set of samples from the given channel of the model in single-precision floating-poi...
virtual void setCompletion(int completion)
virtual bool isReady(int *completion=0) const
Return true if the model has finished loading or calculating all its data, for a model that is capabl...
Definition: Model.h:142
QString getOutput() const
Definition: Transform.cpp:224
static TransformFactory * getInstance()
Transforms m_transforms
Time/value point type for use in a SparseModel or SparseValueModel.
void setPluginParameters(const Transform &transform, Vamp::PluginBase *plugin)
Set the parameters, program and configuration strings on the given plugin from the given Transform ob...
virtual void setScaleUnits(QString units)
void setStartFrame(int startFrame)
RealTime getStartTime() const
Definition: Transform.cpp:359
virtual void addPoint(const PointType &point)
Add a point.
virtual int getSampleRate() const =0
Return the frame rate in frames per second.
virtual sample_t ** getAudioInputBuffers()=0
virtual void run(const Vamp::RealTime &blockStartTime, size_t count=0)=0
Run for one block, starting at the given time.
void setBlockSize(int s)
Definition: Transform.cpp:341
virtual RealTimePluginInstance * instantiatePlugin(QString identifier, int clientId, int position, unsigned int sampleRate, unsigned int blockSize, unsigned int channels)=0
Instantiate a plugin.
#define SVDEBUG
Definition: Debug.h:42
Base class for models containing dense two-dimensional data (value against time).
virtual int getEndFrame() const =0
Return the last audio frame spanned by the model.
static long realTime2Frame(const RealTime &r, unsigned int sampleRate)
Convert a RealTime into a sample frame at the given sample rate.
Definition: RealTime.cpp:442
TransformId getIdentifier() const
Definition: Transform.cpp:182
A ModelTransformer turns one data model into another.
QString getTransformUnits(TransformId identifier)
RealTimeEffectModelTransformer(Input input, const Transform &transform)
virtual void setCompletion(int completion, bool update=true)
Definition: SparseModel.h:761
int getBlockSize() const
Definition: Transform.cpp:335
virtual size_t getBufferSize() const =0
Model * getInputModel()
Return the input model for the transform.
virtual float getControlOutputValue(size_t n) const =0
QString getPluginIdentifier() const
Definition: Transform.cpp:218
virtual bool addSamples(float **samples, int count)
Call addSamples to append a block of samples to the end of the file.
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...
Definition: RealTime.h:35
RealTime getDuration() const
Definition: Transform.cpp:371