Mercurial > hg > svcore
diff transform/BeatDetectionFunctionTransform.cpp @ 0:da6937383da8
initial import
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2006 16:33:16 +0000 |
parents | |
children | d86891498eef |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/transform/BeatDetectionFunctionTransform.cpp Tue Jan 10 16:33:16 2006 +0000 @@ -0,0 +1,154 @@ +/* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ + +/* + A waveform viewer and audio annotation editor. + Chris Cannam, Queen Mary University of London, 2005 + + This is experimental software. Not for distribution. +*/ + +#include "BeatDetectionFunctionTransform.h" + +#include "model/DenseTimeValueModel.h" +#include "model/SparseTimeValueModel.h" + +#include <iostream> +#include "dsp/onsets/DetectionFunction.h" +#include "dsp/tempotracking/TempoTrack.h" + + +BeatDetectionFunctionTransform::BeatDetectionFunctionTransform(Model *inputModel) : + Transform(inputModel) +{ + m_output = new SparseTimeValueModel(inputModel->getSampleRate(), 1, + 0.0, 0.0, false); +} + +BeatDetectionFunctionTransform::~BeatDetectionFunctionTransform() +{ + // parent does it all +} + +TransformName +BeatDetectionFunctionTransform::getName() +{ + return tr("Beat Detection Function"); +} + +void +BeatDetectionFunctionTransform::run() +{ + SparseTimeValueModel *output = getOutput(); + DenseTimeValueModel *input = getInput(); + if (!input) { + std::cerr << "BeatDetectionFunctionTransform::run: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl; + return; + } + + DFConfig config; + + config.DFType = DF_COMPLEXSD; + + // Step resolution for the detection function in seconds + config.stepSecs = 0.01161; + + // Step resolution for the detection function in samples + config.stepSize = (unsigned int)floor((double)input->getSampleRate() * + config.stepSecs ); + + config.frameLength = 2 * config.stepSize; + + unsigned int stepSize = config.stepSize; + unsigned int frameLength = config.frameLength; + + output->setResolution(stepSize); + + //Tempo Tracking Configuration Parameters + TTParams ttparams; + + // Low Pass filter coefficients for detection function smoothing + double* aCoeffs = new double[3]; + double* bCoeffs = new double[3]; + + aCoeffs[ 0 ] = 1; + aCoeffs[ 1 ] = -0.5949; + aCoeffs[ 2 ] = 0.2348; + bCoeffs[ 0 ] = 0.1600; + bCoeffs[ 1 ] = 0.3200; + bCoeffs[ 2 ] = 0.1600; + + ttparams.winLength = 512; + ttparams.lagLength = 128; + ttparams.LPOrd = 2; + ttparams.LPACoeffs = aCoeffs; + ttparams.LPBCoeffs = bCoeffs; + ttparams.alpha = 9; + ttparams.WinT.post = 8; + ttparams.WinT.pre = 7; + + //////////////////////////////////////////////////////////// + // DetectionFunction + //////////////////////////////////////////////////////////// + // Instantiate and configure detection function object + + DetectionFunction df(config); + + size_t origin = input->getStartFrame(); + size_t frameCount = input->getEndFrame() - origin; + size_t blocks = (frameCount / stepSize); + if (blocks * stepSize < frameCount) ++blocks; + + double *buffer = new double[frameLength]; + + // DF output with causal extension + unsigned int clen = blocks + ttparams.winLength; + double *dfOutput = new double[clen]; + + std::cerr << "Running beat detection function at step size " << stepSize << "..." << std::endl; + + for (size_t i = 0; i < clen; ++i) { + +// std::cerr << "block " << i << "/" << clen << std::endl; +// std::cerr << "."; + + if (i < blocks) { + size_t got = input->getValues(-1, //!!! needs to come from parent layer -- which is not supposed to be in scope at this point + origin + i * stepSize, + origin + i * stepSize + frameLength, + buffer); + while (got < frameLength) buffer[got++] = 0.0; + dfOutput[i] = df.process(buffer); + } else { + dfOutput[i] = 0.0; + } + + output->addPoint(SparseTimeValueModel::Point + (i * stepSize, dfOutput[i], + QString("%1").arg(dfOutput[i]))); +// m_w->m_bdf->setCompletion(i * 99 / clen); + output->setCompletion(i * 99 / clen); + + if (m_deleting) { + delete [] buffer; + delete [] dfOutput; + delete [] aCoeffs; + delete [] bCoeffs; + return; + } + } + + output->setCompletion(100); +} + +DenseTimeValueModel * +BeatDetectionFunctionTransform::getInput() +{ + return dynamic_cast<DenseTimeValueModel *>(getInputModel()); +} + +SparseTimeValueModel * +BeatDetectionFunctionTransform::getOutput() +{ + return static_cast<SparseTimeValueModel *>(getOutputModel()); +} +