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