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 RealTime m_timestamp;
00231 bool m_unrun;
00232 OutputList m_outputs;
00233
00234 void processBlock(FeatureSet& allFeatureSets, RealTime timestamp);
00235 };
00236
00237 PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) :
00238 PluginWrapper(plugin)
00239 {
00240 m_impl = new Impl(plugin, m_inputSampleRate);
00241 }
00242
00243 PluginBufferingAdapter::~PluginBufferingAdapter()
00244 {
00245 delete m_impl;
00246 }
00247
00248 bool
00249 PluginBufferingAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
00250 {
00251 return m_impl->initialise(channels, stepSize, blockSize);
00252 }
00253
00254 PluginBufferingAdapter::OutputList
00255 PluginBufferingAdapter::getOutputDescriptors() const
00256 {
00257 return m_impl->getOutputDescriptors();
00258 }
00259
00260 void
00261 PluginBufferingAdapter::reset()
00262 {
00263 m_impl->reset();
00264 }
00265
00266 PluginBufferingAdapter::FeatureSet
00267 PluginBufferingAdapter::process(const float *const *inputBuffers,
00268 RealTime timestamp)
00269 {
00270 return m_impl->process(inputBuffers, timestamp);
00271 }
00272
00273 PluginBufferingAdapter::FeatureSet
00274 PluginBufferingAdapter::getRemainingFeatures()
00275 {
00276 return m_impl->getRemainingFeatures();
00277 }
00278
00279 PluginBufferingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
00280 m_plugin(plugin),
00281 m_inputStepSize(0),
00282 m_inputBlockSize(0),
00283 m_stepSize(0),
00284 m_blockSize(0),
00285 m_channels(0),
00286 m_queue(0),
00287 m_buffers(0),
00288 m_inputSampleRate(inputSampleRate),
00289 m_timestamp(RealTime::zeroTime),
00290 m_unrun(true)
00291 {
00292 m_outputs = plugin->getOutputDescriptors();
00293 }
00294
00295 PluginBufferingAdapter::Impl::~Impl()
00296 {
00297
00298
00299 for (size_t i = 0; i < m_channels; ++i) {
00300 delete m_queue[i];
00301 delete[] m_buffers[i];
00302 }
00303 delete[] m_buffers;
00304 }
00305
00306 size_t
00307 PluginBufferingAdapter::getPreferredStepSize() const
00308 {
00309 return getPreferredBlockSize();
00310 }
00311
00312 bool
00313 PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
00314 {
00315 if (stepSize != blockSize) {
00316 std::cerr << "PluginBufferingAdapter::initialise: input stepSize must be equal to blockSize for this adapter (stepSize = " << stepSize << ", blockSize = " << blockSize << ")" << std::endl;
00317 return false;
00318 }
00319
00320 m_channels = channels;
00321 m_inputStepSize = stepSize;
00322 m_inputBlockSize = blockSize;
00323
00324
00325 m_stepSize = m_plugin->getPreferredStepSize();
00326 m_blockSize = m_plugin->getPreferredBlockSize();
00327
00328
00329 if (m_blockSize == 0) {
00330 m_blockSize = 1024;
00331 }
00332 if (m_stepSize == 0) {
00333 if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) {
00334 m_stepSize = m_blockSize/2;
00335 } else {
00336 m_stepSize = m_blockSize;
00337 }
00338 } else if (m_stepSize > m_blockSize) {
00339 if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) {
00340 m_blockSize = m_stepSize * 2;
00341 } else {
00342 m_blockSize = m_stepSize;
00343 }
00344 }
00345
00346 std::cerr << "PluginBufferingAdapter::initialise: stepSize " << m_inputStepSize << " -> " << m_stepSize
00347 << ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl;
00348
00349
00350 if (m_stepSize > m_blockSize) {
00351 std::cerr << "PluginBufferingAdapter::initialise: plugin's preferred stepSize greater than blockSize, giving up!" << std::endl;
00352 return false;
00353 }
00354
00355 m_buffers = new float *[m_channels];
00356
00357 for (size_t i = 0; i < m_channels; ++i) {
00358 m_queue.push_back(new RingBuffer(m_blockSize + m_inputBlockSize));
00359 m_buffers[i] = new float[m_blockSize];
00360 }
00361
00362 return m_plugin->initialise(m_channels, m_stepSize, m_blockSize);
00363 }
00364
00365 PluginBufferingAdapter::OutputList
00366 PluginBufferingAdapter::Impl::getOutputDescriptors() const
00367 {
00368 OutputList outs = m_plugin->getOutputDescriptors();
00369 for (size_t i = 0; i < outs.size(); ++i) {
00370 if (outs[i].sampleType == OutputDescriptor::OneSamplePerStep) {
00371 outs[i].sampleRate = 1.f / m_stepSize;
00372 }
00373 outs[i].sampleType = OutputDescriptor::VariableSampleRate;
00374 }
00375 return outs;
00376 }
00377
00378 void
00379 PluginBufferingAdapter::Impl::reset()
00380 {
00381 m_timestamp = RealTime::zeroTime;
00382 m_unrun = true;
00383
00384 for (size_t i = 0; i < m_queue.size(); ++i) {
00385 m_queue[i]->reset();
00386 }
00387 }
00388
00389 PluginBufferingAdapter::FeatureSet
00390 PluginBufferingAdapter::Impl::process(const float *const *inputBuffers,
00391 RealTime timestamp)
00392 {
00393 FeatureSet allFeatureSets;
00394
00395 if (m_unrun) {
00396 m_timestamp = timestamp;
00397 m_unrun = false;
00398 }
00399
00400
00401
00402 for (size_t i = 0; i < m_channels; ++i) {
00403 int written = m_queue[i]->write(inputBuffers[i], m_inputBlockSize);
00404 if (written < int(m_inputBlockSize) && i == 0) {
00405 std::cerr << "WARNING: PluginBufferingAdapter::Impl::process: "
00406 << "Buffer overflow: wrote " << written
00407 << " of " << m_inputBlockSize
00408 << " input samples (for plugin step size "
00409 << m_stepSize << ", block size " << m_blockSize << ")"
00410 << std::endl;
00411 }
00412 }
00413
00414
00415
00416 while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
00417 processBlock(allFeatureSets, timestamp);
00418 }
00419
00420 return allFeatureSets;
00421 }
00422
00423 PluginBufferingAdapter::FeatureSet
00424 PluginBufferingAdapter::Impl::getRemainingFeatures()
00425 {
00426 FeatureSet allFeatureSets;
00427
00428
00429 while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
00430 processBlock(allFeatureSets, m_timestamp);
00431 }
00432
00433
00434 if (m_queue[0]->getReadSpace() > 0) {
00435 for (size_t i = 0; i < m_channels; ++i) {
00436 m_queue[i]->zero(m_blockSize - m_queue[i]->getReadSpace());
00437 }
00438 processBlock(allFeatureSets, m_timestamp);
00439 }
00440
00441
00442
00443 FeatureSet featureSet = m_plugin->getRemainingFeatures();
00444
00445 for (map<int, FeatureList>::iterator iter = featureSet.begin();
00446 iter != featureSet.end(); ++iter) {
00447 FeatureList featureList = iter->second;
00448 for (size_t i = 0; i < featureList.size(); ++i) {
00449 allFeatureSets[iter->first].push_back(featureList[i]);
00450 }
00451 }
00452
00453 return allFeatureSets;
00454 }
00455
00456 void
00457 PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets,
00458 RealTime timestamp)
00459 {
00460 for (size_t i = 0; i < m_channels; ++i) {
00461 m_queue[i]->peek(m_buffers[i], m_blockSize);
00462 }
00463
00464 FeatureSet featureSet = m_plugin->process(m_buffers, m_timestamp);
00465
00466 for (map<int, FeatureList>::iterator iter = featureSet.begin();
00467 iter != featureSet.end(); ++iter) {
00468
00469 FeatureList featureList = iter->second;
00470 int outputNo = iter->first;
00471
00472 for (size_t i = 0; i < featureList.size(); ++i) {
00473
00474
00475 switch (m_outputs[outputNo].sampleType) {
00476
00477 case OutputDescriptor::OneSamplePerStep:
00478
00479 featureList[i].timestamp = m_timestamp;
00480 break;
00481
00482 case OutputDescriptor::FixedSampleRate:
00483
00484 featureList[i].timestamp = m_timestamp;
00485 break;
00486
00487 case OutputDescriptor::VariableSampleRate:
00488 break;
00489
00490 default:
00491 break;
00492 }
00493
00494 allFeatureSets[outputNo].push_back(featureList[i]);
00495 }
00496 }
00497
00498
00499
00500 for (size_t i = 0; i < m_channels; ++i) {
00501 m_queue[i]->skip(m_stepSize);
00502 }
00503
00504
00505
00506 long frame = RealTime::realTime2Frame(m_timestamp,
00507 int(m_inputSampleRate + 0.5));
00508 m_timestamp = RealTime::frame2RealTime(frame + m_stepSize,
00509 int(m_inputSampleRate + 0.5));
00510 }
00511
00512 }
00513
00514 }
00515
00516