Mercurial > hg > vamp-tempogram
comparison Tempogram.cpp @ 1:3fd1a41b089b
* Now displaying some output. Needs testing to see if bugs are present.
author | Carl Bussey <c.bussey@se10.qmul.ac.uk> |
---|---|
date | Wed, 09 Jul 2014 10:26:51 +0100 |
parents | 31d2a7e07786 |
children | 1d0b7dcea27f |
comparison
equal
deleted
inserted
replaced
0:31d2a7e07786 | 1:3fd1a41b089b |
---|---|
15 using namespace std; | 15 using namespace std; |
16 | 16 |
17 Tempogram::Tempogram(float inputSampleRate) : | 17 Tempogram::Tempogram(float inputSampleRate) : |
18 Plugin(inputSampleRate), | 18 Plugin(inputSampleRate), |
19 m_blockSize(0), | 19 m_blockSize(0), |
20 m_stepSize(0), | |
20 compressionConstant(1000), //make param | 21 compressionConstant(1000), //make param |
21 previousY(NULL), | 22 previousY(NULL), |
22 currentY(NULL), | 23 currentY(NULL), |
23 tN(1024), //make param | 24 tN(1024), //make param |
24 thopSize(512), //make param | 25 thopSize(512), //make param |
95 } | 96 } |
96 | 97 |
97 size_t | 98 size_t |
98 Tempogram::getPreferredStepSize() const | 99 Tempogram::getPreferredStepSize() const |
99 { | 100 { |
100 //23 ms? | |
101 return 0; // 0 means "anything sensible"; in practice this | 101 return 0; // 0 means "anything sensible"; in practice this |
102 // means the same as the block size for TimeDomain | 102 // means the same as the block size for TimeDomain |
103 // plugins, or half of it for FrequencyDomain plugins | 103 // plugins, or half of it for FrequencyDomain plugins |
104 } | 104 } |
105 | 105 |
172 | 172 |
173 void | 173 void |
174 Tempogram::setParameter(string identifier, float value) | 174 Tempogram::setParameter(string identifier, float value) |
175 { | 175 { |
176 if (identifier == "C") { | 176 if (identifier == "C") { |
177 compressionConstant = value;// set the actual value of your parameter | 177 compressionConstant = value; // set the actual value of your parameter |
178 } | 178 } |
179 if (identifier == "tN") { | 179 if (identifier == "tN") { |
180 tN = value; | 180 tN = value; |
181 } | 181 } |
182 } | 182 } |
208 { | 208 { |
209 OutputList list; | 209 OutputList list; |
210 | 210 |
211 // See OutputDescriptor documentation for the possibilities here. | 211 // See OutputDescriptor documentation for the possibilities here. |
212 // Every plugin must have at least one output. | 212 // Every plugin must have at least one output. |
213 | 213 |
214 OutputDescriptor d; | 214 OutputDescriptor d; |
215 d.identifier = "output"; | 215 d.identifier = "tempogram"; |
216 d.name = "Cyclic Tempogram"; | 216 d.name = "Cyclic Tempogram"; |
217 d.description = "Cyclic Tempogram"; | 217 d.description = "Cyclic Tempogram"; |
218 d.unit = ""; | 218 d.unit = ""; |
219 d.hasFixedBinCount = false; | 219 d.hasFixedBinCount = true; |
220 //d.binCount = 1; | 220 d.binCount = tN; |
221 d.hasKnownExtents = false; | 221 d.hasKnownExtents = false; |
222 d.isQuantized = false; | 222 d.isQuantized = false; |
223 d.sampleType = OutputDescriptor::VariableSampleRate; | 223 d.sampleType = OutputDescriptor::FixedSampleRate; |
224 d.sampleRate = 0.0; | 224 float d_sampleRate = m_inputSampleRate/(m_stepSize * thopSize); |
225 d.sampleRate = d_sampleRate > 0.0 && !isnan(d_sampleRate) ? d_sampleRate : 0.0; | |
225 d.hasDuration = false; | 226 d.hasDuration = false; |
226 list.push_back(d); | 227 list.push_back(d); |
227 | 228 |
229 d.identifier = "nc"; | |
230 d.name = "Novelty Curve"; | |
231 d.description = "Novelty Curve"; | |
232 d.unit = ""; | |
233 d.hasFixedBinCount = true; | |
234 d.binCount = 1; | |
235 d.hasKnownExtents = false; | |
236 d.isQuantized = false; | |
237 d.sampleType = OutputDescriptor::FixedSampleRate; | |
238 d_sampleRate = m_inputSampleRate/m_stepSize; | |
239 d.sampleRate = d_sampleRate > 0 && !isnan(d_sampleRate) ? d_sampleRate : 0.0; | |
240 d.hasDuration = false; | |
241 list.push_back(d); | |
242 | |
228 return list; | 243 return list; |
229 } | 244 } |
230 | 245 |
231 bool | 246 bool |
232 Tempogram::initialise(size_t channels, size_t stepSize, size_t blockSize) | 247 Tempogram::initialise(size_t channels, size_t stepSize, size_t blockSize) |
234 if (channels < getMinChannelCount() || | 249 if (channels < getMinChannelCount() || |
235 channels > getMaxChannelCount()) return false; | 250 channels > getMaxChannelCount()) return false; |
236 | 251 |
237 // Real initialisation work goes here! | 252 // Real initialisation work goes here! |
238 m_blockSize = blockSize; | 253 m_blockSize = blockSize; |
254 m_stepSize = stepSize; | |
239 currentY = new float[m_blockSize]; | 255 currentY = new float[m_blockSize]; |
240 previousY = new float[m_blockSize]; | 256 previousY = new float[m_blockSize]; |
241 | 257 |
242 return true; | 258 return true; |
243 } | 259 } |
253 { | 269 { |
254 size_t n = m_blockSize/2 + 1; | 270 size_t n = m_blockSize/2 + 1; |
255 | 271 |
256 FeatureSet featureSet; | 272 FeatureSet featureSet; |
257 Feature feature; | 273 Feature feature; |
258 feature.hasTimestamp = false; | |
259 | 274 |
260 const float *in = inputBuffers[0]; | 275 const float *in = inputBuffers[0]; |
261 | 276 |
262 //Calculate log magnitude | 277 //Calculate log magnitude |
263 float sum = 0; | 278 float sum = 0; |
310 Tempogram::FeatureSet | 325 Tempogram::FeatureSet |
311 Tempogram::getRemainingFeatures() | 326 Tempogram::getRemainingFeatures() |
312 { | 327 { |
313 //Make sure this is called at the beginning of the function | 328 //Make sure this is called at the beginning of the function |
314 initialiseForGRF(); | 329 initialiseForGRF(); |
330 FeatureSet featureSet; | |
315 | 331 |
316 vector<float> noveltyCurveLocalAverage(ncLength); | 332 vector<float> noveltyCurveLocalAverage(ncLength); |
317 | 333 |
318 FIRFilter *filter = new FIRFilter(ncLength, hannN); | 334 FIRFilter *filter = new FIRFilter(ncLength, hannN); |
319 filter->process(&noveltyCurve[0], hannWindow, &noveltyCurveLocalAverage[0]); | 335 filter->process(&noveltyCurve[0], hannWindow, &noveltyCurveLocalAverage[0]); |
320 delete filter; | 336 delete filter; |
321 | 337 |
322 for(int i = 0; i < ncLength; i++){ | 338 for(int i = 0; i < ncLength; i++){ |
323 noveltyCurve[i] -= noveltyCurveLocalAverage[i]; | 339 noveltyCurve[i] -= noveltyCurveLocalAverage[i]; |
324 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0; | 340 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0; |
341 Feature ncFeature; | |
342 ncFeature.values.push_back(noveltyCurve[i]); | |
343 featureSet[1].push_back(ncFeature); | |
325 } | 344 } |
326 | 345 |
327 int i=0; | 346 int i=0; |
328 WindowFunction::hanning(hannWindowtN, tN); | 347 WindowFunction::hanning(hannWindowtN, tN); |
329 | 348 |
330 int index; | 349 int index; |
331 int start = floor(tN/2 + 0.5); | 350 int frameBeginOffset = floor(tN/2 + 0.5); |
332 int timestampInc = floor((((float)ncTimestamps[1].nsec - ncTimestamps[0].nsec)/1e9)*(thopSize) + 0.5); | 351 int timestampInc = floor((((float)ncTimestamps[1].nsec - ncTimestamps[0].nsec)/1e9)*(thopSize) + 0.5); |
333 //cout << timestampInc << endl; | 352 //cout << timestampInc << endl; |
334 | 353 |
335 FeatureSet featureSet; | |
336 | |
337 while(i < ncLength){ | 354 while(i < ncLength){ |
338 Feature feature; | 355 Feature feature; |
339 Vamp::RealTime timestamp; | |
340 | 356 |
341 for (int n = start; n < tN; n++){ | 357 for (int n = frameBeginOffset; n < tN; n++){ |
342 index = i + n - tN/2; | 358 index = i + n - tN/2; |
343 assert (index >= 0); | 359 assert (index >= 0); |
344 | 360 |
345 if(index < ncLength){ | 361 if(index < ncLength){ |
346 fftInput[n] = noveltyCurve[i + n] * hannWindowtN[n]; | 362 fftInput[n] = noveltyCurve[i + n] * hannWindowtN[n]; |
349 fftInput[n] = 0.0; //pad the end with zeros | 365 fftInput[n] = 0.0; //pad the end with zeros |
350 } | 366 } |
351 //cout << fftInput[n] << endl; | 367 //cout << fftInput[n] << endl; |
352 } | 368 } |
353 if (i+tN/2 > ncLength){ | 369 if (i+tN/2 > ncLength){ |
354 timestamp = Vamp::RealTime::fromSeconds(ncTimestamps[i].sec + timestampInc); | 370 feature.timestamp = Vamp::RealTime::fromSeconds(ncTimestamps[i].sec + timestampInc); |
355 } | 371 } |
356 else{ | 372 else{ |
357 timestamp = ncTimestamps[i + tN/2]; | 373 feature.timestamp = ncTimestamps[i + tN/2]; |
358 } | 374 } |
359 | 375 |
360 FFT::forward(tN, fftInput, NULL, fftOutputReal, fftOutputImag); | 376 FFT::forward(tN, fftInput, NULL, fftOutputReal, fftOutputImag); |
361 | 377 |
362 //TODO: sample at logarithmic spacing | 378 //TODO: sample at logarithmic spacing |
363 for(int k = 0; k < tN; k++){ | 379 for(int k = 0; k < tN; k++){ |
364 double fftOutputPower = (fftOutputReal[k]*fftOutputReal[k] + fftOutputImag[k]*fftOutputImag[k]); //Magnitude or power? | 380 float fftOutputPower = (fftOutputReal[k]*fftOutputReal[k] + fftOutputImag[k]*fftOutputImag[k]); //Magnitude or power? |
365 assert (!isinf(fftOutputPower)); | |
366 | 381 |
367 feature.values.push_back(fftOutputPower); | 382 feature.values.push_back(fftOutputPower); |
368 } | 383 } |
369 | 384 |
370 i += thopSize; | 385 i += thopSize; |
371 start = 0; | 386 frameBeginOffset = 0; |
372 | 387 |
373 feature.timestamp = timestamp; | |
374 feature.hasTimestamp = true; | 388 feature.hasTimestamp = true; |
375 featureSet[0].push_back(feature); | 389 featureSet[0].push_back(feature); |
376 } | 390 } |
377 | 391 |
378 //Make sure this is called at the end of the function | 392 //Make sure this is called at the end of the function |