comparison transform/RealTimePluginTransform.cpp @ 110:d25ea0c2af5c

* Fix real-time plugin corruption when getLatency is called for some plugins * Other minor changes
author Chris Cannam
date Thu, 01 Mar 2007 15:35:27 +0000
parents bedc7517b6e8
children b4110b17bca8
comparison
equal deleted inserted replaced
109:e6c4b27cba2c 110:d25ea0c2af5c
32 const ExecutionContext &context, 32 const ExecutionContext &context,
33 QString configurationXml, 33 QString configurationXml,
34 QString units, 34 QString units,
35 int output) : 35 int output) :
36 PluginTransform(inputModel, context), 36 PluginTransform(inputModel, context),
37 m_pluginId(pluginId),
38 m_configurationXml(configurationXml),
39 m_units(units),
37 m_plugin(0), 40 m_plugin(0),
38 m_outputNo(output) 41 m_outputNo(output)
39 { 42 {
40 if (!m_context.blockSize) m_context.blockSize = 1024; 43 if (!m_context.blockSize) m_context.blockSize = 1024;
41 44
118 DenseTimeValueModel *input = getInput(); 121 DenseTimeValueModel *input = getInput();
119 if (!input) return; 122 if (!input) return;
120 123
121 while (!input->isReady()) { 124 while (!input->isReady()) {
122 if (dynamic_cast<WaveFileModel *>(input)) break; // no need to wait 125 if (dynamic_cast<WaveFileModel *>(input)) break; // no need to wait
123 std::cerr << "FeatureExtractionPluginTransform::run: Waiting for input model to be ready..." << std::endl; 126 std::cerr << "RealTimePluginTransform::run: Waiting for input model to be ready..." << std::endl;
124 sleep(1); 127 sleep(1);
125 } 128 }
126 129
127 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>(m_output); 130 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *>(m_output);
128 WritableWaveFileModel *wwfm = dynamic_cast<WritableWaveFileModel *>(m_output); 131 WritableWaveFileModel *wwfm = dynamic_cast<WritableWaveFileModel *>(m_output);
134 int channelCount = input->getChannelCount(); 137 int channelCount = input->getChannelCount();
135 if (!wwfm && m_context.channel != -1) channelCount = 1; 138 if (!wwfm && m_context.channel != -1) channelCount = 1;
136 139
137 size_t blockSize = m_plugin->getBufferSize(); 140 size_t blockSize = m_plugin->getBufferSize();
138 141
139 float **buffers = m_plugin->getAudioInputBuffers(); 142 float **inbufs = m_plugin->getAudioInputBuffers();
140 143
141 size_t startFrame = m_input->getStartFrame(); 144 size_t startFrame = m_input->getStartFrame();
142 size_t endFrame = m_input->getEndFrame(); 145 size_t endFrame = m_input->getEndFrame();
143 size_t blockFrame = startFrame; 146 size_t blockFrame = startFrame;
144 147
155 ( (endFrame - startFrame) / blockSize); 158 ( (endFrame - startFrame) / blockSize);
156 159
157 size_t got = 0; 160 size_t got = 0;
158 161
159 if (channelCount == 1) { 162 if (channelCount == 1) {
160 if (buffers && buffers[0]) { 163 if (inbufs && inbufs[0]) {
161 got = input->getValues 164 got = input->getValues
162 (m_context.channel, blockFrame, blockFrame + blockSize, buffers[0]); 165 (m_context.channel, blockFrame, blockFrame + blockSize, inbufs[0]);
163 while (got < blockSize) { 166 while (got < blockSize) {
164 buffers[0][got++] = 0.0; 167 inbufs[0][got++] = 0.0;
165 } 168 }
166 if (m_context.channel == -1 && channelCount > 1) { 169 }
167 // use mean instead of sum, as plugin input 170 for (size_t ch = 1; ch < m_plugin->getAudioInputCount(); ++ch) {
168 for (size_t i = 0; i < got; ++i) { 171 for (size_t i = 0; i < blockSize; ++i) {
169 buffers[0][i] /= channelCount; 172 inbufs[ch][i] = inbufs[0][i];
170 } 173 }
171 }
172 } 174 }
173 } else { 175 } else {
174 for (size_t ch = 0; ch < channelCount; ++ch) { 176 for (size_t ch = 0; ch < channelCount; ++ch) {
175 if (buffers && buffers[ch]) { 177 if (inbufs && inbufs[ch]) {
176 got = input->getValues 178 got = input->getValues
177 (ch, blockFrame, blockFrame + blockSize, buffers[ch]); 179 (ch, blockFrame, blockFrame + blockSize, inbufs[ch]);
178 while (got < blockSize) { 180 while (got < blockSize) {
179 buffers[ch][got++] = 0.0; 181 inbufs[ch][got++] = 0.0;
180 } 182 }
181 } 183 }
182 } 184 }
185 for (size_t ch = channelCount; ch < m_plugin->getAudioInputCount(); ++ch) {
186 for (size_t i = 0; i < blockSize; ++i) {
187 inbufs[ch][i] = inbufs[ch % channelCount][i];
188 }
189 }
183 } 190 }
191
192 /*
193 std::cerr << "Input for plugin: " << m_plugin->getAudioInputCount() << " channels "<< std::endl;
194
195 for (size_t ch = 0; ch < m_plugin->getAudioInputCount(); ++ch) {
196 std::cerr << "Input channel " << ch << std::endl;
197 for (size_t i = 0; i < 100; ++i) {
198 std::cerr << inbufs[ch][i] << " ";
199 if (isnan(inbufs[ch][i])) {
200 std::cerr << "\n\nWARNING: NaN in audio input" << std::endl;
201 }
202 }
203 }
204 */
184 205
185 m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate)); 206 m_plugin->run(Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
186 207
187 if (stvm) { 208 if (stvm) {
188 209
195 stvm->addPoint(SparseTimeValueModel::Point 216 stvm->addPoint(SparseTimeValueModel::Point
196 (pointFrame, value, "")); 217 (pointFrame, value, ""));
197 218
198 } else if (wwfm) { 219 } else if (wwfm) {
199 220
200 float **buffers = m_plugin->getAudioOutputBuffers(); 221 float **outbufs = m_plugin->getAudioOutputBuffers();
201 222
202 if (buffers) { 223 if (outbufs) {
203 224
204 if (blockFrame >= latency) { 225 if (blockFrame >= latency) {
205 wwfm->addSamples(buffers, blockSize); 226 wwfm->addSamples(outbufs, blockSize);
206 } else if (blockFrame + blockSize >= latency) { 227 } else if (blockFrame + blockSize >= latency) {
207 size_t offset = latency - blockFrame; 228 size_t offset = latency - blockFrame;
208 size_t count = blockSize - offset; 229 size_t count = blockSize - offset;
209 float **tmp = new float *[channelCount]; 230 float **tmp = new float *[channelCount];
210 for (size_t c = 0; c < channelCount; ++c) { 231 for (size_t c = 0; c < channelCount; ++c) {
211 tmp[c] = buffers[c] + offset; 232 tmp[c] = outbufs[c] + offset;
212 } 233 }
213 wwfm->addSamples(tmp, count); 234 wwfm->addSamples(tmp, count);
214 delete[] tmp; 235 delete[] tmp;
215 } 236 }
216 } 237 }