Mercurial > hg > svcore
comparison transform/FeatureExtractionModelTransformer.cpp @ 874:862fe7b20df7 tony_integration
Merge from tonioni branch
author | Chris Cannam |
---|---|
date | Tue, 28 Jan 2014 15:01:54 +0000 |
parents | 786ee8d1f30e 13803edd513d |
children | 4cbf8c6a462d |
comparison
equal
deleted
inserted
replaced
862:786ee8d1f30e | 874:862fe7b20df7 |
---|---|
25 #include "data/model/SparseOneDimensionalModel.h" | 25 #include "data/model/SparseOneDimensionalModel.h" |
26 #include "data/model/SparseTimeValueModel.h" | 26 #include "data/model/SparseTimeValueModel.h" |
27 #include "data/model/EditableDenseThreeDimensionalModel.h" | 27 #include "data/model/EditableDenseThreeDimensionalModel.h" |
28 #include "data/model/DenseTimeValueModel.h" | 28 #include "data/model/DenseTimeValueModel.h" |
29 #include "data/model/NoteModel.h" | 29 #include "data/model/NoteModel.h" |
30 #include "data/model/FlexiNoteModel.h" | |
30 #include "data/model/RegionModel.h" | 31 #include "data/model/RegionModel.h" |
31 #include "data/model/FFTModel.h" | 32 #include "data/model/FFTModel.h" |
32 #include "data/model/WaveFileModel.h" | 33 #include "data/model/WaveFileModel.h" |
33 #include "rdf/PluginRDFDescription.h" | 34 #include "rdf/PluginRDFDescription.h" |
34 | 35 |
35 #include "TransformFactory.h" | 36 #include "TransformFactory.h" |
36 | 37 |
37 #include <iostream> | 38 #include <iostream> |
38 | 39 |
40 #include <QSettings> | |
41 | |
39 FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in, | 42 FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in, |
40 const Transform &transform) : | 43 const Transform &transform) : |
41 ModelTransformer(in, transform), | 44 ModelTransformer(in, transform), |
42 m_plugin(0), | 45 m_plugin(0) |
43 m_descriptor(0), | |
44 m_outputNo(0), | |
45 m_fixedRateFeatureNo(-1) // we increment before use | |
46 { | 46 { |
47 // SVDEBUG << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: plugin " << pluginId << ", outputName " << m_transform.getOutput() << endl; | 47 // SVDEBUG << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: plugin " << pluginId << ", outputName " << m_transform.getOutput() << endl; |
48 | 48 |
49 QString pluginId = transform.getPluginIdentifier(); | 49 initialise(); |
50 } | |
51 | |
52 FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in, | |
53 const Transforms &transforms) : | |
54 ModelTransformer(in, transforms), | |
55 m_plugin(0) | |
56 { | |
57 // SVDEBUG << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: plugin " << pluginId << ", outputName " << m_transform.getOutput() << endl; | |
58 | |
59 initialise(); | |
60 } | |
61 | |
62 static bool | |
63 areTransformsSimilar(const Transform &t1, const Transform &t2) | |
64 { | |
65 Transform t2o(t2); | |
66 t2o.setOutput(t1.getOutput()); | |
67 return t1 == t2o; | |
68 } | |
69 | |
70 bool | |
71 FeatureExtractionModelTransformer::initialise() | |
72 { | |
73 // All transforms must use the same plugin, parameters, and | |
74 // inputs: they can differ only in choice of plugin output. So we | |
75 // initialise based purely on the first transform in the list (but | |
76 // first check that they are actually similar as promised) | |
77 | |
78 for (int j = 1; j < (int)m_transforms.size(); ++j) { | |
79 if (!areTransformsSimilar(m_transforms[0], m_transforms[j])) { | |
80 m_message = tr("Transforms supplied to a single FeatureExtractionModelTransformer instance must be similar in every respect except plugin output"); | |
81 return false; | |
82 } | |
83 } | |
84 | |
85 Transform primaryTransform = m_transforms[0]; | |
86 | |
87 QString pluginId = primaryTransform.getPluginIdentifier(); | |
50 | 88 |
51 FeatureExtractionPluginFactory *factory = | 89 FeatureExtractionPluginFactory *factory = |
52 FeatureExtractionPluginFactory::instanceFor(pluginId); | 90 FeatureExtractionPluginFactory::instanceFor(pluginId); |
53 | 91 |
54 if (!factory) { | 92 if (!factory) { |
55 m_message = tr("No factory available for feature extraction plugin id \"%1\" (unknown plugin type, or internal error?)").arg(pluginId); | 93 m_message = tr("No factory available for feature extraction plugin id \"%1\" (unknown plugin type, or internal error?)").arg(pluginId); |
56 return; | 94 return false; |
57 } | 95 } |
58 | 96 |
59 DenseTimeValueModel *input = getConformingInput(); | 97 DenseTimeValueModel *input = getConformingInput(); |
60 if (!input) { | 98 if (!input) { |
61 m_message = tr("Input model for feature extraction plugin \"%1\" is of wrong type (internal error?)").arg(pluginId); | 99 m_message = tr("Input model for feature extraction plugin \"%1\" is of wrong type (internal error?)").arg(pluginId); |
62 return; | 100 return false; |
63 } | 101 } |
64 | 102 |
65 m_plugin = factory->instantiatePlugin(pluginId, input->getSampleRate()); | 103 m_plugin = factory->instantiatePlugin(pluginId, input->getSampleRate()); |
66 if (!m_plugin) { | 104 if (!m_plugin) { |
67 m_message = tr("Failed to instantiate plugin \"%1\"").arg(pluginId); | 105 m_message = tr("Failed to instantiate plugin \"%1\"").arg(pluginId); |
68 return; | 106 return false; |
69 } | 107 } |
70 | 108 |
71 TransformFactory::getInstance()->makeContextConsistentWithPlugin | 109 TransformFactory::getInstance()->makeContextConsistentWithPlugin |
72 (m_transform, m_plugin); | 110 (primaryTransform, m_plugin); |
73 | 111 |
74 TransformFactory::getInstance()->setPluginParameters | 112 TransformFactory::getInstance()->setPluginParameters |
75 (m_transform, m_plugin); | 113 (primaryTransform, m_plugin); |
76 | 114 |
77 size_t channelCount = input->getChannelCount(); | 115 size_t channelCount = input->getChannelCount(); |
78 if (m_plugin->getMaxChannelCount() < channelCount) { | 116 if (m_plugin->getMaxChannelCount() < channelCount) { |
79 channelCount = 1; | 117 channelCount = 1; |
80 } | 118 } |
82 m_message = tr("Cannot provide enough channels to feature extraction plugin \"%1\" (plugin min is %2, max %3; input model has %4)") | 120 m_message = tr("Cannot provide enough channels to feature extraction plugin \"%1\" (plugin min is %2, max %3; input model has %4)") |
83 .arg(pluginId) | 121 .arg(pluginId) |
84 .arg(m_plugin->getMinChannelCount()) | 122 .arg(m_plugin->getMinChannelCount()) |
85 .arg(m_plugin->getMaxChannelCount()) | 123 .arg(m_plugin->getMaxChannelCount()) |
86 .arg(input->getChannelCount()); | 124 .arg(input->getChannelCount()); |
87 return; | 125 return false; |
88 } | 126 } |
89 | 127 |
90 SVDEBUG << "Initialising feature extraction plugin with channels = " | 128 SVDEBUG << "Initialising feature extraction plugin with channels = " |
91 << channelCount << ", step = " << m_transform.getStepSize() | 129 << channelCount << ", step = " << primaryTransform.getStepSize() |
92 << ", block = " << m_transform.getBlockSize() << endl; | 130 << ", block = " << primaryTransform.getBlockSize() << endl; |
93 | 131 |
94 if (!m_plugin->initialise(channelCount, | 132 if (!m_plugin->initialise(channelCount, |
95 m_transform.getStepSize(), | 133 primaryTransform.getStepSize(), |
96 m_transform.getBlockSize())) { | 134 primaryTransform.getBlockSize())) { |
97 | 135 |
98 size_t pstep = m_transform.getStepSize(); | 136 size_t pstep = primaryTransform.getStepSize(); |
99 size_t pblock = m_transform.getBlockSize(); | 137 size_t pblock = primaryTransform.getBlockSize(); |
100 | 138 |
101 m_transform.setStepSize(0); | 139 ///!!! hang on, this isn't right -- we're modifying a copy |
102 m_transform.setBlockSize(0); | 140 primaryTransform.setStepSize(0); |
141 primaryTransform.setBlockSize(0); | |
103 TransformFactory::getInstance()->makeContextConsistentWithPlugin | 142 TransformFactory::getInstance()->makeContextConsistentWithPlugin |
104 (m_transform, m_plugin); | 143 (primaryTransform, m_plugin); |
105 | 144 |
106 if (m_transform.getStepSize() != pstep || | 145 if (primaryTransform.getStepSize() != pstep || |
107 m_transform.getBlockSize() != pblock) { | 146 primaryTransform.getBlockSize() != pblock) { |
108 | 147 |
109 if (!m_plugin->initialise(channelCount, | 148 if (!m_plugin->initialise(channelCount, |
110 m_transform.getStepSize(), | 149 primaryTransform.getStepSize(), |
111 m_transform.getBlockSize())) { | 150 primaryTransform.getBlockSize())) { |
112 | 151 |
113 m_message = tr("Failed to initialise feature extraction plugin \"%1\"").arg(pluginId); | 152 m_message = tr("Failed to initialise feature extraction plugin \"%1\"").arg(pluginId); |
114 return; | 153 return false; |
115 | 154 |
116 } else { | 155 } else { |
117 | 156 |
118 m_message = tr("Feature extraction plugin \"%1\" rejected the given step and block sizes (%2 and %3); using plugin defaults (%4 and %5) instead") | 157 m_message = tr("Feature extraction plugin \"%1\" rejected the given step and block sizes (%2 and %3); using plugin defaults (%4 and %5) instead") |
119 .arg(pluginId) | 158 .arg(pluginId) |
120 .arg(pstep) | 159 .arg(pstep) |
121 .arg(pblock) | 160 .arg(pblock) |
122 .arg(m_transform.getStepSize()) | 161 .arg(primaryTransform.getStepSize()) |
123 .arg(m_transform.getBlockSize()); | 162 .arg(primaryTransform.getBlockSize()); |
124 } | 163 } |
125 | 164 |
126 } else { | 165 } else { |
127 | 166 |
128 m_message = tr("Failed to initialise feature extraction plugin \"%1\"").arg(pluginId); | 167 m_message = tr("Failed to initialise feature extraction plugin \"%1\"").arg(pluginId); |
129 return; | 168 return false; |
130 } | 169 } |
131 } | 170 } |
132 | 171 |
133 if (m_transform.getPluginVersion() != "") { | 172 if (primaryTransform.getPluginVersion() != "") { |
134 QString pv = QString("%1").arg(m_plugin->getPluginVersion()); | 173 QString pv = QString("%1").arg(m_plugin->getPluginVersion()); |
135 if (pv != m_transform.getPluginVersion()) { | 174 if (pv != primaryTransform.getPluginVersion()) { |
136 QString vm = tr("Transform was configured for version %1 of plugin \"%2\", but the plugin being used is version %3") | 175 QString vm = tr("Transform was configured for version %1 of plugin \"%2\", but the plugin being used is version %3") |
137 .arg(m_transform.getPluginVersion()) | 176 .arg(primaryTransform.getPluginVersion()) |
138 .arg(pluginId) | 177 .arg(pluginId) |
139 .arg(pv); | 178 .arg(pv); |
140 if (m_message != "") { | 179 if (m_message != "") { |
141 m_message = QString("%1; %2").arg(vm).arg(m_message); | 180 m_message = QString("%1; %2").arg(vm).arg(m_message); |
142 } else { | 181 } else { |
147 | 186 |
148 Vamp::Plugin::OutputList outputs = m_plugin->getOutputDescriptors(); | 187 Vamp::Plugin::OutputList outputs = m_plugin->getOutputDescriptors(); |
149 | 188 |
150 if (outputs.empty()) { | 189 if (outputs.empty()) { |
151 m_message = tr("Plugin \"%1\" has no outputs").arg(pluginId); | 190 m_message = tr("Plugin \"%1\" has no outputs").arg(pluginId); |
152 return; | 191 return false; |
153 } | 192 } |
154 | 193 |
155 for (size_t i = 0; i < outputs.size(); ++i) { | 194 for (int j = 0; j < (int)m_transforms.size(); ++j) { |
195 | |
196 for (int i = 0; i < (int)outputs.size(); ++i) { | |
156 // SVDEBUG << "comparing output " << i << " name \"" << outputs[i].identifier << "\" with expected \"" << m_transform.getOutput() << "\"" << endl; | 197 // SVDEBUG << "comparing output " << i << " name \"" << outputs[i].identifier << "\" with expected \"" << m_transform.getOutput() << "\"" << endl; |
157 if (m_transform.getOutput() == "" || | 198 if (m_transforms[j].getOutput() == "" || |
158 outputs[i].identifier == m_transform.getOutput().toStdString()) { | 199 outputs[i].identifier == m_transforms[j].getOutput().toStdString()) { |
159 m_outputNo = i; | 200 m_outputNos.push_back(i); |
160 m_descriptor = new Vamp::Plugin::OutputDescriptor(outputs[i]); | 201 m_descriptors.push_back(new Vamp::Plugin::OutputDescriptor(outputs[i])); |
161 break; | 202 m_fixedRateFeatureNos.push_back(-1); // we increment before use |
162 } | 203 break; |
163 } | 204 } |
164 | 205 } |
165 if (!m_descriptor) { | 206 |
166 m_message = tr("Plugin \"%1\" has no output named \"%2\"") | 207 if (m_descriptors.size() <= j) { |
167 .arg(pluginId) | 208 m_message = tr("Plugin \"%1\" has no output named \"%2\"") |
168 .arg(m_transform.getOutput()); | 209 .arg(pluginId) |
169 return; | 210 .arg(m_transforms[j].getOutput()); |
170 } | 211 return false; |
171 | 212 } |
172 createOutputModel(); | 213 } |
214 | |
215 for (int j = 0; j < (int)m_transforms.size(); ++j) { | |
216 createOutputModel(j); | |
217 } | |
218 | |
219 return true; | |
173 } | 220 } |
174 | 221 |
175 void | 222 void |
176 FeatureExtractionModelTransformer::createOutputModel() | 223 FeatureExtractionModelTransformer::createOutputModel(int n) |
177 { | 224 { |
178 DenseTimeValueModel *input = getConformingInput(); | 225 DenseTimeValueModel *input = getConformingInput(); |
179 | 226 |
180 // cerr << "FeatureExtractionModelTransformer::createOutputModel: sample type " << m_descriptor->sampleType << ", rate " << m_descriptor->sampleRate << endl; | 227 // cerr << "FeatureExtractionModelTransformer::createOutputModel: sample type " << m_descriptor->sampleType << ", rate " << m_descriptor->sampleRate << endl; |
181 | 228 |
182 PluginRDFDescription description(m_transform.getPluginIdentifier()); | 229 PluginRDFDescription description(m_transforms[n].getPluginIdentifier()); |
183 QString outputId = m_transform.getOutput(); | 230 QString outputId = m_transforms[n].getOutput(); |
184 | 231 |
185 int binCount = 1; | 232 int binCount = 1; |
186 float minValue = 0.0, maxValue = 0.0; | 233 float minValue = 0.0, maxValue = 0.0; |
187 bool haveExtents = false; | 234 bool haveExtents = false; |
188 | 235 |
189 if (m_descriptor->hasFixedBinCount) { | 236 if (m_descriptors[n]->hasFixedBinCount) { |
190 binCount = m_descriptor->binCount; | 237 binCount = m_descriptors[n]->binCount; |
191 } | 238 } |
192 | 239 |
193 // cerr << "FeatureExtractionModelTransformer: output bin count " | 240 // cerr << "FeatureExtractionModelTransformer: output bin count " |
194 // << binCount << endl; | 241 // << binCount << endl; |
195 | 242 |
196 if (binCount > 0 && m_descriptor->hasKnownExtents) { | 243 if (binCount > 0 && m_descriptors[n]->hasKnownExtents) { |
197 minValue = m_descriptor->minValue; | 244 minValue = m_descriptors[n]->minValue; |
198 maxValue = m_descriptor->maxValue; | 245 maxValue = m_descriptors[n]->maxValue; |
199 haveExtents = true; | 246 haveExtents = true; |
200 } | 247 } |
201 | 248 |
202 size_t modelRate = input->getSampleRate(); | 249 size_t modelRate = input->getSampleRate(); |
203 size_t modelResolution = 1; | 250 size_t modelResolution = 1; |
204 | 251 |
205 if (m_descriptor->sampleType != | 252 if (m_descriptors[n]->sampleType != |
206 Vamp::Plugin::OutputDescriptor::OneSamplePerStep) { | 253 Vamp::Plugin::OutputDescriptor::OneSamplePerStep) { |
207 if (m_descriptor->sampleRate > input->getSampleRate()) { | 254 if (m_descriptors[n]->sampleRate > input->getSampleRate()) { |
208 cerr << "WARNING: plugin reports output sample rate as " | 255 cerr << "WARNING: plugin reports output sample rate as " |
209 << m_descriptor->sampleRate << " (can't display features with finer resolution than the input rate of " << input->getSampleRate() << ")" << endl; | 256 << m_descriptors[n]->sampleRate << " (can't display features with finer resolution than the input rate of " << input->getSampleRate() << ")" << endl; |
210 } | 257 } |
211 } | 258 } |
212 | 259 |
213 switch (m_descriptor->sampleType) { | 260 switch (m_descriptors[n]->sampleType) { |
214 | 261 |
215 case Vamp::Plugin::OutputDescriptor::VariableSampleRate: | 262 case Vamp::Plugin::OutputDescriptor::VariableSampleRate: |
216 if (m_descriptor->sampleRate != 0.0) { | 263 if (m_descriptors[n]->sampleRate != 0.0) { |
217 modelResolution = size_t(modelRate / m_descriptor->sampleRate + 0.001); | 264 modelResolution = size_t(modelRate / m_descriptors[n]->sampleRate + 0.001); |
218 } | 265 } |
219 break; | 266 break; |
220 | 267 |
221 case Vamp::Plugin::OutputDescriptor::OneSamplePerStep: | 268 case Vamp::Plugin::OutputDescriptor::OneSamplePerStep: |
222 modelResolution = m_transform.getStepSize(); | 269 modelResolution = m_transforms[n].getStepSize(); |
223 break; | 270 break; |
224 | 271 |
225 case Vamp::Plugin::OutputDescriptor::FixedSampleRate: | 272 case Vamp::Plugin::OutputDescriptor::FixedSampleRate: |
226 //!!! SV doesn't actually support display of models that have | 273 //!!! SV doesn't actually support display of models that have |
227 //!!! different underlying rates together -- so we always set | 274 //!!! different underlying rates together -- so we always set |
228 //!!! the model rate to be the input model's rate, and adjust | 275 //!!! the model rate to be the input model's rate, and adjust |
229 //!!! the resolution appropriately. We can't properly display | 276 //!!! the resolution appropriately. We can't properly display |
230 //!!! data with a higher resolution than the base model at all | 277 //!!! data with a higher resolution than the base model at all |
231 // modelRate = size_t(m_descriptor->sampleRate + 0.001); | 278 // modelRate = size_t(m_descriptors[n]->sampleRate + 0.001); |
232 if (m_descriptor->sampleRate > input->getSampleRate()) { | 279 if (m_descriptors[n]->sampleRate > input->getSampleRate()) { |
233 modelResolution = 1; | 280 modelResolution = 1; |
234 } else { | 281 } else { |
235 modelResolution = size_t(input->getSampleRate() / | 282 modelResolution = size_t(input->getSampleRate() / |
236 m_descriptor->sampleRate); | 283 m_descriptors[n]->sampleRate); |
237 } | 284 } |
238 break; | 285 break; |
239 } | 286 } |
240 | 287 |
241 bool preDurationPlugin = (m_plugin->getVampApiVersion() < 2); | 288 bool preDurationPlugin = (m_plugin->getVampApiVersion() < 2); |
242 | 289 |
290 Model *out = 0; | |
291 | |
243 if (binCount == 0 && | 292 if (binCount == 0 && |
244 (preDurationPlugin || !m_descriptor->hasDuration)) { | 293 (preDurationPlugin || !m_descriptors[n]->hasDuration)) { |
245 | 294 |
246 // Anything with no value and no duration is an instant | 295 // Anything with no value and no duration is an instant |
247 | 296 |
248 m_output = new SparseOneDimensionalModel(modelRate, modelResolution, | 297 out = new SparseOneDimensionalModel(modelRate, modelResolution, false); |
249 false); | |
250 | |
251 QString outputEventTypeURI = description.getOutputEventTypeURI(outputId); | 298 QString outputEventTypeURI = description.getOutputEventTypeURI(outputId); |
252 m_output->setRDFTypeURI(outputEventTypeURI); | 299 out->setRDFTypeURI(outputEventTypeURI); |
253 | 300 |
254 } else if ((preDurationPlugin && binCount > 1 && | 301 } else if ((preDurationPlugin && binCount > 1 && |
255 (m_descriptor->sampleType == | 302 (m_descriptors[n]->sampleType == |
256 Vamp::Plugin::OutputDescriptor::VariableSampleRate)) || | 303 Vamp::Plugin::OutputDescriptor::VariableSampleRate)) || |
257 (!preDurationPlugin && m_descriptor->hasDuration)) { | 304 (!preDurationPlugin && m_descriptors[n]->hasDuration)) { |
258 | 305 |
259 // For plugins using the old v1 API without explicit duration, | 306 // For plugins using the old v1 API without explicit duration, |
260 // we treat anything that has multiple bins (i.e. that has the | 307 // we treat anything that has multiple bins (i.e. that has the |
261 // potential to have value and duration) and a variable sample | 308 // potential to have value and duration) and a variable sample |
262 // rate as a note model, taking its values as pitch, duration | 309 // rate as a note model, taking its values as pitch, duration |
283 // duration) | 330 // duration) |
284 if (binCount > 1) isNoteModel = true; | 331 if (binCount > 1) isNoteModel = true; |
285 | 332 |
286 // Regions do not have units of Hz or MIDI things (a sweeping | 333 // Regions do not have units of Hz or MIDI things (a sweeping |
287 // assumption!) | 334 // assumption!) |
288 if (m_descriptor->unit == "Hz" || | 335 if (m_descriptors[n]->unit == "Hz" || |
289 m_descriptor->unit.find("MIDI") != std::string::npos || | 336 m_descriptors[n]->unit.find("MIDI") != std::string::npos || |
290 m_descriptor->unit.find("midi") != std::string::npos) { | 337 m_descriptors[n]->unit.find("midi") != std::string::npos) { |
291 isNoteModel = true; | 338 isNoteModel = true; |
292 } | 339 } |
293 | 340 |
294 // If we had a "sparse 3D model", we would have the additional | 341 // If we had a "sparse 3D model", we would have the additional |
295 // problem of determining whether to use that here (if bin | 342 // problem of determining whether to use that here (if bin |
296 // count > 1). But we don't. | 343 // count > 1). But we don't. |
297 | 344 |
298 if (isNoteModel) { | 345 QSettings settings; |
346 settings.beginGroup("Transformer"); | |
347 bool flexi = settings.value("use-flexi-note-model", false).toBool(); | |
348 settings.endGroup(); | |
349 | |
350 cerr << "flexi = " << flexi << endl; | |
351 | |
352 if (isNoteModel && !flexi) { | |
299 | 353 |
300 NoteModel *model; | 354 NoteModel *model; |
301 if (haveExtents) { | 355 if (haveExtents) { |
302 model = new NoteModel | 356 model = new NoteModel |
303 (modelRate, modelResolution, minValue, maxValue, false); | 357 (modelRate, modelResolution, minValue, maxValue, false); |
304 } else { | 358 } else { |
305 model = new NoteModel | 359 model = new NoteModel |
306 (modelRate, modelResolution, false); | 360 (modelRate, modelResolution, false); |
307 } | 361 } |
308 model->setScaleUnits(m_descriptor->unit.c_str()); | 362 model->setScaleUnits(m_descriptors[n]->unit.c_str()); |
309 m_output = model; | 363 out = model; |
364 | |
365 } else if (isNoteModel && flexi) { | |
366 | |
367 FlexiNoteModel *model; | |
368 if (haveExtents) { | |
369 model = new FlexiNoteModel | |
370 (modelRate, modelResolution, minValue, maxValue, false); | |
371 } else { | |
372 model = new FlexiNoteModel | |
373 (modelRate, modelResolution, false); | |
374 } | |
375 model->setScaleUnits(m_descriptors[n]->unit.c_str()); | |
376 out = model; | |
310 | 377 |
311 } else { | 378 } else { |
312 | 379 |
313 RegionModel *model; | 380 RegionModel *model; |
314 if (haveExtents) { | 381 if (haveExtents) { |
316 (modelRate, modelResolution, minValue, maxValue, false); | 383 (modelRate, modelResolution, minValue, maxValue, false); |
317 } else { | 384 } else { |
318 model = new RegionModel | 385 model = new RegionModel |
319 (modelRate, modelResolution, false); | 386 (modelRate, modelResolution, false); |
320 } | 387 } |
321 model->setScaleUnits(m_descriptor->unit.c_str()); | 388 model->setScaleUnits(m_descriptors[n]->unit.c_str()); |
322 m_output = model; | 389 out = model; |
323 } | 390 } |
324 | 391 |
325 QString outputEventTypeURI = description.getOutputEventTypeURI(outputId); | 392 QString outputEventTypeURI = description.getOutputEventTypeURI(outputId); |
326 m_output->setRDFTypeURI(outputEventTypeURI); | 393 out->setRDFTypeURI(outputEventTypeURI); |
327 | 394 |
328 } else if (binCount == 1 || | 395 } else if (binCount == 1 || |
329 (m_descriptor->sampleType == | 396 (m_descriptors[n]->sampleType == |
330 Vamp::Plugin::OutputDescriptor::VariableSampleRate)) { | 397 Vamp::Plugin::OutputDescriptor::VariableSampleRate)) { |
331 | 398 |
332 // Anything that is not a 1D, note, or interval model and that | 399 // Anything that is not a 1D, note, or interval model and that |
333 // has only one value per result must be a sparse time value | 400 // has only one value per result must be a sparse time value |
334 // model. | 401 // model. |
346 model = new SparseTimeValueModel | 413 model = new SparseTimeValueModel |
347 (modelRate, modelResolution, false); | 414 (modelRate, modelResolution, false); |
348 } | 415 } |
349 | 416 |
350 Vamp::Plugin::OutputList outputs = m_plugin->getOutputDescriptors(); | 417 Vamp::Plugin::OutputList outputs = m_plugin->getOutputDescriptors(); |
351 model->setScaleUnits(outputs[m_outputNo].unit.c_str()); | 418 model->setScaleUnits(outputs[m_outputNos[n]].unit.c_str()); |
352 | 419 |
353 m_output = model; | 420 out = model; |
354 | 421 |
355 QString outputEventTypeURI = description.getOutputEventTypeURI(outputId); | 422 QString outputEventTypeURI = description.getOutputEventTypeURI(outputId); |
356 m_output->setRDFTypeURI(outputEventTypeURI); | 423 out->setRDFTypeURI(outputEventTypeURI); |
357 | 424 |
358 } else { | 425 } else { |
359 | 426 |
360 // Anything that is not a 1D, note, or interval model and that | 427 // Anything that is not a 1D, note, or interval model and that |
361 // has a fixed sample rate and more than one value per result | 428 // has a fixed sample rate and more than one value per result |
365 new EditableDenseThreeDimensionalModel | 432 new EditableDenseThreeDimensionalModel |
366 (modelRate, modelResolution, binCount, | 433 (modelRate, modelResolution, binCount, |
367 EditableDenseThreeDimensionalModel::BasicMultirateCompression, | 434 EditableDenseThreeDimensionalModel::BasicMultirateCompression, |
368 false); | 435 false); |
369 | 436 |
370 if (!m_descriptor->binNames.empty()) { | 437 if (!m_descriptors[n]->binNames.empty()) { |
371 std::vector<QString> names; | 438 std::vector<QString> names; |
372 for (size_t i = 0; i < m_descriptor->binNames.size(); ++i) { | 439 for (size_t i = 0; i < m_descriptors[n]->binNames.size(); ++i) { |
373 names.push_back(m_descriptor->binNames[i].c_str()); | 440 names.push_back(m_descriptors[n]->binNames[i].c_str()); |
374 } | 441 } |
375 model->setBinNames(names); | 442 model->setBinNames(names); |
376 } | 443 } |
377 | 444 |
378 m_output = model; | 445 out = model; |
379 | 446 |
380 QString outputSignalTypeURI = description.getOutputSignalTypeURI(outputId); | 447 QString outputSignalTypeURI = description.getOutputSignalTypeURI(outputId); |
381 m_output->setRDFTypeURI(outputSignalTypeURI); | 448 out->setRDFTypeURI(outputSignalTypeURI); |
382 } | 449 } |
383 | 450 |
384 if (m_output) m_output->setSourceModel(input); | 451 if (out) { |
452 out->setSourceModel(input); | |
453 m_outputs.push_back(out); | |
454 } | |
385 } | 455 } |
386 | 456 |
387 FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer() | 457 FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer() |
388 { | 458 { |
389 // SVDEBUG << "FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer()" << endl; | 459 // SVDEBUG << "FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer()" << endl; |
390 delete m_plugin; | 460 delete m_plugin; |
391 delete m_descriptor; | 461 for (int j = 0; j < m_descriptors.size(); ++j) { |
462 delete m_descriptors[j]; | |
463 } | |
392 } | 464 } |
393 | 465 |
394 DenseTimeValueModel * | 466 DenseTimeValueModel * |
395 FeatureExtractionModelTransformer::getConformingInput() | 467 FeatureExtractionModelTransformer::getConformingInput() |
396 { | 468 { |
408 FeatureExtractionModelTransformer::run() | 480 FeatureExtractionModelTransformer::run() |
409 { | 481 { |
410 DenseTimeValueModel *input = getConformingInput(); | 482 DenseTimeValueModel *input = getConformingInput(); |
411 if (!input) return; | 483 if (!input) return; |
412 | 484 |
413 if (!m_output) return; | 485 if (m_outputs.empty()) return; |
486 | |
487 Transform primaryTransform = m_transforms[0]; | |
414 | 488 |
415 while (!input->isReady() && !m_abandoned) { | 489 while (!input->isReady() && !m_abandoned) { |
416 SVDEBUG << "FeatureExtractionModelTransformer::run: Waiting for input model to be ready..." << endl; | 490 SVDEBUG << "FeatureExtractionModelTransformer::run: Waiting for input model to be ready..." << endl; |
417 usleep(500000); | 491 usleep(500000); |
418 } | 492 } |
425 channelCount = 1; | 499 channelCount = 1; |
426 } | 500 } |
427 | 501 |
428 float **buffers = new float*[channelCount]; | 502 float **buffers = new float*[channelCount]; |
429 for (size_t ch = 0; ch < channelCount; ++ch) { | 503 for (size_t ch = 0; ch < channelCount; ++ch) { |
430 buffers[ch] = new float[m_transform.getBlockSize() + 2]; | 504 buffers[ch] = new float[primaryTransform.getBlockSize() + 2]; |
431 } | 505 } |
432 | 506 |
433 size_t stepSize = m_transform.getStepSize(); | 507 size_t stepSize = primaryTransform.getStepSize(); |
434 size_t blockSize = m_transform.getBlockSize(); | 508 size_t blockSize = primaryTransform.getBlockSize(); |
435 | 509 |
436 bool frequencyDomain = (m_plugin->getInputDomain() == | 510 bool frequencyDomain = (m_plugin->getInputDomain() == |
437 Vamp::Plugin::FrequencyDomain); | 511 Vamp::Plugin::FrequencyDomain); |
438 std::vector<FFTModel *> fftModels; | 512 std::vector<FFTModel *> fftModels; |
439 | 513 |
440 if (frequencyDomain) { | 514 if (frequencyDomain) { |
441 for (size_t ch = 0; ch < channelCount; ++ch) { | 515 for (size_t ch = 0; ch < channelCount; ++ch) { |
442 FFTModel *model = new FFTModel | 516 FFTModel *model = new FFTModel |
443 (getConformingInput(), | 517 (getConformingInput(), |
444 channelCount == 1 ? m_input.getChannel() : ch, | 518 channelCount == 1 ? m_input.getChannel() : ch, |
445 m_transform.getWindowType(), | 519 primaryTransform.getWindowType(), |
446 blockSize, | 520 blockSize, |
447 stepSize, | 521 stepSize, |
448 blockSize, | 522 blockSize, |
449 false, | 523 false, |
450 StorageAdviser::PrecisionCritical); | 524 StorageAdviser::PrecisionCritical); |
451 if (!model->isOK()) { | 525 if (!model->isOK()) { |
452 delete model; | 526 delete model; |
453 setCompletion(100); | 527 for (int j = 0; j < (int)m_outputNos.size(); ++j) { |
528 setCompletion(j, 100); | |
529 } | |
454 //!!! need a better way to handle this -- previously we were using a QMessageBox but that isn't an appropriate thing to do here either | 530 //!!! need a better way to handle this -- previously we were using a QMessageBox but that isn't an appropriate thing to do here either |
455 throw AllocationFailed("Failed to create the FFT model for this feature extraction model transformer"); | 531 throw AllocationFailed("Failed to create the FFT model for this feature extraction model transformer"); |
456 } | 532 } |
457 model->resume(); | 533 model->resume(); |
458 fftModels.push_back(model); | 534 fftModels.push_back(model); |
460 } | 536 } |
461 | 537 |
462 long startFrame = m_input.getModel()->getStartFrame(); | 538 long startFrame = m_input.getModel()->getStartFrame(); |
463 long endFrame = m_input.getModel()->getEndFrame(); | 539 long endFrame = m_input.getModel()->getEndFrame(); |
464 | 540 |
465 RealTime contextStartRT = m_transform.getStartTime(); | 541 RealTime contextStartRT = primaryTransform.getStartTime(); |
466 RealTime contextDurationRT = m_transform.getDuration(); | 542 RealTime contextDurationRT = primaryTransform.getDuration(); |
467 | 543 |
468 long contextStart = | 544 long contextStart = |
469 RealTime::realTime2Frame(contextStartRT, sampleRate); | 545 RealTime::realTime2Frame(contextStartRT, sampleRate); |
470 | 546 |
471 long contextDuration = | 547 long contextDuration = |
484 | 560 |
485 long blockFrame = contextStart; | 561 long blockFrame = contextStart; |
486 | 562 |
487 long prevCompletion = 0; | 563 long prevCompletion = 0; |
488 | 564 |
489 setCompletion(0); | 565 for (int j = 0; j < (int)m_outputNos.size(); ++j) { |
566 setCompletion(j, 0); | |
567 } | |
490 | 568 |
491 float *reals = 0; | 569 float *reals = 0; |
492 float *imaginaries = 0; | 570 float *imaginaries = 0; |
493 if (frequencyDomain) { | 571 if (frequencyDomain) { |
494 reals = new float[blockSize/2 + 1]; | 572 reals = new float[blockSize/2 + 1]; |
541 Vamp::Plugin::FeatureSet features = m_plugin->process | 619 Vamp::Plugin::FeatureSet features = m_plugin->process |
542 (buffers, Vamp::RealTime::frame2RealTime(blockFrame, sampleRate)); | 620 (buffers, Vamp::RealTime::frame2RealTime(blockFrame, sampleRate)); |
543 | 621 |
544 if (m_abandoned) break; | 622 if (m_abandoned) break; |
545 | 623 |
546 for (size_t fi = 0; fi < features[m_outputNo].size(); ++fi) { | 624 for (int j = 0; j < (int)m_outputNos.size(); ++j) { |
547 Vamp::Plugin::Feature feature = features[m_outputNo][fi]; | 625 for (size_t fi = 0; fi < features[m_outputNos[j]].size(); ++fi) { |
548 addFeature(blockFrame, feature); | 626 Vamp::Plugin::Feature feature = features[m_outputNos[j]][fi]; |
549 } | 627 addFeature(j, blockFrame, feature); |
628 } | |
629 } | |
550 | 630 |
551 if (blockFrame == contextStart || completion > prevCompletion) { | 631 if (blockFrame == contextStart || completion > prevCompletion) { |
552 setCompletion(completion); | 632 for (int j = 0; j < (int)m_outputNos.size(); ++j) { |
633 setCompletion(j, completion); | |
634 } | |
553 prevCompletion = completion; | 635 prevCompletion = completion; |
554 } | 636 } |
555 | 637 |
556 blockFrame += stepSize; | 638 blockFrame += stepSize; |
557 } | 639 } |
558 | 640 |
559 if (!m_abandoned) { | 641 if (!m_abandoned) { |
560 Vamp::Plugin::FeatureSet features = m_plugin->getRemainingFeatures(); | 642 Vamp::Plugin::FeatureSet features = m_plugin->getRemainingFeatures(); |
561 | 643 |
562 for (size_t fi = 0; fi < features[m_outputNo].size(); ++fi) { | 644 for (int j = 0; j < (int)m_outputNos.size(); ++j) { |
563 Vamp::Plugin::Feature feature = features[m_outputNo][fi]; | 645 for (size_t fi = 0; fi < features[m_outputNos[j]].size(); ++fi) { |
564 addFeature(blockFrame, feature); | 646 Vamp::Plugin::Feature feature = features[m_outputNos[j]][fi]; |
565 } | 647 addFeature(j, blockFrame, feature); |
566 } | 648 } |
567 | 649 } |
568 setCompletion(100); | 650 } |
651 | |
652 for (int j = 0; j < (int)m_outputNos.size(); ++j) { | |
653 setCompletion(j, 100); | |
654 } | |
569 | 655 |
570 if (frequencyDomain) { | 656 if (frequencyDomain) { |
571 for (size_t ch = 0; ch < channelCount; ++ch) { | 657 for (size_t ch = 0; ch < channelCount; ++ch) { |
572 delete fftModels[ch]; | 658 delete fftModels[ch]; |
573 } | 659 } |
635 ++got; | 721 ++got; |
636 } | 722 } |
637 } | 723 } |
638 | 724 |
639 void | 725 void |
640 FeatureExtractionModelTransformer::addFeature(size_t blockFrame, | 726 FeatureExtractionModelTransformer::addFeature(int n, |
727 size_t blockFrame, | |
641 const Vamp::Plugin::Feature &feature) | 728 const Vamp::Plugin::Feature &feature) |
642 { | 729 { |
643 size_t inputRate = m_input.getModel()->getSampleRate(); | 730 size_t inputRate = m_input.getModel()->getSampleRate(); |
644 | 731 |
645 // cerr << "FeatureExtractionModelTransformer::addFeature: blockFrame = " | 732 // cerr << "FeatureExtractionModelTransformer::addFeature: blockFrame = " |
647 // << ", timestamp = " << feature.timestamp << ", hasDuration = " | 734 // << ", timestamp = " << feature.timestamp << ", hasDuration = " |
648 // << feature.hasDuration << ", duration = " << feature.duration | 735 // << feature.hasDuration << ", duration = " << feature.duration |
649 // << endl; | 736 // << endl; |
650 | 737 |
651 int binCount = 1; | 738 int binCount = 1; |
652 if (m_descriptor->hasFixedBinCount) { | 739 if (m_descriptors[n]->hasFixedBinCount) { |
653 binCount = m_descriptor->binCount; | 740 binCount = m_descriptors[n]->binCount; |
654 } | 741 } |
655 | 742 |
656 int frame = blockFrame; | 743 int frame = blockFrame; |
657 | 744 |
658 if (m_descriptor->sampleType == | 745 if (m_descriptors[n]->sampleType == |
659 Vamp::Plugin::OutputDescriptor::VariableSampleRate) { | 746 Vamp::Plugin::OutputDescriptor::VariableSampleRate) { |
660 | 747 |
661 if (!feature.hasTimestamp) { | 748 if (!feature.hasTimestamp) { |
662 cerr | 749 cerr |
663 << "WARNING: FeatureExtractionModelTransformer::addFeature: " | 750 << "WARNING: FeatureExtractionModelTransformer::addFeature: " |
666 return; | 753 return; |
667 } else { | 754 } else { |
668 frame = Vamp::RealTime::realTime2Frame(feature.timestamp, inputRate); | 755 frame = Vamp::RealTime::realTime2Frame(feature.timestamp, inputRate); |
669 } | 756 } |
670 | 757 |
671 } else if (m_descriptor->sampleType == | 758 } else if (m_descriptors[n]->sampleType == |
672 Vamp::Plugin::OutputDescriptor::FixedSampleRate) { | 759 Vamp::Plugin::OutputDescriptor::FixedSampleRate) { |
673 | 760 |
674 if (!feature.hasTimestamp) { | 761 if (!feature.hasTimestamp) { |
675 ++m_fixedRateFeatureNo; | 762 ++m_fixedRateFeatureNos[n]; |
676 } else { | 763 } else { |
677 RealTime ts(feature.timestamp.sec, feature.timestamp.nsec); | 764 RealTime ts(feature.timestamp.sec, feature.timestamp.nsec); |
678 m_fixedRateFeatureNo = | 765 m_fixedRateFeatureNos[n] = |
679 lrint(ts.toDouble() * m_descriptor->sampleRate); | 766 lrint(ts.toDouble() * m_descriptors[n]->sampleRate); |
680 } | 767 } |
681 | 768 |
682 // cerr << "m_fixedRateFeatureNo = " << m_fixedRateFeatureNo | 769 // cerr << "m_fixedRateFeatureNo = " << m_fixedRateFeatureNo |
683 // << ", m_descriptor->sampleRate = " << m_descriptor->sampleRate | 770 // << ", m_descriptor->sampleRate = " << m_descriptor->sampleRate |
684 // << ", inputRate = " << inputRate | 771 // << ", inputRate = " << inputRate |
685 // << " giving frame = "; | 772 // << " giving frame = "; |
686 | 773 |
687 frame = lrintf((m_fixedRateFeatureNo / m_descriptor->sampleRate) | 774 frame = lrintf((m_fixedRateFeatureNos[n] / m_descriptors[n]->sampleRate) |
688 * int(inputRate)); | 775 * int(inputRate)); |
689 | |
690 // cerr << frame << endl; | |
691 } | 776 } |
692 | 777 |
693 if (frame < 0) { | 778 if (frame < 0) { |
694 cerr | 779 cerr |
695 << "WARNING: FeatureExtractionModelTransformer::addFeature: " | 780 << "WARNING: FeatureExtractionModelTransformer::addFeature: " |
703 // Rather than repeat the complicated tests from the constructor | 788 // Rather than repeat the complicated tests from the constructor |
704 // to determine what sort of model we must be adding the features | 789 // to determine what sort of model we must be adding the features |
705 // to, we instead test what sort of model the constructor decided | 790 // to, we instead test what sort of model the constructor decided |
706 // to create. | 791 // to create. |
707 | 792 |
708 if (isOutput<SparseOneDimensionalModel>()) { | 793 if (isOutput<SparseOneDimensionalModel>(n)) { |
709 | 794 |
710 SparseOneDimensionalModel *model = | 795 SparseOneDimensionalModel *model = |
711 getConformingOutput<SparseOneDimensionalModel>(); | 796 getConformingOutput<SparseOneDimensionalModel>(n); |
712 if (!model) return; | 797 if (!model) return; |
713 | 798 |
714 model->addPoint(SparseOneDimensionalModel::Point | 799 model->addPoint(SparseOneDimensionalModel::Point |
715 (frame, feature.label.c_str())); | 800 (frame, feature.label.c_str())); |
716 | 801 |
717 } else if (isOutput<SparseTimeValueModel>()) { | 802 } else if (isOutput<SparseTimeValueModel>(n)) { |
718 | 803 |
719 SparseTimeValueModel *model = | 804 SparseTimeValueModel *model = |
720 getConformingOutput<SparseTimeValueModel>(); | 805 getConformingOutput<SparseTimeValueModel>(n); |
721 if (!model) return; | 806 if (!model) return; |
722 | 807 |
723 for (int i = 0; i < feature.values.size(); ++i) { | 808 for (int i = 0; i < feature.values.size(); ++i) { |
724 | 809 |
725 float value = feature.values[i]; | 810 float value = feature.values[i]; |
730 } | 815 } |
731 | 816 |
732 model->addPoint(SparseTimeValueModel::Point(frame, value, label)); | 817 model->addPoint(SparseTimeValueModel::Point(frame, value, label)); |
733 } | 818 } |
734 | 819 |
735 } else if (isOutput<NoteModel>() || isOutput<RegionModel>()) { | 820 } else if (isOutput<FlexiNoteModel>(n) || isOutput<NoteModel>(n) || isOutput<RegionModel>(n)) { //GF: Added Note Model |
736 | 821 |
737 int index = 0; | 822 int index = 0; |
738 | 823 |
739 float value = 0.0; | 824 float value = 0.0; |
740 if (feature.values.size() > index) { | 825 if (feature.values.size() > index) { |
747 } else { | 832 } else { |
748 if (feature.values.size() > index) { | 833 if (feature.values.size() > index) { |
749 duration = feature.values[index++]; | 834 duration = feature.values[index++]; |
750 } | 835 } |
751 } | 836 } |
752 | 837 |
753 if (isOutput<NoteModel>()) { | 838 if (isOutput<FlexiNoteModel>(n)) { // GF: added for flexi note model |
754 | 839 |
755 float velocity = 100; | 840 float velocity = 100; |
756 if (feature.values.size() > index) { | 841 if (feature.values.size() > index) { |
757 velocity = feature.values[index++]; | 842 velocity = feature.values[index++]; |
758 } | 843 } |
759 if (velocity < 0) velocity = 127; | 844 if (velocity < 0) velocity = 127; |
760 if (velocity > 127) velocity = 127; | 845 if (velocity > 127) velocity = 127; |
761 | 846 |
762 NoteModel *model = getConformingOutput<NoteModel>(); | 847 FlexiNoteModel *model = getConformingOutput<FlexiNoteModel>(n); |
848 if (!model) return; | |
849 model->addPoint(FlexiNoteModel::Point(frame, value, // value is pitch | |
850 lrintf(duration), | |
851 velocity / 127.f, | |
852 feature.label.c_str())); | |
853 // GF: end -- added for flexi note model | |
854 } else if (isOutput<NoteModel>(n)) { | |
855 | |
856 float velocity = 100; | |
857 if (feature.values.size() > index) { | |
858 velocity = feature.values[index++]; | |
859 } | |
860 if (velocity < 0) velocity = 127; | |
861 if (velocity > 127) velocity = 127; | |
862 | |
863 NoteModel *model = getConformingOutput<NoteModel>(n); | |
763 if (!model) return; | 864 if (!model) return; |
764 model->addPoint(NoteModel::Point(frame, value, // value is pitch | 865 model->addPoint(NoteModel::Point(frame, value, // value is pitch |
765 lrintf(duration), | 866 lrintf(duration), |
766 velocity / 127.f, | 867 velocity / 127.f, |
767 feature.label.c_str())); | 868 feature.label.c_str())); |
768 } else { | 869 } else { |
769 RegionModel *model = getConformingOutput<RegionModel>(); | 870 |
871 RegionModel *model = getConformingOutput<RegionModel>(n); | |
770 if (!model) return; | 872 if (!model) return; |
771 | 873 |
772 if (feature.hasDuration && !feature.values.empty()) { | 874 if (feature.hasDuration && !feature.values.empty()) { |
773 | 875 |
774 for (int i = 0; i < feature.values.size(); ++i) { | 876 for (int i = 0; i < feature.values.size(); ++i) { |
790 lrintf(duration), | 892 lrintf(duration), |
791 feature.label.c_str())); | 893 feature.label.c_str())); |
792 } | 894 } |
793 } | 895 } |
794 | 896 |
795 } else if (isOutput<EditableDenseThreeDimensionalModel>()) { | 897 } else if (isOutput<EditableDenseThreeDimensionalModel>(n)) { |
796 | 898 |
797 DenseThreeDimensionalModel::Column values = | 899 DenseThreeDimensionalModel::Column values = |
798 DenseThreeDimensionalModel::Column::fromStdVector(feature.values); | 900 DenseThreeDimensionalModel::Column::fromStdVector(feature.values); |
799 | 901 |
800 EditableDenseThreeDimensionalModel *model = | 902 EditableDenseThreeDimensionalModel *model = |
801 getConformingOutput<EditableDenseThreeDimensionalModel>(); | 903 getConformingOutput<EditableDenseThreeDimensionalModel>(n); |
802 if (!model) return; | 904 if (!model) return; |
803 | 905 |
804 model->setColumn(frame / model->getResolution(), values); | 906 model->setColumn(frame / model->getResolution(), values); |
805 | 907 |
806 } else { | 908 } else { |
807 SVDEBUG << "FeatureExtractionModelTransformer::addFeature: Unknown output model type!" << endl; | 909 SVDEBUG << "FeatureExtractionModelTransformer::addFeature: Unknown output model type!" << endl; |
808 } | 910 } |
809 } | 911 } |
810 | 912 |
811 void | 913 void |
812 FeatureExtractionModelTransformer::setCompletion(int completion) | 914 FeatureExtractionModelTransformer::setCompletion(int n, int completion) |
813 { | 915 { |
814 int binCount = 1; | 916 int binCount = 1; |
815 if (m_descriptor->hasFixedBinCount) { | 917 if (m_descriptors[n]->hasFixedBinCount) { |
816 binCount = m_descriptor->binCount; | 918 binCount = m_descriptors[n]->binCount; |
817 } | 919 } |
818 | 920 |
819 // SVDEBUG << "FeatureExtractionModelTransformer::setCompletion(" | 921 // SVDEBUG << "FeatureExtractionModelTransformer::setCompletion(" |
820 // << completion << ")" << endl; | 922 // << completion << ")" << endl; |
821 | 923 |
822 if (isOutput<SparseOneDimensionalModel>()) { | 924 if (isOutput<SparseOneDimensionalModel>(n)) { |
823 | 925 |
824 SparseOneDimensionalModel *model = | 926 SparseOneDimensionalModel *model = |
825 getConformingOutput<SparseOneDimensionalModel>(); | 927 getConformingOutput<SparseOneDimensionalModel>(n); |
826 if (!model) return; | 928 if (!model) return; |
827 model->setCompletion(completion, true); | 929 model->setCompletion(completion, true); |
828 | 930 |
829 } else if (isOutput<SparseTimeValueModel>()) { | 931 } else if (isOutput<SparseTimeValueModel>(n)) { |
830 | 932 |
831 SparseTimeValueModel *model = | 933 SparseTimeValueModel *model = |
832 getConformingOutput<SparseTimeValueModel>(); | 934 getConformingOutput<SparseTimeValueModel>(n); |
833 if (!model) return; | 935 if (!model) return; |
834 model->setCompletion(completion, true); | 936 model->setCompletion(completion, true); |
835 | 937 |
836 } else if (isOutput<NoteModel>()) { | 938 } else if (isOutput<NoteModel>(n)) { |
837 | 939 |
838 NoteModel *model = getConformingOutput<NoteModel>(); | 940 NoteModel *model = getConformingOutput<NoteModel>(n); |
839 if (!model) return; | 941 if (!model) return; |
840 model->setCompletion(completion, true); | 942 model->setCompletion(completion, true); |
841 | 943 |
842 } else if (isOutput<RegionModel>()) { | 944 } else if (isOutput<FlexiNoteModel>(n)) { |
843 | 945 |
844 RegionModel *model = getConformingOutput<RegionModel>(); | 946 FlexiNoteModel *model = getConformingOutput<FlexiNoteModel>(n); |
845 if (!model) return; | 947 if (!model) return; |
846 model->setCompletion(completion, true); | 948 model->setCompletion(completion, true); |
847 | 949 |
848 } else if (isOutput<EditableDenseThreeDimensionalModel>()) { | 950 } else if (isOutput<RegionModel>(n)) { |
951 | |
952 RegionModel *model = getConformingOutput<RegionModel>(n); | |
953 if (!model) return; | |
954 model->setCompletion(completion, true); | |
955 | |
956 } else if (isOutput<EditableDenseThreeDimensionalModel>(n)) { | |
849 | 957 |
850 EditableDenseThreeDimensionalModel *model = | 958 EditableDenseThreeDimensionalModel *model = |
851 getConformingOutput<EditableDenseThreeDimensionalModel>(); | 959 getConformingOutput<EditableDenseThreeDimensionalModel>(n); |
852 if (!model) return; | 960 if (!model) return; |
853 model->setCompletion(completion, true); //!!!m_context.updates); | 961 model->setCompletion(completion, true); //!!!m_context.updates); |
854 } | 962 } |
855 } | 963 } |
856 | 964 |