cannam@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@0: cannam@0: /* cannam@0: QM DSP Library cannam@0: cannam@0: Centre for Digital Music, Queen Mary, University of London. cannam@0: This file copyright 2005-2006 Christian Landone. cannam@0: All rights reserved. cannam@0: */ cannam@0: cannam@0: #include "PeakPicking.h" cannam@16: #include "maths/Polyfit.h" cannam@0: cannam@12: #include cannam@47: #include cannam@47: cannam@0: cannam@0: ////////////////////////////////////////////////////////////////////// cannam@0: // Construction/Destruction cannam@0: ////////////////////////////////////////////////////////////////////// cannam@0: cannam@0: PeakPicking::PeakPicking( PPickParams Config ) cannam@0: { cannam@0: m_workBuffer = NULL; cannam@0: initialise( Config ); cannam@0: } cannam@0: cannam@0: PeakPicking::~PeakPicking() cannam@0: { cannam@0: deInitialise(); cannam@0: } cannam@0: cannam@0: void PeakPicking::initialise( PPickParams Config ) cannam@0: { cannam@0: m_DFLength = Config.length ; cannam@0: Qfilta = Config.QuadThresh.a ; cannam@0: Qfiltb = Config.QuadThresh.b ; cannam@0: Qfiltc = Config.QuadThresh.c ; cannam@0: cannam@0: m_DFProcessingParams.length = m_DFLength; cannam@0: m_DFProcessingParams.LPOrd = Config.LPOrd; cannam@0: m_DFProcessingParams.LPACoeffs = Config.LPACoeffs; cannam@0: m_DFProcessingParams.LPBCoeffs = Config.LPBCoeffs; cannam@0: m_DFProcessingParams.winPre = Config.WinT.pre; cannam@0: m_DFProcessingParams.winPost = Config.WinT.post; cannam@0: m_DFProcessingParams.AlphaNormParam = Config.alpha; cannam@0: m_DFProcessingParams.isMedianPositive = false; cannam@0: cannam@0: m_DFSmoothing = new DFProcess( m_DFProcessingParams ); cannam@0: cannam@0: m_workBuffer = new double[ m_DFLength ]; cannam@0: memset( m_workBuffer, 0, sizeof(double)*m_DFLength); cannam@0: } cannam@0: cannam@0: void PeakPicking::deInitialise() cannam@0: { cannam@0: delete [] m_workBuffer; cannam@0: delete m_DFSmoothing; cannam@0: m_workBuffer = NULL; cannam@0: } cannam@0: cannam@0: void PeakPicking::process( double* src, unsigned int len, vector &onsets ) cannam@0: { cannam@58: if (len < 4) return; cannam@58: cannam@0: vector m_maxima; cannam@0: cannam@0: // Signal conditioning cannam@0: m_DFSmoothing->process( src, m_workBuffer ); cannam@0: cannam@0: for( unsigned int u = 0; u < len; u++) cannam@0: { cannam@0: m_maxima.push_back( m_workBuffer[ u ] ); cannam@0: } cannam@0: cannam@0: quadEval( m_maxima, onsets ); cannam@0: cannam@0: for( int b = 0; b < m_maxima.size(); b++) cannam@0: { cannam@0: src[ b ] = m_maxima[ b ]; cannam@0: } cannam@0: } cannam@0: cannam@0: int PeakPicking::quadEval( vector &src, vector &idx ) cannam@0: { cannam@0: unsigned int maxLength; cannam@0: cannam@0: vector m_maxIndex; cannam@0: vector m_onsetPosition; cannam@0: cannam@0: vector m_maxFit; cannam@0: vector m_poly; cannam@0: vector m_err; cannam@0: cannam@0: double p; cannam@0: cannam@0: m_poly.push_back(0); cannam@0: m_poly.push_back(0); cannam@0: m_poly.push_back(0); cannam@0: cannam@0: for( int t = -2; t < 3; t++) cannam@0: { cannam@0: m_err.push_back( (double)t ); cannam@0: } cannam@0: for( unsigned int i = 2; i < src.size() - 2; i++) cannam@0: { cannam@12: if( (src[i] > src[i-1]) && (src[i] > src[i+1]) && (src[i] > 0) ) cannam@0: { cannam@12: // m_maxIndex.push_back( i + 1 ); cannam@12: m_maxIndex.push_back(i); cannam@0: } cannam@0: } cannam@0: cannam@0: maxLength = m_maxIndex.size(); cannam@0: cannam@0: double selMax = 0; cannam@0: cannam@0: for( unsigned int j = 0; j < maxLength ; j++) cannam@0: { cannam@12: for (int k = -2; k <= 2; ++k) cannam@0: { cannam@0: selMax = src[ m_maxIndex[j] + k ] ; cannam@0: m_maxFit.push_back(selMax); cannam@0: } cannam@0: cannam@0: p = TPolyFit::PolyFit2( m_err, m_maxFit, m_poly); cannam@0: cannam@0: double f = m_poly[0]; cannam@0: double g = m_poly[1]; cannam@0: double h = m_poly[2]; cannam@0: cannam@0: int kk = m_poly.size(); cannam@12: cannam@12: if (h < -Qfilta || f > Qfiltc) cannam@12: { cannam@12: idx.push_back(m_maxIndex[j]); cannam@12: } cannam@0: cannam@12: m_maxFit.clear(); cannam@0: } cannam@0: cannam@0: return 1; cannam@0: }