00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <vector>
00039 #include <map>
00040
00041 #include "PluginBufferingAdapter.h"
00042
00043 using std::vector;
00044 using std::map;
00045
00046 namespace Vamp {
00047
00048 namespace HostExt {
00049
00050 class PluginBufferingAdapter::Impl
00051 {
00052 public:
00053 Impl(Plugin *plugin, float inputSampleRate);
00054 ~Impl();
00055
00056 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
00057
00058 OutputList getOutputDescriptors() const;
00059
00060 void reset();
00061
00062 FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
00063
00064 FeatureSet getRemainingFeatures();
00065
00066 protected:
00067 class RingBuffer
00068 {
00069 public:
00070 RingBuffer(int n) :
00071 m_buffer(new float[n+1]), m_writer(0), m_reader(0), m_size(n+1) { }
00072 virtual ~RingBuffer() { delete[] m_buffer; }
00073
00074 int getSize() const { return m_size-1; }
00075 void reset() { m_writer = 0; m_reader = 0; }
00076
00077 int getReadSpace() const {
00078 int writer = m_writer, reader = m_reader, space;
00079 if (writer > reader) space = writer - reader;
00080 else if (writer < reader) space = (writer + m_size) - reader;
00081 else space = 0;
00082 return space;
00083 }
00084
00085 int getWriteSpace() const {
00086 int writer = m_writer;
00087 int reader = m_reader;
00088 int space = (reader + m_size - writer - 1);
00089 if (space >= m_size) space -= m_size;
00090 return space;
00091 }
00092
00093 int peek(float *destination, int n) const {
00094
00095 int available = getReadSpace();
00096
00097 if (n > available) {
00098 for (int i = available; i < n; ++i) {
00099 destination[i] = 0.f;
00100 }
00101 n = available;
00102 }
00103 if (n == 0) return n;
00104
00105 int reader = m_reader;
00106 int here = m_size - reader;
00107 const float *const bufbase = m_buffer + reader;
00108
00109 if (here >= n) {
00110 for (int i = 0; i < n; ++i) {
00111 destination[i] = bufbase[i];
00112 }
00113 } else {
00114 for (int i = 0; i < here; ++i) {
00115 destination[i] = bufbase[i];
00116 }
00117 float *const destbase = destination + here;
00118 const int nh = n - here;
00119 for (int i = 0; i < nh; ++i) {
00120 destbase[i] = m_buffer[i];
00121 }
00122 }
00123
00124 return n;
00125 }
00126
00127 int skip(int n) {
00128
00129 int available = getReadSpace();
00130 if (n > available) {
00131 n = available;
00132 }
00133 if (n == 0) return n;
00134
00135 int reader = m_reader;
00136 reader += n;
00137 while (reader >= m_size) reader -= m_size;
00138 m_reader = reader;
00139 return n;
00140 }
00141
00142 int write(const float *source, int n) {
00143
00144 int available = getWriteSpace();
00145 if (n > available) {
00146 n = available;
00147 }
00148 if (n == 0) return n;
00149
00150 int writer = m_writer;
00151 int here = m_size - writer;
00152 float *const bufbase = m_buffer + writer;
00153
00154 if (here >= n) {
00155 for (int i = 0; i < n; ++i) {
00156 bufbase[i] = source[i];
00157 }
00158 } else {
00159 for (int i = 0; i < here; ++i) {
00160 bufbase[i] = source[i];
00161 }
00162 const int nh = n - here;
00163 const float *const srcbase = source + here;
00164 float *const buf = m_buffer;
00165 for (int i = 0; i < nh; ++i) {
00166 buf[i] = srcbase[i];
00167 }
00168 }
00169
00170 writer += n;
00171 while (writer >= m_size) writer -= m_size;
00172 m_writer = writer;
00173
00174 return n;
00175 }
00176
00177 int zero(int n) {
00178
00179 int available = getWriteSpace();
00180 if (n > available) {
00181 n = available;
00182 }
00183 if (n == 0) return n;
00184
00185 int writer = m_writer;
00186 int here = m_size - writer;
00187 float *const bufbase = m_buffer + writer;
00188
00189 if (here >= n) {
00190 for (int i = 0; i < n; ++i) {
00191 bufbase[i] = 0.f;
00192 }
00193 } else {
00194 for (int i = 0; i < here; ++i) {
00195 bufbase[i] = 0.f;
00196 }
00197 const int nh = n - here;
00198 for (int i = 0; i < nh; ++i) {
00199 m_buffer[i] = 0.f;
00200 }
00201 }
00202
00203 writer += n;
00204 while (writer >= m_size) writer -= m_size;
00205 m_writer = writer;
00206
00207 return n;
00208 }
00209
00210 protected:
00211 float *m_buffer;
00212 int m_writer;
00213 int m_reader;
00214 int m_size;
00215
00216 private:
00217 RingBuffer(const RingBuffer &);
00218 RingBuffer &operator=(const RingBuffer &);
00219 };
00220
00221 Plugin *m_plugin;
00222 size_t m_inputStepSize;
00223 size_t m_inputBlockSize;
00224 size_t m_stepSize;
00225 size_t m_blockSize;
00226 size_t m_channels;
00227 vector<RingBuffer *> m_queue;
00228 float **m_buffers;
00229 float m_inputSampleRate;
00230 long m_frame;
00231 bool m_unrun;
00232 mutable OutputList m_outputs;
00233 mutable std::map<int, bool> m_rewriteOutputTimes;
00234
00235 void processBlock(FeatureSet& allFeatureSets);
00236 };
00237
00238 PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) :
00239 PluginWrapper(plugin)
00240 {
00241 m_impl = new Impl(plugin, m_inputSampleRate);
00242 }
00243
00244 PluginBufferingAdapter::~PluginBufferingAdapter()
00245 {
00246 delete m_impl;
00247 }
00248
00249 bool
00250 PluginBufferingAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
00251 {
00252 return m_impl->initialise(channels, stepSize, blockSize);
00253 }
00254
00255 PluginBufferingAdapter::OutputList
00256 PluginBufferingAdapter::getOutputDescriptors() const
00257 {
00258 return m_impl->getOutputDescriptors();
00259 }
00260
00261 void
00262 PluginBufferingAdapter::reset()
00263 {
00264 m_impl->reset();
00265 }
00266
00267 PluginBufferingAdapter::FeatureSet
00268 PluginBufferingAdapter::process(const float *const *inputBuffers,
00269 RealTime timestamp)
00270 {
00271 return m_impl->process(inputBuffers, timestamp);
00272 }
00273
00274 PluginBufferingAdapter::FeatureSet
00275 PluginBufferingAdapter::getRemainingFeatures()
00276 {
00277 return m_impl->getRemainingFeatures();
00278 }
00279
00280 PluginBufferingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
00281 m_plugin(plugin),
00282 m_inputStepSize(0),
00283 m_inputBlockSize(0),
00284 m_stepSize(0),
00285 m_blockSize(0),
00286 m_channels(0),
00287 m_queue(0),
00288 m_buffers(0),
00289 m_inputSampleRate(inputSampleRate),
00290 m_frame(0),
00291 m_unrun(true)
00292 {
00293 (void)getOutputDescriptors();
00294 }
00295
00296 PluginBufferingAdapter::Impl::~Impl()
00297 {
00298
00299
00300 for (size_t i = 0; i < m_channels; ++i) {
00301 delete m_queue[i];
00302 delete[] m_buffers[i];
00303 }
00304 delete[] m_buffers;
00305 }
00306
00307 size_t
00308 PluginBufferingAdapter::getPreferredStepSize() const
00309 {
00310 return getPreferredBlockSize();
00311 }
00312
00313 bool
00314 PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
00315 {
00316 if (stepSize != blockSize) {
00317 std::cerr << "PluginBufferingAdapter::initialise: input stepSize must be equal to blockSize for this adapter (stepSize = " << stepSize << ", blockSize = " << blockSize << ")" << std::endl;
00318 return false;
00319 }
00320
00321 m_channels = channels;
00322 m_inputStepSize = stepSize;
00323 m_inputBlockSize = blockSize;
00324
00325
00326 m_stepSize = m_plugin->getPreferredStepSize();
00327 m_blockSize = m_plugin->getPreferredBlockSize();
00328
00329
00330 if (m_blockSize == 0) {
00331 m_blockSize = 1024;
00332 }
00333 if (m_stepSize == 0) {
00334 if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) {
00335 m_stepSize = m_blockSize/2;
00336 } else {
00337 m_stepSize = m_blockSize;
00338 }
00339 } else if (m_stepSize > m_blockSize) {
00340 if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) {
00341 m_blockSize = m_stepSize * 2;
00342 } else {
00343 m_blockSize = m_stepSize;
00344 }
00345 }
00346
00347 std::cerr << "PluginBufferingAdapter::initialise: stepSize " << m_inputStepSize << " -> " << m_stepSize
00348 << ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl;
00349
00350
00351 if (m_stepSize > m_blockSize) {
00352 std::cerr << "PluginBufferingAdapter::initialise: plugin's preferred stepSize greater than blockSize, giving up!" << std::endl;
00353 return false;
00354 }
00355
00356 m_buffers = new float *[m_channels];
00357
00358 for (size_t i = 0; i < m_channels; ++i) {
00359 m_queue.push_back(new RingBuffer(m_blockSize + m_inputBlockSize));
00360 m_buffers[i] = new float[m_blockSize];
00361 }
00362
00363 return m_plugin->initialise(m_channels, m_stepSize, m_blockSize);
00364 }
00365
00366 PluginBufferingAdapter::OutputList
00367 PluginBufferingAdapter::Impl::getOutputDescriptors() const
00368 {
00369 if (m_outputs.empty()) {
00370 m_outputs = m_plugin->getOutputDescriptors();
00371 }
00372
00373 PluginBufferingAdapter::OutputList outs = m_outputs;
00374
00375 for (size_t i = 0; i < outs.size(); ++i) {
00376
00377 switch (outs[i].sampleType) {
00378
00379 case OutputDescriptor::OneSamplePerStep:
00380 outs[i].sampleType = OutputDescriptor::FixedSampleRate;
00381 outs[i].sampleRate = (1.f / m_inputSampleRate) * m_stepSize;
00382 m_rewriteOutputTimes[i] = true;
00383 break;
00384
00385 case OutputDescriptor::FixedSampleRate:
00386 if (outs[i].sampleRate == 0.f) {
00387 outs[i].sampleRate = (1.f / m_inputSampleRate) * m_stepSize;
00388 }
00389
00390
00391
00392
00393 m_rewriteOutputTimes[i] = true;
00394 break;
00395
00396 case OutputDescriptor::VariableSampleRate:
00397 m_rewriteOutputTimes[i] = false;
00398 break;
00399 }
00400 }
00401
00402 return outs;
00403 }
00404
00405 void
00406 PluginBufferingAdapter::Impl::reset()
00407 {
00408 m_frame = 0;
00409 m_unrun = true;
00410
00411 for (size_t i = 0; i < m_queue.size(); ++i) {
00412 m_queue[i]->reset();
00413 }
00414 }
00415
00416 PluginBufferingAdapter::FeatureSet
00417 PluginBufferingAdapter::Impl::process(const float *const *inputBuffers,
00418 RealTime timestamp)
00419 {
00420 FeatureSet allFeatureSets;
00421
00422 if (m_unrun) {
00423 m_frame = RealTime::realTime2Frame(timestamp,
00424 int(m_inputSampleRate + 0.5));
00425 m_unrun = false;
00426 }
00427
00428
00429
00430 for (size_t i = 0; i < m_channels; ++i) {
00431 int written = m_queue[i]->write(inputBuffers[i], m_inputBlockSize);
00432 if (written < int(m_inputBlockSize) && i == 0) {
00433 std::cerr << "WARNING: PluginBufferingAdapter::Impl::process: "
00434 << "Buffer overflow: wrote " << written
00435 << " of " << m_inputBlockSize
00436 << " input samples (for plugin step size "
00437 << m_stepSize << ", block size " << m_blockSize << ")"
00438 << std::endl;
00439 }
00440 }
00441
00442
00443
00444 while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
00445 processBlock(allFeatureSets);
00446 }
00447
00448 return allFeatureSets;
00449 }
00450
00451 PluginBufferingAdapter::FeatureSet
00452 PluginBufferingAdapter::Impl::getRemainingFeatures()
00453 {
00454 FeatureSet allFeatureSets;
00455
00456
00457 while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
00458 processBlock(allFeatureSets);
00459 }
00460
00461
00462 if (m_queue[0]->getReadSpace() > 0) {
00463 for (size_t i = 0; i < m_channels; ++i) {
00464 m_queue[i]->zero(m_blockSize - m_queue[i]->getReadSpace());
00465 }
00466 processBlock(allFeatureSets);
00467 }
00468
00469
00470
00471 FeatureSet featureSet = m_plugin->getRemainingFeatures();
00472
00473 for (map<int, FeatureList>::iterator iter = featureSet.begin();
00474 iter != featureSet.end(); ++iter) {
00475 FeatureList featureList = iter->second;
00476 for (size_t i = 0; i < featureList.size(); ++i) {
00477 allFeatureSets[iter->first].push_back(featureList[i]);
00478 }
00479 }
00480
00481 return allFeatureSets;
00482 }
00483
00484 void
00485 PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets)
00486 {
00487 for (size_t i = 0; i < m_channels; ++i) {
00488 m_queue[i]->peek(m_buffers[i], m_blockSize);
00489 }
00490
00491 long frame = m_frame;
00492 RealTime timestamp = RealTime::frame2RealTime
00493 (frame, int(m_inputSampleRate + 0.5));
00494
00495 FeatureSet featureSet = m_plugin->process(m_buffers, timestamp);
00496
00497 for (FeatureSet::iterator iter = featureSet.begin();
00498 iter != featureSet.end(); ++iter) {
00499
00500 int outputNo = iter->first;
00501
00502 if (m_rewriteOutputTimes[outputNo]) {
00503
00504 FeatureList featureList = iter->second;
00505
00506 for (size_t i = 0; i < featureList.size(); ++i) {
00507
00508 switch (m_outputs[outputNo].sampleType) {
00509
00510 case OutputDescriptor::OneSamplePerStep:
00511
00512 featureList[i].timestamp = timestamp;
00513 featureList[i].hasTimestamp = true;
00514 break;
00515
00516 case OutputDescriptor::FixedSampleRate:
00517
00518 if (!featureList[i].hasTimestamp) {
00519 featureList[i].timestamp = timestamp;
00520 featureList[i].hasTimestamp = true;
00521 }
00522 break;
00523
00524 case OutputDescriptor::VariableSampleRate:
00525 break;
00526
00527 default:
00528 break;
00529 }
00530
00531 allFeatureSets[outputNo].push_back(featureList[i]);
00532 }
00533 } else {
00534 for (size_t i = 0; i < iter->second.size(); ++i) {
00535 allFeatureSets[outputNo].push_back(iter->second[i]);
00536 }
00537 }
00538 }
00539
00540
00541
00542 for (size_t i = 0; i < m_channels; ++i) {
00543 m_queue[i]->skip(m_stepSize);
00544 }
00545
00546
00547 m_frame += m_stepSize;
00548 }
00549
00550 }
00551
00552 }
00553
00554