Mercurial > hg > vamp-tempogram
comparison TempogramPlugin.cpp @ 18:89bc9e5199d7
* Added Cyclic Tempogram output - very buggy right now!
author | Carl Bussey <c.bussey@se10.qmul.ac.uk> |
---|---|
date | Thu, 14 Aug 2014 16:43:26 +0100 |
parents | 203551cbad47 |
children | e90a4797e579 |
comparison
equal
deleted
inserted
replaced
17:1e4c02ca8b81 | 18:89bc9e5199d7 |
---|---|
12 using Vamp::RealTime; | 12 using Vamp::RealTime; |
13 using namespace std; | 13 using namespace std; |
14 | 14 |
15 TempogramPlugin::TempogramPlugin(float inputSampleRate) : | 15 TempogramPlugin::TempogramPlugin(float inputSampleRate) : |
16 Plugin(inputSampleRate), | 16 Plugin(inputSampleRate), |
17 m_blockSize(0), | 17 m_inputBlockSize(0), //host parameter |
18 m_stepSize(0), | 18 m_inputStepSize(0), //host parameter |
19 m_compressionConstant(1000), //parameter | 19 m_noveltyCurveMinDB(0), //set in initialise() |
20 m_minDB(0), | 20 m_noveltyCurveCompressionConstant(1000), //parameter |
21 m_log2WindowLength(10), //parameter | 21 m_tempogramLog2WindowLength(10), //parameter |
22 m_windowLength(pow((float)2,m_log2WindowLength)), | 22 m_tempogramWindowLength(pow((float)2,m_tempogramLog2WindowLength)), |
23 m_log2FftLength(m_log2WindowLength), | 23 m_tempogramLog2FftLength(m_tempogramLog2WindowLength), //parameter |
24 m_fftLength(m_windowLength), | 24 m_tempogramFftLength(m_tempogramWindowLength), |
25 m_log2HopSize(6), //parameter | 25 m_tempogramLog2HopSize(6), //parameter |
26 m_hopSize(pow((float)2,m_log2HopSize)), | 26 m_tempogramHopSize(pow((float)2,m_tempogramLog2HopSize)), |
27 m_minBPM(30), | 27 m_tempogramMinBPM(30), //parameter |
28 m_maxBPM(480), | 28 m_tempogramMaxBPM(480), //parameter |
29 m_minBin(0), //set in initialise() | 29 m_tempogramMinBin(0), //set in initialise() |
30 m_maxBin(0) //set in initialise() | 30 m_tempogramMaxBin(0), //set in initialise() |
31 m_cyclicTempogramMinBPM(30), //reset in initialise() | |
32 m_cyclicTempogramNumberOfOctaves(0), //set in initialise() | |
33 m_cyclicTempogramOctaveDivider(30) //parameter | |
31 | 34 |
32 // Also be sure to set your plugin parameters (presumably stored | 35 // Also be sure to set your plugin parameters (presumably stored |
33 // in member variables) to their default values here -- the host | 36 // in member variables) to their default values here -- the host |
34 // will not do that for you | 37 // will not do that for you |
35 { | 38 { |
189 } | 192 } |
190 list.push_back(d4); | 193 list.push_back(d4); |
191 | 194 |
192 ParameterDescriptor d5; | 195 ParameterDescriptor d5; |
193 d5.identifier = "minBPM"; | 196 d5.identifier = "minBPM"; |
194 d5.name = "Tempogram Minimum BPM"; | 197 d5.name = "(Cyclic) Tempogram Minimum BPM"; |
195 d5.description = "The minimum BPM of the tempogram output bins."; | 198 d5.description = "The minimum BPM of the tempogram output bins."; |
196 d5.unit = ""; | 199 d5.unit = ""; |
197 d5.minValue = 0; | 200 d5.minValue = 0; |
198 d5.maxValue = 2000; | 201 d5.maxValue = 2000; |
199 d5.defaultValue = 30; | 202 d5.defaultValue = 30; |
201 d5.quantizeStep = 5; | 204 d5.quantizeStep = 5; |
202 list.push_back(d5); | 205 list.push_back(d5); |
203 | 206 |
204 ParameterDescriptor d6; | 207 ParameterDescriptor d6; |
205 d6.identifier = "maxBPM"; | 208 d6.identifier = "maxBPM"; |
206 d6.name = "Tempogram Maximum BPM"; | 209 d6.name = "(Cyclic) Tempogram Maximum BPM"; |
207 d6.description = "The minimum BPM of the tempogram output bins."; | 210 d6.description = "The maximum BPM of the tempogram output bins."; |
208 d6.unit = ""; | 211 d6.unit = ""; |
209 d6.minValue = 30; | 212 d6.minValue = 30; |
210 d6.maxValue = 2000; | 213 d6.maxValue = 2000; |
211 d6.defaultValue = 480; | 214 d6.defaultValue = 480; |
212 d6.isQuantized = true; | 215 d6.isQuantized = true; |
213 d6.quantizeStep = 5; | 216 d6.quantizeStep = 5; |
214 list.push_back(d6); | 217 list.push_back(d6); |
218 | |
219 ParameterDescriptor d7; | |
220 d7.identifier = "octDiv"; | |
221 d7.name = "Cyclic Tempogram Octave Divider"; | |
222 d7.description = "The number bins within each octave."; | |
223 d7.unit = ""; | |
224 d7.minValue = 5; | |
225 d7.maxValue = 60; | |
226 d7.defaultValue = 30; | |
227 d7.isQuantized = true; | |
228 d7.quantizeStep = 1; | |
229 list.push_back(d7); | |
215 | 230 |
216 return list; | 231 return list; |
217 } | 232 } |
218 | 233 |
219 float | 234 float |
220 TempogramPlugin::getParameter(string identifier) const | 235 TempogramPlugin::getParameter(string identifier) const |
221 { | 236 { |
222 if (identifier == "C") { | 237 if (identifier == "C") { |
223 return m_compressionConstant; // return the ACTUAL current value of your parameter here! | 238 return m_noveltyCurveCompressionConstant; // return the ACTUAL current value of your parameter here! |
224 } | 239 } |
225 else if (identifier == "log2TN"){ | 240 else if (identifier == "log2TN"){ |
226 return m_log2WindowLength; | 241 return m_tempogramLog2WindowLength; |
227 } | 242 } |
228 else if (identifier == "log2HopSize"){ | 243 else if (identifier == "log2HopSize"){ |
229 return m_log2HopSize; | 244 return m_tempogramLog2HopSize; |
230 } | 245 } |
231 else if (identifier == "log2FftLength"){ | 246 else if (identifier == "log2FftLength"){ |
232 return m_log2FftLength; | 247 return m_tempogramLog2FftLength; |
233 } | 248 } |
234 else if (identifier == "minBPM") { | 249 else if (identifier == "minBPM") { |
235 return m_minBPM; | 250 return m_tempogramMinBPM; |
236 } | 251 } |
237 else if (identifier == "maxBPM"){ | 252 else if (identifier == "maxBPM"){ |
238 return m_maxBPM; | 253 return m_tempogramMaxBPM; |
254 } | |
255 else if (identifier == "octDiv"){ | |
256 return m_cyclicTempogramOctaveDivider; | |
239 } | 257 } |
240 | 258 |
241 return 0; | 259 return 0; |
242 } | 260 } |
243 | 261 |
244 void | 262 void |
245 TempogramPlugin::setParameter(string identifier, float value) | 263 TempogramPlugin::setParameter(string identifier, float value) |
246 { | 264 { |
247 | 265 |
248 if (identifier == "C") { | 266 if (identifier == "C") { |
249 m_compressionConstant = value; // set the actual value of your parameter | 267 m_noveltyCurveCompressionConstant = value; // set the actual value of your parameter |
250 } | 268 } |
251 else if (identifier == "log2TN") { | 269 else if (identifier == "log2TN") { |
252 m_windowLength = pow(2,value); | 270 m_tempogramWindowLength = pow(2,value); |
253 m_log2WindowLength = value; | 271 m_tempogramLog2WindowLength = value; |
254 } | 272 } |
255 else if (identifier == "log2HopSize"){ | 273 else if (identifier == "log2HopSize"){ |
256 m_hopSize = pow(2,value); | 274 m_tempogramHopSize = pow(2,value); |
257 m_log2HopSize = value; | 275 m_tempogramLog2HopSize = value; |
258 } | 276 } |
259 else if (identifier == "log2HopFftLength"){ | 277 else if (identifier == "log2FftLength"){ |
260 m_fftLength = pow(2,value); | 278 m_tempogramFftLength = pow(2,value); |
261 m_log2FftLength = value; | 279 m_tempogramLog2FftLength = value; |
262 } | 280 } |
263 else if (identifier == "minBPM") { | 281 else if (identifier == "minBPM") { |
264 m_minBPM = value; | 282 m_tempogramMinBPM = value; |
265 } | 283 } |
266 else if (identifier == "maxBPM"){ | 284 else if (identifier == "maxBPM"){ |
267 m_maxBPM = value; | 285 m_tempogramMaxBPM = value; |
286 } | |
287 else if (identifier == "octDiv"){ | |
288 m_cyclicTempogramOctaveDivider = value; | |
268 } | 289 } |
269 | 290 |
270 } | 291 } |
271 | 292 |
272 void TempogramPlugin::updateBPMParameters(){ | 293 void TempogramPlugin::updateBPMParameters(){ |
309 OutputList list; | 330 OutputList list; |
310 | 331 |
311 // See OutputDescriptor documentation for the possibilities here. | 332 // See OutputDescriptor documentation for the possibilities here. |
312 // Every plugin must have at least one output. | 333 // Every plugin must have at least one output. |
313 | 334 |
314 OutputDescriptor d; | 335 OutputDescriptor d1; |
315 float d_sampleRate; | 336 float d_sampleRate; |
316 float tempogramInputSampleRate = (float)m_inputSampleRate/m_stepSize; | 337 float tempogramInputSampleRate = (float)m_inputSampleRate/m_inputStepSize; |
317 | 338 |
318 d.identifier = "tempogram"; | 339 d1.identifier = "tempogram"; |
319 d.name = "Tempogram"; | 340 d1.name = "Tempogram"; |
320 d.description = "Tempogram"; | 341 d1.description = "Tempogram"; |
321 d.unit = "BPM"; | 342 d1.unit = "BPM"; |
322 d.hasFixedBinCount = true; | 343 d1.hasFixedBinCount = true; |
323 d.binCount = m_maxBin - m_minBin + 1; | 344 d1.binCount = m_tempogramMaxBin - m_tempogramMinBin + 1; |
324 d.hasKnownExtents = false; | 345 d1.hasKnownExtents = false; |
325 d.isQuantized = false; | 346 d1.isQuantized = false; |
326 d.sampleType = OutputDescriptor::FixedSampleRate; | 347 d1.sampleType = OutputDescriptor::FixedSampleRate; |
327 d_sampleRate = tempogramInputSampleRate/m_hopSize; | 348 d_sampleRate = tempogramInputSampleRate/m_tempogramHopSize; |
328 d.sampleRate = d_sampleRate > 0.0 && !isnan(d_sampleRate) ? d_sampleRate : 0.0; | 349 d1.sampleRate = d_sampleRate > 0.0 && !isnan(d_sampleRate) ? d_sampleRate : 0.0; |
329 for(int i = m_minBin; i <= (int)m_maxBin; i++){ | 350 for(int i = m_tempogramMinBin; i <= (int)m_tempogramMaxBin; i++){ |
330 float w = ((float)i/m_fftLength)*(tempogramInputSampleRate); | 351 float w = ((float)i/m_tempogramFftLength)*(tempogramInputSampleRate); |
331 d.binNames.push_back(floatToString(w*60)); | 352 d1.binNames.push_back(floatToString(w*60)); |
332 } | 353 } |
333 d.hasDuration = false; | 354 d1.hasDuration = false; |
334 list.push_back(d); | 355 list.push_back(d1); |
335 | 356 |
336 d.identifier = "nc"; | 357 OutputDescriptor d2; |
337 d.name = "Novelty Curve"; | 358 d2.identifier = "nc"; |
338 d.description = "Novelty Curve"; | 359 d2.name = "Novelty Curve"; |
339 d.unit = ""; | 360 d2.description = "Novelty Curve"; |
340 d.hasFixedBinCount = true; | 361 d2.unit = ""; |
341 d.binCount = 1; | 362 d2.hasFixedBinCount = true; |
342 d.hasKnownExtents = false; | 363 d2.binCount = 1; |
343 d.isQuantized = false; | 364 d2.hasKnownExtents = false; |
344 d.sampleType = OutputDescriptor::FixedSampleRate; | 365 d2.isQuantized = false; |
366 d2.sampleType = OutputDescriptor::FixedSampleRate; | |
345 d_sampleRate = tempogramInputSampleRate; | 367 d_sampleRate = tempogramInputSampleRate; |
346 d.sampleRate = d_sampleRate > 0 && !isnan(d_sampleRate) ? d_sampleRate : 0.0; | 368 d2.sampleRate = d_sampleRate > 0 && !isnan(d_sampleRate) ? d_sampleRate : 0; |
347 d.hasDuration = false; | 369 d2.hasDuration = false; |
348 list.push_back(d); | 370 list.push_back(d2); |
371 | |
372 OutputDescriptor d3; | |
373 d3.identifier = "cyclicTempogram"; | |
374 d3.name = "Cyclic Tempogram"; | |
375 d3.description = "Cyclic Tempogram"; | |
376 d3.unit = ""; | |
377 d3.hasFixedBinCount = true; | |
378 d3.binCount = m_cyclicTempogramOctaveDivider > 0 && !isnan(m_cyclicTempogramOctaveDivider) ? m_cyclicTempogramOctaveDivider : 0; | |
379 d3.hasKnownExtents = false; | |
380 d3.isQuantized = false; | |
381 d3.sampleType = OutputDescriptor::FixedSampleRate; | |
382 d_sampleRate = tempogramInputSampleRate/m_tempogramHopSize; | |
383 d3.sampleRate = d_sampleRate > 0.0 && !isnan(d_sampleRate) ? d_sampleRate : 0; | |
384 d3.hasDuration = false; | |
385 list.push_back(d3); | |
349 | 386 |
350 return list; | 387 return list; |
351 } | 388 } |
352 | 389 |
353 bool | 390 bool |
355 { | 392 { |
356 if (channels < getMinChannelCount() || | 393 if (channels < getMinChannelCount() || |
357 channels > getMaxChannelCount()) return false; | 394 channels > getMaxChannelCount()) return false; |
358 | 395 |
359 // Real initialisation work goes here! | 396 // Real initialisation work goes here! |
360 m_blockSize = blockSize; | 397 m_inputBlockSize = blockSize; |
361 m_stepSize = stepSize; | 398 m_inputStepSize = stepSize; |
362 m_minDB = pow(10,(float)-74/20); | 399 m_noveltyCurveMinDB = pow(10,(float)-74/20); |
363 | 400 |
364 if (m_fftLength < m_windowLength){ | 401 if (m_tempogramFftLength < m_tempogramWindowLength){ |
365 m_fftLength = m_windowLength; | 402 m_tempogramFftLength = m_tempogramWindowLength; |
366 } | 403 } |
367 if (m_minBPM > m_maxBPM){ | 404 if (m_tempogramMinBPM > m_tempogramMaxBPM){ |
368 m_minBPM = 30; | 405 m_tempogramMinBPM = 30; |
369 m_maxBPM = 480; | 406 m_tempogramMaxBPM = 480; |
370 } | 407 } |
371 float tempogramInputSampleRate = (float)m_inputSampleRate/m_stepSize; | 408 |
372 m_minBin = (unsigned int)(max(floor(((m_minBPM/60)/tempogramInputSampleRate)*m_fftLength), (float)0.0)); | 409 float tempogramInputSampleRate = (float)m_inputSampleRate/m_inputStepSize; |
373 m_maxBin = (unsigned int)(min(ceil(((m_maxBPM/60)/tempogramInputSampleRate)*m_fftLength), (float)m_fftLength/2)); | 410 m_tempogramMinBin = (unsigned int)(max(floor(((m_tempogramMinBPM/60)/tempogramInputSampleRate)*m_tempogramFftLength), (float)0.0)); |
374 | 411 m_tempogramMaxBin = (unsigned int)(min(ceil(((m_tempogramMaxBPM/60)/tempogramInputSampleRate)*m_tempogramFftLength), (float)m_tempogramFftLength/2)); |
375 m_spectrogram = SpectrogramTransposed(m_blockSize/2 + 1); | 412 |
413 if (m_tempogramMinBPM > m_cyclicTempogramMinBPM) m_cyclicTempogramMinBPM = m_tempogramMinBPM; | |
414 float cyclicTempogramMaxBPM = 480; | |
415 if (m_tempogramMaxBPM < cyclicTempogramMaxBPM) cyclicTempogramMaxBPM = m_tempogramMaxBPM; | |
416 | |
417 m_spectrogram = SpectrogramTransposed(m_inputBlockSize/2 + 1); | |
418 | |
419 m_cyclicTempogramNumberOfOctaves = floor(log2(cyclicTempogramMaxBPM/m_cyclicTempogramMinBPM)); | |
420 int numberOfBinsInFirstOctave = bpmToBin(m_cyclicTempogramMinBPM); | |
421 if (m_cyclicTempogramOctaveDivider < numberOfBinsInFirstOctave) m_cyclicTempogramOctaveDivider = numberOfBinsInFirstOctave; | |
376 | 422 |
377 return true; | 423 return true; |
378 } | 424 } |
379 | 425 |
380 void TempogramPlugin::cleanup(){ | 426 void TempogramPlugin::cleanup(){ |
383 | 429 |
384 void | 430 void |
385 TempogramPlugin::reset() | 431 TempogramPlugin::reset() |
386 { | 432 { |
387 // Clear buffers, reset stored values, etc | 433 // Clear buffers, reset stored values, etc |
388 ncTimestamps.clear(); | 434 m_spectrogram = SpectrogramTransposed(m_inputBlockSize/2 + 1); |
389 m_spectrogram = SpectrogramTransposed(m_blockSize/2 + 1); | |
390 } | 435 } |
391 | 436 |
392 TempogramPlugin::FeatureSet | 437 TempogramPlugin::FeatureSet |
393 TempogramPlugin::process(const float *const *inputBuffers, Vamp::RealTime timestamp) | 438 TempogramPlugin::process(const float *const *inputBuffers, Vamp::RealTime timestamp) |
394 { | 439 { |
395 size_t n = m_blockSize/2 + 1; | 440 size_t n = m_inputBlockSize/2 + 1; |
396 | 441 |
397 FeatureSet featureSet; | 442 FeatureSet featureSet; |
398 Feature feature; | 443 Feature feature; |
399 | 444 |
400 const float *in = inputBuffers[0]; | 445 const float *in = inputBuffers[0]; |
401 | 446 |
402 //calculate magnitude of FrequencyDomain input | 447 //calculate magnitude of FrequencyDomain input |
403 for (unsigned int i = 0; i < n; i++){ | 448 for (unsigned int i = 0; i < n; i++){ |
404 float magnitude = sqrt(in[2*i] * in[2*i] + in[2*i + 1] * in[2*i + 1]); | 449 float magnitude = sqrt(in[2*i] * in[2*i] + in[2*i + 1] * in[2*i + 1]); |
405 magnitude = magnitude > m_minDB ? magnitude : m_minDB; | 450 magnitude = magnitude > m_noveltyCurveMinDB ? magnitude : m_noveltyCurveMinDB; |
406 m_spectrogram[i].push_back(magnitude); | 451 m_spectrogram[i].push_back(magnitude); |
407 } | 452 } |
408 | |
409 ncTimestamps.push_back(timestamp); //save timestamp | |
410 | 453 |
411 return featureSet; | 454 return featureSet; |
455 } | |
456 | |
457 vector<unsigned int> TempogramPlugin::calculateTempogramNearestNeighbourLogBins() const | |
458 { | |
459 vector<unsigned int> logBins; | |
460 | |
461 for (int i = 0; i < (int)ceil(m_cyclicTempogramNumberOfOctaves*m_cyclicTempogramOctaveDivider); i++){ | |
462 float bpm = m_cyclicTempogramMinBPM*pow(2.0f, (float)i/m_cyclicTempogramOctaveDivider); | |
463 int bin = bpmToBin(bpm); | |
464 | |
465 logBins.push_back(bin); | |
466 } | |
467 | |
468 return logBins; | |
469 } | |
470 | |
471 int TempogramPlugin::bpmToBin(const float &bpm) const | |
472 { | |
473 float w = (float)bpm/60; | |
474 float sampleRate = m_inputSampleRate/m_inputStepSize; | |
475 int bin = floor((float)m_tempogramFftLength*w/sampleRate + 0.5); | |
476 | |
477 if(bin < 0) bin = 0; | |
478 else if(bin > m_tempogramFftLength/2) bin = m_tempogramFftLength; | |
479 | |
480 return bin; | |
412 } | 481 } |
413 | 482 |
414 TempogramPlugin::FeatureSet | 483 TempogramPlugin::FeatureSet |
415 TempogramPlugin::getRemainingFeatures() | 484 TempogramPlugin::getRemainingFeatures() |
416 { | 485 { |
417 | 486 |
418 float * hannWindow = new float[m_windowLength]; | 487 float * hannWindow = new float[m_tempogramWindowLength]; |
419 for (unsigned int i = 0; i < m_windowLength; i++){ | 488 for (unsigned int i = 0; i < m_tempogramWindowLength; i++){ |
420 hannWindow[i] = 0.0; | 489 hannWindow[i] = 0.0; |
421 } | 490 } |
422 | 491 |
423 FeatureSet featureSet; | 492 FeatureSet featureSet; |
424 | 493 |
425 //initialise m_noveltyCurve processor | 494 //initialise m_noveltyCurve processor |
426 size_t numberOfBlocks = m_spectrogram[0].size(); | 495 size_t numberOfBlocks = m_spectrogram[0].size(); |
427 NoveltyCurveProcessor nc(m_inputSampleRate, m_blockSize, numberOfBlocks, m_compressionConstant); | 496 NoveltyCurveProcessor nc(m_inputSampleRate, m_inputBlockSize, numberOfBlocks, m_noveltyCurveCompressionConstant); |
428 m_noveltyCurve = nc.spectrogramToNoveltyCurve(m_spectrogram); //calculate novelty curve from magnitude data | 497 m_noveltyCurve = nc.spectrogramToNoveltyCurve(m_spectrogram); //calculate novelty curve from magnitude data |
429 | 498 |
430 //push novelty curve data to featureset 1 and set timestamps | 499 //push novelty curve data to featureset 1 and set timestamps |
431 for (unsigned int i = 0; i < numberOfBlocks; i++){ | 500 for (unsigned int i = 0; i < numberOfBlocks; i++){ |
432 Feature feature; | 501 Feature feature; |
435 //feature.timestamp = ncTimestamps[i]; | 504 //feature.timestamp = ncTimestamps[i]; |
436 featureSet[1].push_back(feature); | 505 featureSet[1].push_back(feature); |
437 } | 506 } |
438 | 507 |
439 //window function for spectrogram | 508 //window function for spectrogram |
440 WindowFunction::hanning(hannWindow, m_windowLength); | 509 WindowFunction::hanning(hannWindow, m_tempogramWindowLength); |
441 | 510 |
442 //initialise spectrogram processor | 511 //initialise spectrogram processor |
443 SpectrogramProcessor spectrogramProcessor(m_windowLength, m_fftLength, m_hopSize); | 512 SpectrogramProcessor spectrogramProcessor(m_tempogramWindowLength, m_tempogramFftLength, m_tempogramHopSize); |
444 //compute spectrogram from novelty curve data (i.e., tempogram) | 513 //compute spectrogram from novelty curve data (i.e., tempogram) |
445 Spectrogram tempogram = spectrogramProcessor.process(&m_noveltyCurve[0], numberOfBlocks, hannWindow); | 514 Tempogram tempogram = spectrogramProcessor.process(&m_noveltyCurve[0], numberOfBlocks, hannWindow); |
446 | 515 delete []hannWindow; |
447 int timePointer = m_hopSize-m_windowLength/2; | 516 hannWindow = 0; |
517 | |
448 int tempogramLength = tempogram.size(); | 518 int tempogramLength = tempogram.size(); |
449 | 519 |
450 //push tempogram data to featureset 0 and set timestamps. | 520 //push tempogram data to featureset 0 and set timestamps. |
451 for (int block = 0; block < tempogramLength; block++){ | 521 for (int block = 0; block < tempogramLength; block++){ |
452 Feature feature; | 522 Feature feature; |
453 | 523 |
454 //int timeMS = floor(1000*(m_stepSize*timePointer)/m_inputSampleRate + 0.5); | 524 assert(tempogram[block].size() == (m_tempogramFftLength/2 + 1)); |
455 | 525 for(int k = m_tempogramMinBin; k < (int)m_tempogramMaxBin; k++){ |
456 assert(tempogram[block].size() == (m_fftLength/2 + 1)); | |
457 for(int k = m_minBin; k < (int)m_maxBin; k++){ | |
458 feature.values.push_back(tempogram[block][k]); | 526 feature.values.push_back(tempogram[block][k]); |
459 //cout << tempogram[k][block] << endl; | |
460 } | 527 } |
461 feature.hasTimestamp = false; | 528 feature.hasTimestamp = false; |
462 //feature.timestamp = RealTime::fromMilliseconds(timeMS); | |
463 featureSet[0].push_back(feature); | 529 featureSet[0].push_back(feature); |
530 } | |
531 | |
532 //Calculate cyclic tempogram | |
533 vector<unsigned int> logBins = calculateTempogramNearestNeighbourLogBins(); | |
534 Tempogram cyclicTempogram; | |
535 | |
536 for (int block = 0; block < tempogramLength; block++){ | |
537 Feature feature; | |
464 | 538 |
465 timePointer += m_hopSize; | 539 for (int i = 0; i < m_cyclicTempogramOctaveDivider; i++){ |
466 } | 540 float sum = 0; |
467 | 541 for (int j = 0; j < m_cyclicTempogramNumberOfOctaves; j++){ |
468 delete []hannWindow; | 542 sum += tempogram[block][logBins[i+j*m_cyclicTempogramOctaveDivider]]; |
469 hannWindow = 0; | 543 } |
544 feature.values.push_back(sum/m_cyclicTempogramNumberOfOctaves); | |
545 } | |
546 | |
547 feature.hasTimestamp = false; | |
548 | |
549 featureSet[2].push_back(feature); | |
550 } | |
470 | 551 |
471 return featureSet; | 552 return featureSet; |
472 } | 553 } |