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 &transform) :
00034     ModelTransformer(in, transform),
00035     m_plugin(0)
00036 {
00037     m_units = TransformFactory::getInstance()->getTransformUnits
00038         (transform.getIdentifier());
00039     m_outputNo =
00040         (transform.getOutput() == "A") ? -1 : transform.getOutput().toInt();
00041 
00042     QString pluginId = transform.getPluginIdentifier();
00043 
00044     if (!m_transform.getBlockSize()) m_transform.setBlockSize(1024);
00045 
00046 //    std::cerr << "RealTimeEffectModelTransformer::RealTimeEffectModelTransformer: plugin " << pluginId.toStdString() << ", output " << output << std::endl;
00047 
00048     RealTimePluginFactory *factory =
00049         RealTimePluginFactory::instanceFor(pluginId);
00050 
00051     if (!factory) {
00052         std::cerr << "RealTimeEffectModelTransformer: No factory available for plugin id \""
00053                   << pluginId.toStdString() << "\"" << std::endl;
00054         return;
00055     }
00056 
00057     DenseTimeValueModel *input = getConformingInput();
00058     if (!input) return;
00059 
00060     m_plugin = factory->instantiatePlugin(pluginId, 0, 0,
00061                                           input->getSampleRate(),
00062                                           m_transform.getBlockSize(),
00063                                           input->getChannelCount());
00064 
00065     if (!m_plugin) {
00066         std::cerr << "RealTimeEffectModelTransformer: Failed to instantiate plugin \""
00067                   << pluginId.toStdString() << "\"" << std::endl;
00068         return;
00069     }
00070 
00071     TransformFactory::getInstance()->setPluginParameters(m_transform, m_plugin);
00072 
00073     if (m_outputNo >= 0 &&
00074         m_outputNo >= int(m_plugin->getControlOutputCount())) {
00075         std::cerr << "RealTimeEffectModelTransformer: Plugin has fewer than desired " << m_outputNo << " control outputs" << std::endl;
00076         return;
00077     }
00078 
00079     if (m_outputNo == -1) {
00080 
00081         size_t outputChannels = m_plugin->getAudioOutputCount();
00082         if (outputChannels > input->getChannelCount()) {
00083             outputChannels = input->getChannelCount();
00084         }
00085 
00086         WritableWaveFileModel *model = new WritableWaveFileModel
00087             (input->getSampleRate(), outputChannels);
00088 
00089         m_output = model;
00090 
00091     } else {
00092         
00093         SparseTimeValueModel *model = new SparseTimeValueModel
00094             (input->getSampleRate(), m_transform.getBlockSize(), 0.0, 0.0, false);
00095 
00096         if (m_units != "") model->setScaleUnits(m_units);
00097 
00098         m_output = model;
00099     }
00100 }
00101 
00102 RealTimeEffectModelTransformer::~RealTimeEffectModelTransformer()
00103 {
00104     delete m_plugin;
00105 }
00106 
00107 DenseTimeValueModel *
00108 RealTimeEffectModelTransformer::getConformingInput()
00109 {
00110     DenseTimeValueModel *dtvm =
00111         dynamic_cast<DenseTimeValueModel *>(getInputModel());
00112     if (!dtvm) {
00113         std::cerr << "RealTimeEffectModelTransformer::getConformingInput: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl;
00114     }
00115     return dtvm;
00116 }
00117 
00118 void
00119 RealTimeEffectModelTransformer::run()
00120 {
00121     DenseTimeValueModel *input = getConformingInput();
00122     if (!input) return;
00123 
00124     while (!input->isReady()) {
00125         if (dynamic_cast<WaveFileModel *>(input)) break; // no need to wait
00126         std::cerr << "RealTimeEffectModelTransformer::run: Waiting for input model to be ready..." << std::endl;
00127         sleep(1);
00128     }
00129 
00130     SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>(m_output);
00131     WritableWaveFileModel *wwfm = dynamic_cast<WritableWaveFileModel *>(m_output);
00132     if (!stvm && !wwfm) return;
00133 
00134     if (stvm && (m_outputNo >= int(m_plugin->getControlOutputCount()))) return;
00135 
00136     size_t sampleRate = input->getSampleRate();
00137     size_t channelCount = input->getChannelCount();
00138     if (!wwfm && m_input.getChannel() != -1) channelCount = 1;
00139 
00140     long blockSize = m_plugin->getBufferSize();
00141 
00142     float **inbufs = m_plugin->getAudioInputBuffers();
00143 
00144     long startFrame = m_input.getModel()->getStartFrame();
00145     long   endFrame = m_input.getModel()->getEndFrame();
00146     
00147     RealTime contextStartRT = m_transform.getStartTime();
00148     RealTime contextDurationRT = m_transform.getDuration();
00149 
00150     long contextStart =
00151         RealTime::realTime2Frame(contextStartRT, sampleRate);
00152 
00153     long contextDuration =
00154         RealTime::realTime2Frame(contextDurationRT, sampleRate);
00155 
00156     if (contextStart == 0 || contextStart < startFrame) {
00157         contextStart = startFrame;
00158     }
00159 
00160     if (contextDuration == 0) {
00161         contextDuration = endFrame - contextStart;
00162     }
00163     if (contextStart + contextDuration > endFrame) {
00164         contextDuration = endFrame - contextStart;
00165     }
00166 
00167     wwfm->setStartFrame(contextStart);
00168 
00169     long blockFrame = contextStart;
00170 
00171     long prevCompletion = 0;
00172 
00173     long latency = m_plugin->getLatency();
00174 
00175     while (blockFrame < contextStart + contextDuration + latency &&
00176            !m_abandoned) {
00177 
00178         long completion =
00179             (((blockFrame - contextStart) / blockSize) * 99) /
00180             ((contextDuration) / blockSize);
00181 
00182         long got = 0;
00183 
00184         if (channelCount == 1) {
00185             if (inbufs && inbufs[0]) {
00186                 got = input->getData
00187                     (m_input.getChannel(), blockFrame, blockSize, inbufs[0]);
00188                 while (got < blockSize) {
00189                     inbufs[0][got++] = 0.0;
00190                 }          
00191             }
00192             for (size_t ch = 1; ch < m_plugin->getAudioInputCount(); ++ch) {
00193                 for (long i = 0; i < blockSize; ++i) {
00194                     inbufs[ch][i] = inbufs[0][i];
00195                 }
00196             }
00197         } else {
00198             got = input->getData(0, channelCount - 1,
00199                                  blockFrame, blockSize,
00200                                  inbufs);
00201             while (got < blockSize) {
00202                 for (size_t ch = 0; ch < channelCount; ++ch) {
00203                     inbufs[ch][got] = 0.0;
00204                 }
00205                 ++got;
00206             }
00207             for (size_t ch = channelCount; ch < m_plugin->getAudioInputCount(); ++ch) {
00208                 for (long i = 0; i < blockSize; ++i) {
00209                     inbufs[ch][i] = inbufs[ch % channelCount][i];
00210                 }
00211             }
00212         }
00213 
00214 /*
00215         std::cerr << "Input for plugin: " << m_plugin->getAudioInputCount() << " channels "<< std::endl;
00216 
00217         for (size_t ch = 0; ch < m_plugin->getAudioInputCount(); ++ch) {
00218             std::cerr << "Input channel " << ch << std::endl;
00219             for (size_t i = 0; i < 100; ++i) {
00220                 std::cerr << inbufs[ch][i] << " ";
00221                 if (isnan(inbufs[ch][i])) {
00222                     std::cerr << "\n\nWARNING: NaN in audio input" << std::endl;
00223                 }
00224             }
00225         }
00226 */
00227 
00228         m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
00229 
00230         if (stvm) {
00231 
00232             float value = m_plugin->getControlOutputValue(m_outputNo);
00233 
00234             long pointFrame = blockFrame;
00235             if (pointFrame > latency) pointFrame -= latency;
00236             else pointFrame = 0;
00237 
00238             stvm->addPoint(SparseTimeValueModel::Point
00239                            (pointFrame, value, ""));
00240 
00241         } else if (wwfm) {
00242 
00243             float **outbufs = m_plugin->getAudioOutputBuffers();
00244 
00245             if (outbufs) {
00246 
00247                 if (blockFrame >= latency) {
00248                     long writeSize = std::min
00249                         (blockSize,
00250                          contextStart + contextDuration + latency - blockFrame);
00251                     wwfm->addSamples(outbufs, writeSize);
00252                 } else if (blockFrame + blockSize >= latency) {
00253                     long offset = latency - blockFrame;
00254                     long count = blockSize - offset;
00255                     float **tmp = new float *[channelCount];
00256                     for (size_t c = 0; c < channelCount; ++c) {
00257                         tmp[c] = outbufs[c] + offset;
00258                     }
00259                     wwfm->addSamples(tmp, count);
00260                     delete[] tmp;
00261                 }
00262             }
00263         }
00264 
00265         if (blockFrame == contextStart || completion > prevCompletion) {
00266             if (stvm) stvm->setCompletion(completion);
00267             if (wwfm) wwfm->setCompletion(completion);
00268             prevCompletion = completion;
00269         }
00270         
00271         blockFrame += blockSize;
00272     }
00273 
00274     if (m_abandoned) return;
00275     
00276     if (stvm) stvm->setCompletion(100);
00277     if (wwfm) wwfm->setCompletion(100);
00278 }
00279 

Generated on Wed Feb 20 15:45:27 2008 for SonicVisualiser by  doxygen 1.5.1