annotate transform/BeatDetectionFunctionTransform.cpp @ 6:44bbf5793d84

* Rework handling of layer properties in file I/O -- we now get the individual layers to load and save them rather than doing it via generic property lists in the base class, so as to ensure we read and write meaningful values rather than generic int values requiring conversion.
author Chris Cannam
date Thu, 19 Jan 2006 12:54:38 +0000
parents d86891498eef
children 39ae3dee27b9
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 A waveform viewer and audio annotation editor.
Chris@2 5 Chris Cannam, Queen Mary University of London, 2005-2006
Chris@0 6
Chris@0 7 This is experimental software. Not for distribution.
Chris@0 8 */
Chris@0 9
Chris@0 10 #include "BeatDetectionFunctionTransform.h"
Chris@0 11
Chris@0 12 #include "model/DenseTimeValueModel.h"
Chris@0 13 #include "model/SparseTimeValueModel.h"
Chris@0 14
Chris@0 15 #include <iostream>
Chris@0 16 #include "dsp/onsets/DetectionFunction.h"
Chris@0 17 #include "dsp/tempotracking/TempoTrack.h"
Chris@0 18
Chris@0 19
Chris@0 20 BeatDetectionFunctionTransform::BeatDetectionFunctionTransform(Model *inputModel) :
Chris@0 21 Transform(inputModel)
Chris@0 22 {
Chris@0 23 m_output = new SparseTimeValueModel(inputModel->getSampleRate(), 1,
Chris@0 24 0.0, 0.0, false);
Chris@0 25 }
Chris@0 26
Chris@0 27 BeatDetectionFunctionTransform::~BeatDetectionFunctionTransform()
Chris@0 28 {
Chris@0 29 // parent does it all
Chris@0 30 }
Chris@0 31
Chris@0 32 TransformName
Chris@0 33 BeatDetectionFunctionTransform::getName()
Chris@0 34 {
Chris@0 35 return tr("Beat Detection Function");
Chris@0 36 }
Chris@0 37
Chris@0 38 void
Chris@0 39 BeatDetectionFunctionTransform::run()
Chris@0 40 {
Chris@0 41 SparseTimeValueModel *output = getOutput();
Chris@0 42 DenseTimeValueModel *input = getInput();
Chris@0 43 if (!input) {
Chris@0 44 std::cerr << "BeatDetectionFunctionTransform::run: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl;
Chris@0 45 return;
Chris@0 46 }
Chris@0 47
Chris@0 48 DFConfig config;
Chris@0 49
Chris@0 50 config.DFType = DF_COMPLEXSD;
Chris@0 51
Chris@0 52 // Step resolution for the detection function in seconds
Chris@0 53 config.stepSecs = 0.01161;
Chris@0 54
Chris@0 55 // Step resolution for the detection function in samples
Chris@0 56 config.stepSize = (unsigned int)floor((double)input->getSampleRate() *
Chris@0 57 config.stepSecs );
Chris@0 58
Chris@0 59 config.frameLength = 2 * config.stepSize;
Chris@0 60
Chris@0 61 unsigned int stepSize = config.stepSize;
Chris@0 62 unsigned int frameLength = config.frameLength;
Chris@0 63
Chris@0 64 output->setResolution(stepSize);
Chris@0 65
Chris@0 66 //Tempo Tracking Configuration Parameters
Chris@0 67 TTParams ttparams;
Chris@0 68
Chris@0 69 // Low Pass filter coefficients for detection function smoothing
Chris@0 70 double* aCoeffs = new double[3];
Chris@0 71 double* bCoeffs = new double[3];
Chris@0 72
Chris@0 73 aCoeffs[ 0 ] = 1;
Chris@0 74 aCoeffs[ 1 ] = -0.5949;
Chris@0 75 aCoeffs[ 2 ] = 0.2348;
Chris@0 76 bCoeffs[ 0 ] = 0.1600;
Chris@0 77 bCoeffs[ 1 ] = 0.3200;
Chris@0 78 bCoeffs[ 2 ] = 0.1600;
Chris@0 79
Chris@0 80 ttparams.winLength = 512;
Chris@0 81 ttparams.lagLength = 128;
Chris@0 82 ttparams.LPOrd = 2;
Chris@0 83 ttparams.LPACoeffs = aCoeffs;
Chris@0 84 ttparams.LPBCoeffs = bCoeffs;
Chris@0 85 ttparams.alpha = 9;
Chris@0 86 ttparams.WinT.post = 8;
Chris@0 87 ttparams.WinT.pre = 7;
Chris@0 88
Chris@0 89 ////////////////////////////////////////////////////////////
Chris@0 90 // DetectionFunction
Chris@0 91 ////////////////////////////////////////////////////////////
Chris@0 92 // Instantiate and configure detection function object
Chris@0 93
Chris@0 94 DetectionFunction df(config);
Chris@0 95
Chris@0 96 size_t origin = input->getStartFrame();
Chris@0 97 size_t frameCount = input->getEndFrame() - origin;
Chris@0 98 size_t blocks = (frameCount / stepSize);
Chris@0 99 if (blocks * stepSize < frameCount) ++blocks;
Chris@0 100
Chris@0 101 double *buffer = new double[frameLength];
Chris@0 102
Chris@0 103 // DF output with causal extension
Chris@0 104 unsigned int clen = blocks + ttparams.winLength;
Chris@0 105 double *dfOutput = new double[clen];
Chris@0 106
Chris@0 107 std::cerr << "Running beat detection function at step size " << stepSize << "..." << std::endl;
Chris@0 108
Chris@0 109 for (size_t i = 0; i < clen; ++i) {
Chris@0 110
Chris@0 111 // std::cerr << "block " << i << "/" << clen << std::endl;
Chris@0 112 // std::cerr << ".";
Chris@0 113
Chris@0 114 if (i < blocks) {
Chris@0 115 size_t got = input->getValues(-1, //!!! needs to come from parent layer -- which is not supposed to be in scope at this point
Chris@0 116 origin + i * stepSize,
Chris@0 117 origin + i * stepSize + frameLength,
Chris@0 118 buffer);
Chris@0 119 while (got < frameLength) buffer[got++] = 0.0;
Chris@0 120 dfOutput[i] = df.process(buffer);
Chris@0 121 } else {
Chris@0 122 dfOutput[i] = 0.0;
Chris@0 123 }
Chris@0 124
Chris@0 125 output->addPoint(SparseTimeValueModel::Point
Chris@0 126 (i * stepSize, dfOutput[i],
Chris@0 127 QString("%1").arg(dfOutput[i])));
Chris@0 128 // m_w->m_bdf->setCompletion(i * 99 / clen);
Chris@0 129 output->setCompletion(i * 99 / clen);
Chris@0 130
Chris@0 131 if (m_deleting) {
Chris@0 132 delete [] buffer;
Chris@0 133 delete [] dfOutput;
Chris@0 134 delete [] aCoeffs;
Chris@0 135 delete [] bCoeffs;
Chris@0 136 return;
Chris@0 137 }
Chris@0 138 }
Chris@0 139
Chris@0 140 output->setCompletion(100);
Chris@0 141 }
Chris@0 142
Chris@0 143 DenseTimeValueModel *
Chris@0 144 BeatDetectionFunctionTransform::getInput()
Chris@0 145 {
Chris@0 146 return dynamic_cast<DenseTimeValueModel *>(getInputModel());
Chris@0 147 }
Chris@0 148
Chris@0 149 SparseTimeValueModel *
Chris@0 150 BeatDetectionFunctionTransform::getOutput()
Chris@0 151 {
Chris@0 152 return static_cast<SparseTimeValueModel *>(getOutputModel());
Chris@0 153 }
Chris@0 154