svcore  1.9
RealTimeEffectModelTransformer.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: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "RealTimeEffectModelTransformer.h"
00017 
00018 #include "plugin/RealTimePluginFactory.h"
00019 #include "plugin/RealTimePluginInstance.h"
00020 #include "plugin/PluginXml.h"
00021 
00022 #include "data/model/Model.h"
00023 #include "data/model/SparseTimeValueModel.h"
00024 #include "data/model/DenseTimeValueModel.h"
00025 #include "data/model/WritableWaveFileModel.h"
00026 #include "data/model/WaveFileModel.h"
00027 
00028 #include "TransformFactory.h"
00029 
00030 #include <iostream>
00031 
00032 RealTimeEffectModelTransformer::RealTimeEffectModelTransformer(Input in,
00033                                                                const Transform &t) :
00034     ModelTransformer(in, t),
00035     m_plugin(0)
00036 {
00037     Transform transform(t);
00038     if (!transform.getBlockSize()) {
00039         transform.setBlockSize(1024);
00040         m_transforms[0] = transform;
00041     }
00042 
00043     m_units = TransformFactory::getInstance()->getTransformUnits
00044         (transform.getIdentifier());
00045     m_outputNo =
00046         (transform.getOutput() == "A") ? -1 : transform.getOutput().toInt();
00047 
00048     QString pluginId = transform.getPluginIdentifier();
00049 
00050 //    SVDEBUG << "RealTimeEffectModelTransformer::RealTimeEffectModelTransformer: plugin " << pluginId << ", output " << output << endl;
00051 
00052     RealTimePluginFactory *factory =
00053         RealTimePluginFactory::instanceFor(pluginId);
00054 
00055     if (!factory) {
00056         cerr << "RealTimeEffectModelTransformer: No factory available for plugin id \""
00057                   << pluginId << "\"" << endl;
00058         return;
00059     }
00060 
00061     DenseTimeValueModel *input = getConformingInput();
00062     if (!input) return;
00063 
00064     m_plugin = factory->instantiatePlugin(pluginId, 0, 0,
00065                                           input->getSampleRate(),
00066                                           transform.getBlockSize(),
00067                                           input->getChannelCount());
00068 
00069     if (!m_plugin) {
00070         cerr << "RealTimeEffectModelTransformer: Failed to instantiate plugin \""
00071              << pluginId << "\"" << endl;
00072         return;
00073     }
00074 
00075     TransformFactory::getInstance()->setPluginParameters(transform, m_plugin);
00076 
00077     if (m_outputNo >= 0 &&
00078         m_outputNo >= int(m_plugin->getControlOutputCount())) {
00079         cerr << "RealTimeEffectModelTransformer: Plugin has fewer than desired " << m_outputNo << " control outputs" << endl;
00080         return;
00081     }
00082 
00083     if (m_outputNo == -1) {
00084 
00085         int outputChannels = m_plugin->getAudioOutputCount();
00086         if (outputChannels > input->getChannelCount()) {
00087             outputChannels = input->getChannelCount();
00088         }
00089 
00090         WritableWaveFileModel *model = new WritableWaveFileModel
00091             (input->getSampleRate(), outputChannels);
00092 
00093         m_outputs.push_back(model);
00094 
00095     } else {
00096         
00097         SparseTimeValueModel *model = new SparseTimeValueModel
00098             (input->getSampleRate(), transform.getBlockSize(), 0.0, 0.0, false);
00099 
00100         if (m_units != "") model->setScaleUnits(m_units);
00101 
00102         m_outputs.push_back(model);
00103     }
00104 }
00105 
00106 RealTimeEffectModelTransformer::~RealTimeEffectModelTransformer()
00107 {
00108     delete m_plugin;
00109 }
00110 
00111 DenseTimeValueModel *
00112 RealTimeEffectModelTransformer::getConformingInput()
00113 {
00114     DenseTimeValueModel *dtvm =
00115         dynamic_cast<DenseTimeValueModel *>(getInputModel());
00116     if (!dtvm) {
00117         SVDEBUG << "RealTimeEffectModelTransformer::getConformingInput: WARNING: Input model is not conformable to DenseTimeValueModel" << endl;
00118     }
00119     return dtvm;
00120 }
00121 
00122 void
00123 RealTimeEffectModelTransformer::run()
00124 {
00125     DenseTimeValueModel *input = getConformingInput();
00126     if (!input) return;
00127 
00128     while (!input->isReady() && !m_abandoned) {
00129         SVDEBUG << "RealTimeEffectModelTransformer::run: Waiting for input model to be ready..." << endl;
00130         usleep(500000);
00131     }
00132     if (m_abandoned) return;
00133 
00134     SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>(m_outputs[0]);
00135     WritableWaveFileModel *wwfm = dynamic_cast<WritableWaveFileModel *>(m_outputs[0]);
00136     if (!stvm && !wwfm) return;
00137 
00138     if (stvm && (m_outputNo >= int(m_plugin->getControlOutputCount()))) return;
00139 
00140     int sampleRate = input->getSampleRate();
00141     int channelCount = input->getChannelCount();
00142     if (!wwfm && m_input.getChannel() != -1) channelCount = 1;
00143 
00144     long blockSize = m_plugin->getBufferSize();
00145 
00146     float **inbufs = m_plugin->getAudioInputBuffers();
00147 
00148     long startFrame = m_input.getModel()->getStartFrame();
00149     long   endFrame = m_input.getModel()->getEndFrame();
00150 
00151     Transform transform = m_transforms[0];
00152     
00153     RealTime contextStartRT = transform.getStartTime();
00154     RealTime contextDurationRT = transform.getDuration();
00155 
00156     long contextStart =
00157         RealTime::realTime2Frame(contextStartRT, sampleRate);
00158 
00159     long contextDuration =
00160         RealTime::realTime2Frame(contextDurationRT, sampleRate);
00161 
00162     if (contextStart == 0 || contextStart < startFrame) {
00163         contextStart = startFrame;
00164     }
00165 
00166     if (contextDuration == 0) {
00167         contextDuration = endFrame - contextStart;
00168     }
00169     if (contextStart + contextDuration > endFrame) {
00170         contextDuration = endFrame - contextStart;
00171     }
00172 
00173     if (wwfm) {
00174         wwfm->setStartFrame(contextStart);
00175     }
00176 
00177     long blockFrame = contextStart;
00178 
00179     long prevCompletion = 0;
00180 
00181     long latency = m_plugin->getLatency();
00182 
00183     while (blockFrame < contextStart + contextDuration + latency &&
00184            !m_abandoned) {
00185 
00186         long completion =
00187             (((blockFrame - contextStart) / blockSize) * 99) /
00188             (1 + ((contextDuration) / blockSize));
00189 
00190         long got = 0;
00191 
00192         if (channelCount == 1) {
00193             if (inbufs && inbufs[0]) {
00194                 got = input->getData
00195                     (m_input.getChannel(), blockFrame, blockSize, inbufs[0]);
00196                 while (got < blockSize) {
00197                     inbufs[0][got++] = 0.0;
00198                 }          
00199                 for (int ch = 1; ch < (int)m_plugin->getAudioInputCount(); ++ch) {
00200                     for (long i = 0; i < blockSize; ++i) {
00201                         inbufs[ch][i] = inbufs[0][i];
00202                     }
00203                 }
00204             }
00205         } else {
00206             if (inbufs && inbufs[0]) {
00207                 got = input->getData(0, channelCount - 1,
00208                                      blockFrame, blockSize,
00209                                      inbufs);
00210                 while (got < blockSize) {
00211                     for (int ch = 0; ch < channelCount; ++ch) {
00212                         inbufs[ch][got] = 0.0;
00213                     }
00214                     ++got;
00215                 }
00216                 for (int ch = channelCount; ch < (int)m_plugin->getAudioInputCount(); ++ch) {
00217                     for (long i = 0; i < blockSize; ++i) {
00218                         inbufs[ch][i] = inbufs[ch % channelCount][i];
00219                     }
00220                 }
00221             }
00222         }
00223 
00224 /*
00225         cerr << "Input for plugin: " << m_plugin->getAudioInputCount() << " channels "<< endl;
00226 
00227         for (int ch = 0; ch < m_plugin->getAudioInputCount(); ++ch) {
00228             cerr << "Input channel " << ch << endl;
00229             for (int i = 0; i < 100; ++i) {
00230                 cerr << inbufs[ch][i] << " ";
00231                 if (isnan(inbufs[ch][i])) {
00232                     cerr << "\n\nWARNING: NaN in audio input" << endl;
00233                 }
00234             }
00235         }
00236 */
00237 
00238         m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
00239 
00240         if (stvm) {
00241 
00242             float value = m_plugin->getControlOutputValue(m_outputNo);
00243 
00244             long pointFrame = blockFrame;
00245             if (pointFrame > latency) pointFrame -= latency;
00246             else pointFrame = 0;
00247 
00248             stvm->addPoint(SparseTimeValueModel::Point
00249                            (pointFrame, value, ""));
00250 
00251         } else if (wwfm) {
00252 
00253             float **outbufs = m_plugin->getAudioOutputBuffers();
00254 
00255             if (outbufs) {
00256 
00257                 if (blockFrame >= latency) {
00258                     long writeSize = std::min
00259                         (blockSize,
00260                          contextStart + contextDuration + latency - blockFrame);
00261                     wwfm->addSamples(outbufs, writeSize);
00262                 } else if (blockFrame + blockSize >= latency) {
00263                     long offset = latency - blockFrame;
00264                     long count = blockSize - offset;
00265                     float **tmp = new float *[channelCount];
00266                     for (int c = 0; c < channelCount; ++c) {
00267                         tmp[c] = outbufs[c] + offset;
00268                     }
00269                     wwfm->addSamples(tmp, count);
00270                     delete[] tmp;
00271                 }
00272             }
00273         }
00274 
00275         if (blockFrame == contextStart || completion > prevCompletion) {
00276             if (stvm) stvm->setCompletion(completion);
00277             if (wwfm) wwfm->setCompletion(completion);
00278             prevCompletion = completion;
00279         }
00280         
00281         blockFrame += blockSize;
00282     }
00283 
00284     if (m_abandoned) return;
00285     
00286     if (stvm) stvm->setCompletion(100);
00287     if (wwfm) wwfm->setCompletion(100);
00288 }
00289