cannam@0: cannam@0: cannam@0: VampPluginSDK: PluginBufferingAdapter.cpp Source File cannam@0: cannam@0: cannam@0: cannam@0: cannam@0: cannam@0: cannam@0:

PluginBufferingAdapter.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
cannam@0: 00002 
cannam@0: 00003 /*
cannam@0: 00004     Vamp
cannam@0: 00005 
cannam@0: 00006     An API for audio analysis and feature extraction plugins.
cannam@0: 00007 
cannam@0: 00008     Centre for Digital Music, Queen Mary, University of London.
cannam@0: 00009     Copyright 2006-2007 Chris Cannam and QMUL.
cannam@0: 00010     This file by Mark Levy and Chris Cannam.
cannam@0: 00011   
cannam@0: 00012     Permission is hereby granted, free of charge, to any person
cannam@0: 00013     obtaining a copy of this software and associated documentation
cannam@0: 00014     files (the "Software"), to deal in the Software without
cannam@0: 00015     restriction, including without limitation the rights to use, copy,
cannam@0: 00016     modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@0: 00017     of the Software, and to permit persons to whom the Software is
cannam@0: 00018     furnished to do so, subject to the following conditions:
cannam@0: 00019 
cannam@0: 00020     The above copyright notice and this permission notice shall be
cannam@0: 00021     included in all copies or substantial portions of the Software.
cannam@0: 00022 
cannam@0: 00023     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@0: 00024     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@0: 00025     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@0: 00026     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@0: 00027     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@0: 00028     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@0: 00029     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@0: 00030 
cannam@0: 00031     Except as contained in this notice, the names of the Centre for
cannam@0: 00032     Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@0: 00033     shall not be used in advertising or otherwise to promote the sale,
cannam@0: 00034     use or other dealings in this Software without prior written
cannam@0: 00035     authorization.
cannam@0: 00036 */
cannam@0: 00037 
cannam@0: 00038 #include <vector>
cannam@0: 00039 #include <map>
cannam@0: 00040 
cannam@0: 00041 #include "PluginBufferingAdapter.h"
cannam@0: 00042 
cannam@0: 00043 using std::vector;
cannam@0: 00044 using std::map;
cannam@0: 00045 
cannam@0: 00046 namespace Vamp {
cannam@0: 00047         
cannam@0: 00048 namespace HostExt {
cannam@0: 00049                 
cannam@0: 00050 class PluginBufferingAdapter::Impl
cannam@0: 00051 {
cannam@0: 00052 public:
cannam@0: 00053     Impl(Plugin *plugin, float inputSampleRate);
cannam@0: 00054     ~Impl();
cannam@0: 00055                 
cannam@0: 00056     bool initialise(size_t channels, size_t stepSize, size_t blockSize);
cannam@0: 00057 
cannam@0: 00058     OutputList getOutputDescriptors() const;
cannam@0: 00059 
cannam@0: 00060     void reset();
cannam@0: 00061 
cannam@0: 00062     FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
cannam@0: 00063                 
cannam@0: 00064     FeatureSet getRemainingFeatures();
cannam@0: 00065                 
cannam@0: 00066 protected:
cannam@0: 00067     class RingBuffer
cannam@0: 00068     {
cannam@0: 00069     public:
cannam@0: 00070         RingBuffer(int n) :
cannam@0: 00071             m_buffer(new float[n+1]), m_writer(0), m_reader(0), m_size(n+1) { }
cannam@0: 00072         virtual ~RingBuffer() { delete[] m_buffer; }
cannam@0: 00073 
cannam@0: 00074         int getSize() const { return m_size-1; }
cannam@0: 00075         void reset() { m_writer = 0; m_reader = 0; }
cannam@0: 00076 
cannam@0: 00077         int getReadSpace() const {
cannam@0: 00078             int writer = m_writer, reader = m_reader, space;
cannam@0: 00079             if (writer > reader) space = writer - reader;
cannam@0: 00080             else if (writer < reader) space = (writer + m_size) - reader;
cannam@0: 00081             else space = 0;
cannam@0: 00082             return space;
cannam@0: 00083         }
cannam@0: 00084 
cannam@0: 00085         int getWriteSpace() const {
cannam@0: 00086             int writer = m_writer;
cannam@0: 00087             int reader = m_reader;
cannam@0: 00088             int space = (reader + m_size - writer - 1);
cannam@0: 00089             if (space >= m_size) space -= m_size;
cannam@0: 00090             return space;
cannam@0: 00091         }
cannam@0: 00092         
cannam@0: 00093         int peek(float *destination, int n) const {
cannam@0: 00094 
cannam@0: 00095             int available = getReadSpace();
cannam@0: 00096 
cannam@0: 00097             if (n > available) {
cannam@0: 00098                 for (int i = available; i < n; ++i) {
cannam@0: 00099                     destination[i] = 0.f;
cannam@0: 00100                 }
cannam@0: 00101                 n = available;
cannam@0: 00102             }
cannam@0: 00103             if (n == 0) return n;
cannam@0: 00104 
cannam@0: 00105             int reader = m_reader;
cannam@0: 00106             int here = m_size - reader;
cannam@0: 00107             const float *const bufbase = m_buffer + reader;
cannam@0: 00108 
cannam@0: 00109             if (here >= n) {
cannam@0: 00110                 for (int i = 0; i < n; ++i) {
cannam@0: 00111                     destination[i] = bufbase[i];
cannam@0: 00112                 }
cannam@0: 00113             } else {
cannam@0: 00114                 for (int i = 0; i < here; ++i) {
cannam@0: 00115                     destination[i] = bufbase[i];
cannam@0: 00116                 }
cannam@0: 00117                 float *const destbase = destination + here;
cannam@0: 00118                 const int nh = n - here;
cannam@0: 00119                 for (int i = 0; i < nh; ++i) {
cannam@0: 00120                     destbase[i] = m_buffer[i];
cannam@0: 00121                 }
cannam@0: 00122             }
cannam@0: 00123 
cannam@0: 00124             return n;
cannam@0: 00125         }
cannam@0: 00126 
cannam@0: 00127         int skip(int n) {
cannam@0: 00128             
cannam@0: 00129             int available = getReadSpace();
cannam@0: 00130             if (n > available) {
cannam@0: 00131                 n = available;
cannam@0: 00132             }
cannam@0: 00133             if (n == 0) return n;
cannam@0: 00134 
cannam@0: 00135             int reader = m_reader;
cannam@0: 00136             reader += n;
cannam@0: 00137             while (reader >= m_size) reader -= m_size;
cannam@0: 00138             m_reader = reader;
cannam@0: 00139             return n;
cannam@0: 00140         }
cannam@0: 00141         
cannam@0: 00142         int write(const float *source, int n) {
cannam@0: 00143 
cannam@0: 00144             int available = getWriteSpace();
cannam@0: 00145             if (n > available) {
cannam@0: 00146                 n = available;
cannam@0: 00147             }
cannam@0: 00148             if (n == 0) return n;
cannam@0: 00149 
cannam@0: 00150             int writer = m_writer;
cannam@0: 00151             int here = m_size - writer;
cannam@0: 00152             float *const bufbase = m_buffer + writer;
cannam@0: 00153             
cannam@0: 00154             if (here >= n) {
cannam@0: 00155                 for (int i = 0; i < n; ++i) {
cannam@0: 00156                     bufbase[i] = source[i];
cannam@0: 00157                 }
cannam@0: 00158             } else {
cannam@0: 00159                 for (int i = 0; i < here; ++i) {
cannam@0: 00160                     bufbase[i] = source[i];
cannam@0: 00161                 }
cannam@0: 00162                 const int nh = n - here;
cannam@0: 00163                 const float *const srcbase = source + here;
cannam@0: 00164                 float *const buf = m_buffer;
cannam@0: 00165                 for (int i = 0; i < nh; ++i) {
cannam@0: 00166                     buf[i] = srcbase[i];
cannam@0: 00167                 }
cannam@0: 00168             }
cannam@0: 00169 
cannam@0: 00170             writer += n;
cannam@0: 00171             while (writer >= m_size) writer -= m_size;
cannam@0: 00172             m_writer = writer;
cannam@0: 00173 
cannam@0: 00174             return n;
cannam@0: 00175         }
cannam@0: 00176 
cannam@0: 00177         int zero(int n) {
cannam@0: 00178             
cannam@0: 00179             int available = getWriteSpace();
cannam@0: 00180             if (n > available) {
cannam@0: 00181                 n = available;
cannam@0: 00182             }
cannam@0: 00183             if (n == 0) return n;
cannam@0: 00184 
cannam@0: 00185             int writer = m_writer;
cannam@0: 00186             int here = m_size - writer;
cannam@0: 00187             float *const bufbase = m_buffer + writer;
cannam@0: 00188 
cannam@0: 00189             if (here >= n) {
cannam@0: 00190                 for (int i = 0; i < n; ++i) {
cannam@0: 00191                     bufbase[i] = 0.f;
cannam@0: 00192                 }
cannam@0: 00193             } else {
cannam@0: 00194                 for (int i = 0; i < here; ++i) {
cannam@0: 00195                     bufbase[i] = 0.f;
cannam@0: 00196                 }
cannam@0: 00197                 const int nh = n - here;
cannam@0: 00198                 for (int i = 0; i < nh; ++i) {
cannam@0: 00199                     m_buffer[i] = 0.f;
cannam@0: 00200                 }
cannam@0: 00201             }
cannam@0: 00202             
cannam@0: 00203             writer += n;
cannam@0: 00204             while (writer >= m_size) writer -= m_size;
cannam@0: 00205             m_writer = writer;
cannam@0: 00206 
cannam@0: 00207             return n;
cannam@0: 00208         }
cannam@0: 00209 
cannam@0: 00210     protected:
cannam@0: 00211         float *m_buffer;
cannam@0: 00212         int    m_writer;
cannam@0: 00213         int    m_reader;
cannam@0: 00214         int    m_size;
cannam@0: 00215 
cannam@0: 00216     private:
cannam@0: 00217         RingBuffer(const RingBuffer &); // not provided
cannam@0: 00218         RingBuffer &operator=(const RingBuffer &); // not provided
cannam@0: 00219     };
cannam@0: 00220 
cannam@0: 00221     Plugin *m_plugin;
cannam@0: 00222     size_t m_inputStepSize;
cannam@0: 00223     size_t m_inputBlockSize;
cannam@0: 00224     size_t m_stepSize;
cannam@0: 00225     size_t m_blockSize;
cannam@0: 00226     size_t m_channels;
cannam@0: 00227     vector<RingBuffer *> m_queue;
cannam@0: 00228     float **m_buffers;
cannam@0: 00229     float m_inputSampleRate;
cannam@0: 00230     long m_frame;
cannam@0: 00231     bool m_unrun;
cannam@0: 00232     mutable OutputList m_outputs;
cannam@0: 00233     mutable std::map<int, bool> m_rewriteOutputTimes;
cannam@0: 00234                 
cannam@0: 00235     void processBlock(FeatureSet& allFeatureSets);
cannam@0: 00236 };
cannam@0: 00237                 
cannam@0: 00238 PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) :
cannam@0: 00239     PluginWrapper(plugin)
cannam@0: 00240 {
cannam@0: 00241     m_impl = new Impl(plugin, m_inputSampleRate);
cannam@0: 00242 }
cannam@0: 00243                 
cannam@0: 00244 PluginBufferingAdapter::~PluginBufferingAdapter()
cannam@0: 00245 {
cannam@0: 00246     delete m_impl;
cannam@0: 00247 }
cannam@0: 00248                 
cannam@0: 00249 bool
cannam@0: 00250 PluginBufferingAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@0: 00251 {
cannam@0: 00252     return m_impl->initialise(channels, stepSize, blockSize);
cannam@0: 00253 }
cannam@0: 00254 
cannam@0: 00255 PluginBufferingAdapter::OutputList
cannam@0: 00256 PluginBufferingAdapter::getOutputDescriptors() const
cannam@0: 00257 {
cannam@0: 00258     return m_impl->getOutputDescriptors();
cannam@0: 00259 }
cannam@0: 00260 
cannam@0: 00261 void
cannam@0: 00262 PluginBufferingAdapter::reset()
cannam@0: 00263 {
cannam@0: 00264     m_impl->reset();
cannam@0: 00265 }
cannam@0: 00266                 
cannam@0: 00267 PluginBufferingAdapter::FeatureSet
cannam@0: 00268 PluginBufferingAdapter::process(const float *const *inputBuffers,
cannam@0: 00269                                 RealTime timestamp)
cannam@0: 00270 {
cannam@0: 00271     return m_impl->process(inputBuffers, timestamp);
cannam@0: 00272 }
cannam@0: 00273                 
cannam@0: 00274 PluginBufferingAdapter::FeatureSet
cannam@0: 00275 PluginBufferingAdapter::getRemainingFeatures()
cannam@0: 00276 {
cannam@0: 00277     return m_impl->getRemainingFeatures();
cannam@0: 00278 }
cannam@0: 00279                 
cannam@0: 00280 PluginBufferingAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
cannam@0: 00281     m_plugin(plugin),
cannam@0: 00282     m_inputStepSize(0),
cannam@0: 00283     m_inputBlockSize(0),
cannam@0: 00284     m_stepSize(0),
cannam@0: 00285     m_blockSize(0),
cannam@0: 00286     m_channels(0), 
cannam@0: 00287     m_queue(0),
cannam@0: 00288     m_buffers(0),
cannam@0: 00289     m_inputSampleRate(inputSampleRate),
cannam@0: 00290     m_frame(0),
cannam@0: 00291     m_unrun(true)
cannam@0: 00292 {
cannam@0: 00293     (void)getOutputDescriptors(); // set up m_outputs and m_rewriteOutputTimes
cannam@0: 00294 }
cannam@0: 00295                 
cannam@0: 00296 PluginBufferingAdapter::Impl::~Impl()
cannam@0: 00297 {
cannam@0: 00298     // the adapter will delete the plugin
cannam@0: 00299 
cannam@0: 00300     for (size_t i = 0; i < m_channels; ++i) {
cannam@0: 00301         delete m_queue[i];
cannam@0: 00302         delete[] m_buffers[i];
cannam@0: 00303     }
cannam@0: 00304     delete[] m_buffers;
cannam@0: 00305 }
cannam@0: 00306 
cannam@0: 00307 size_t
cannam@0: 00308 PluginBufferingAdapter::getPreferredStepSize() const
cannam@0: 00309 {
cannam@0: 00310     return getPreferredBlockSize();
cannam@0: 00311 }
cannam@0: 00312                 
cannam@0: 00313 bool
cannam@0: 00314 PluginBufferingAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@0: 00315 {
cannam@0: 00316     if (stepSize != blockSize) {
cannam@0: 00317         std::cerr << "PluginBufferingAdapter::initialise: input stepSize must be equal to blockSize for this adapter (stepSize = " << stepSize << ", blockSize = " << blockSize << ")" << std::endl;
cannam@0: 00318         return false;
cannam@0: 00319     }
cannam@0: 00320 
cannam@0: 00321     m_channels = channels;      
cannam@0: 00322     m_inputStepSize = stepSize;
cannam@0: 00323     m_inputBlockSize = blockSize;
cannam@0: 00324     
cannam@0: 00325     // use the step and block sizes which the plugin prefers
cannam@0: 00326     m_stepSize = m_plugin->getPreferredStepSize();
cannam@0: 00327     m_blockSize = m_plugin->getPreferredBlockSize();
cannam@0: 00328     
cannam@0: 00329     // or sensible defaults if it has no preference
cannam@0: 00330     if (m_blockSize == 0) {
cannam@0: 00331         m_blockSize = 1024;
cannam@0: 00332     }
cannam@0: 00333     if (m_stepSize == 0) {
cannam@0: 00334         if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) {
cannam@0: 00335             m_stepSize = m_blockSize/2;
cannam@0: 00336         } else {
cannam@0: 00337             m_stepSize = m_blockSize;
cannam@0: 00338         }
cannam@0: 00339     } else if (m_stepSize > m_blockSize) {
cannam@0: 00340         if (m_plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain) {
cannam@0: 00341             m_blockSize = m_stepSize * 2;
cannam@0: 00342         } else {
cannam@0: 00343             m_blockSize = m_stepSize;
cannam@0: 00344         }
cannam@0: 00345     }
cannam@0: 00346     
cannam@0: 00347     std::cerr << "PluginBufferingAdapter::initialise: stepSize " << m_inputStepSize << " -> " << m_stepSize 
cannam@0: 00348               << ", blockSize " << m_inputBlockSize << " -> " << m_blockSize << std::endl;                      
cannam@0: 00349     
cannam@0: 00350     // current implementation breaks if step is greater than block
cannam@0: 00351     if (m_stepSize > m_blockSize) {
cannam@0: 00352         std::cerr << "PluginBufferingAdapter::initialise: plugin's preferred stepSize greater than blockSize, giving up!" << std::endl;
cannam@0: 00353         return false;
cannam@0: 00354     }
cannam@0: 00355 
cannam@0: 00356     m_buffers = new float *[m_channels];
cannam@0: 00357 
cannam@0: 00358     for (size_t i = 0; i < m_channels; ++i) {
cannam@0: 00359         m_queue.push_back(new RingBuffer(m_blockSize + m_inputBlockSize));
cannam@0: 00360         m_buffers[i] = new float[m_blockSize];
cannam@0: 00361     }
cannam@0: 00362     
cannam@0: 00363     return m_plugin->initialise(m_channels, m_stepSize, m_blockSize);
cannam@0: 00364 }
cannam@0: 00365                 
cannam@0: 00366 PluginBufferingAdapter::OutputList
cannam@0: 00367 PluginBufferingAdapter::Impl::getOutputDescriptors() const
cannam@0: 00368 {
cannam@0: 00369     if (m_outputs.empty()) {
cannam@0: 00370         m_outputs = m_plugin->getOutputDescriptors();
cannam@0: 00371     }
cannam@0: 00372 
cannam@0: 00373     PluginBufferingAdapter::OutputList outs = m_outputs;
cannam@0: 00374 
cannam@0: 00375     for (size_t i = 0; i < outs.size(); ++i) {
cannam@0: 00376 
cannam@0: 00377         switch (outs[i].sampleType) {
cannam@0: 00378 
cannam@0: 00379         case OutputDescriptor::OneSamplePerStep:
cannam@0: 00380             outs[i].sampleType = OutputDescriptor::FixedSampleRate;
cannam@0: 00381             outs[i].sampleRate = (1.f / m_inputSampleRate) * m_stepSize;
cannam@0: 00382             m_rewriteOutputTimes[i] = true;
cannam@0: 00383             break;
cannam@0: 00384             
cannam@0: 00385         case OutputDescriptor::FixedSampleRate:
cannam@0: 00386             if (outs[i].sampleRate == 0.f) {
cannam@0: 00387                 outs[i].sampleRate = (1.f / m_inputSampleRate) * m_stepSize;
cannam@0: 00388             }
cannam@0: 00389             // We actually only need to rewrite output times for
cannam@0: 00390             // features that don't have timestamps already, but we
cannam@0: 00391             // can't tell from here whether our features will have
cannam@0: 00392             // timestamps or not
cannam@0: 00393             m_rewriteOutputTimes[i] = true;
cannam@0: 00394             break;
cannam@0: 00395 
cannam@0: 00396         case OutputDescriptor::VariableSampleRate:
cannam@0: 00397             m_rewriteOutputTimes[i] = false;
cannam@0: 00398             break;
cannam@0: 00399         }
cannam@0: 00400     }
cannam@0: 00401 
cannam@0: 00402     return outs;
cannam@0: 00403 }
cannam@0: 00404 
cannam@0: 00405 void
cannam@0: 00406 PluginBufferingAdapter::Impl::reset()
cannam@0: 00407 {
cannam@0: 00408     m_frame = 0;
cannam@0: 00409     m_unrun = true;
cannam@0: 00410 
cannam@0: 00411     for (size_t i = 0; i < m_queue.size(); ++i) {
cannam@0: 00412         m_queue[i]->reset();
cannam@0: 00413     }
cannam@0: 00414 }
cannam@0: 00415 
cannam@0: 00416 PluginBufferingAdapter::FeatureSet
cannam@0: 00417 PluginBufferingAdapter::Impl::process(const float *const *inputBuffers,
cannam@0: 00418                                       RealTime timestamp)
cannam@0: 00419 {
cannam@0: 00420     FeatureSet allFeatureSets;
cannam@0: 00421 
cannam@0: 00422     if (m_unrun) {
cannam@0: 00423         m_frame = RealTime::realTime2Frame(timestamp,
cannam@0: 00424                                            int(m_inputSampleRate + 0.5));
cannam@0: 00425         m_unrun = false;
cannam@0: 00426     }
cannam@0: 00427                         
cannam@0: 00428     // queue the new input
cannam@0: 00429     
cannam@0: 00430     for (size_t i = 0; i < m_channels; ++i) {
cannam@0: 00431         int written = m_queue[i]->write(inputBuffers[i], m_inputBlockSize);
cannam@0: 00432         if (written < int(m_inputBlockSize) && i == 0) {
cannam@0: 00433             std::cerr << "WARNING: PluginBufferingAdapter::Impl::process: "
cannam@0: 00434                       << "Buffer overflow: wrote " << written 
cannam@0: 00435                       << " of " << m_inputBlockSize 
cannam@0: 00436                       << " input samples (for plugin step size "
cannam@0: 00437                       << m_stepSize << ", block size " << m_blockSize << ")"
cannam@0: 00438                       << std::endl;
cannam@0: 00439         }
cannam@0: 00440     }    
cannam@0: 00441     
cannam@0: 00442     // process as much as we can
cannam@0: 00443 
cannam@0: 00444     while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
cannam@0: 00445         processBlock(allFeatureSets);
cannam@0: 00446     }   
cannam@0: 00447     
cannam@0: 00448     return allFeatureSets;
cannam@0: 00449 }
cannam@0: 00450     
cannam@0: 00451 PluginBufferingAdapter::FeatureSet
cannam@0: 00452 PluginBufferingAdapter::Impl::getRemainingFeatures() 
cannam@0: 00453 {
cannam@0: 00454     FeatureSet allFeatureSets;
cannam@0: 00455     
cannam@0: 00456     // process remaining samples in queue
cannam@0: 00457     while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
cannam@0: 00458         processBlock(allFeatureSets);
cannam@0: 00459     }
cannam@0: 00460     
cannam@0: 00461     // pad any last samples remaining and process
cannam@0: 00462     if (m_queue[0]->getReadSpace() > 0) {
cannam@0: 00463         for (size_t i = 0; i < m_channels; ++i) {
cannam@0: 00464             m_queue[i]->zero(m_blockSize - m_queue[i]->getReadSpace());
cannam@0: 00465         }
cannam@0: 00466         processBlock(allFeatureSets);
cannam@0: 00467     }                   
cannam@0: 00468     
cannam@0: 00469     // get remaining features                   
cannam@0: 00470 
cannam@0: 00471     FeatureSet featureSet = m_plugin->getRemainingFeatures();
cannam@0: 00472 
cannam@0: 00473     for (map<int, FeatureList>::iterator iter = featureSet.begin();
cannam@0: 00474          iter != featureSet.end(); ++iter) {
cannam@0: 00475         FeatureList featureList = iter->second;
cannam@0: 00476         for (size_t i = 0; i < featureList.size(); ++i) {
cannam@0: 00477             allFeatureSets[iter->first].push_back(featureList[i]);
cannam@0: 00478         }
cannam@0: 00479     }
cannam@0: 00480     
cannam@0: 00481     return allFeatureSets;
cannam@0: 00482 }
cannam@0: 00483     
cannam@0: 00484 void
cannam@0: 00485 PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets)
cannam@0: 00486 {
cannam@0: 00487     for (size_t i = 0; i < m_channels; ++i) {
cannam@0: 00488         m_queue[i]->peek(m_buffers[i], m_blockSize);
cannam@0: 00489     }
cannam@0: 00490 
cannam@0: 00491     long frame = m_frame;
cannam@0: 00492     RealTime timestamp = RealTime::frame2RealTime
cannam@0: 00493         (frame, int(m_inputSampleRate + 0.5));
cannam@0: 00494 
cannam@0: 00495     FeatureSet featureSet = m_plugin->process(m_buffers, timestamp);
cannam@0: 00496     
cannam@0: 00497     for (FeatureSet::iterator iter = featureSet.begin();
cannam@0: 00498          iter != featureSet.end(); ++iter) {
cannam@0: 00499 
cannam@0: 00500         int outputNo = iter->first;
cannam@0: 00501 
cannam@0: 00502         if (m_rewriteOutputTimes[outputNo]) {
cannam@0: 00503             
cannam@0: 00504             FeatureList featureList = iter->second;
cannam@0: 00505         
cannam@0: 00506             for (size_t i = 0; i < featureList.size(); ++i) {
cannam@0: 00507 
cannam@0: 00508                 switch (m_outputs[outputNo].sampleType) {
cannam@0: 00509 
cannam@0: 00510                 case OutputDescriptor::OneSamplePerStep:
cannam@0: 00511                     // use our internal timestamp, always
cannam@0: 00512                     featureList[i].timestamp = timestamp;
cannam@0: 00513                     featureList[i].hasTimestamp = true;
cannam@0: 00514                     break;
cannam@0: 00515 
cannam@0: 00516                 case OutputDescriptor::FixedSampleRate:
cannam@0: 00517                     // use our internal timestamp if feature lacks one
cannam@0: 00518                     if (!featureList[i].hasTimestamp) {
cannam@0: 00519                         featureList[i].timestamp = timestamp;
cannam@0: 00520                         featureList[i].hasTimestamp = true;
cannam@0: 00521                     }
cannam@0: 00522                     break;
cannam@0: 00523 
cannam@0: 00524                 case OutputDescriptor::VariableSampleRate:
cannam@0: 00525                     break;              // plugin must set timestamp
cannam@0: 00526 
cannam@0: 00527                 default:
cannam@0: 00528                     break;
cannam@0: 00529                 }
cannam@0: 00530             
cannam@0: 00531                 allFeatureSets[outputNo].push_back(featureList[i]);
cannam@0: 00532             }
cannam@0: 00533         } else {
cannam@0: 00534             for (size_t i = 0; i < iter->second.size(); ++i) {
cannam@0: 00535                 allFeatureSets[outputNo].push_back(iter->second[i]);
cannam@0: 00536             }
cannam@0: 00537         }
cannam@0: 00538     }
cannam@0: 00539     
cannam@0: 00540     // step forward
cannam@0: 00541 
cannam@0: 00542     for (size_t i = 0; i < m_channels; ++i) {
cannam@0: 00543         m_queue[i]->skip(m_stepSize);
cannam@0: 00544     }
cannam@0: 00545     
cannam@0: 00546     // increment internal frame counter each time we step forward
cannam@0: 00547     m_frame += m_stepSize;
cannam@0: 00548 }
cannam@0: 00549 
cannam@0: 00550 }
cannam@0: 00551         
cannam@0: 00552 }
cannam@0: 00553 
cannam@0: 00554 
cannam@0: 
cannam@0:
Generated on Wed Jul 9 11:36:06 2008 for VampPluginSDK by  cannam@0: cannam@0: doxygen 1.5.5
cannam@0: cannam@0: