svcore
1.9
|
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