qm-dsp  1.8
PeakPicking.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     QM DSP Library
00005 
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file 2005-2006 Christian Landone.
00008 
00009     Modifications:
00010 
00011     - delta threshold
00012     Description: add delta threshold used as offset in the smoothed
00013     detection function
00014     Author: Mathieu Barthet
00015     Date: June 2010
00016 
00017     This program is free software; you can redistribute it and/or
00018     modify it under the terms of the GNU General Public License as
00019     published by the Free Software Foundation; either version 2 of the
00020     License, or (at your option) any later version.  See the file
00021     COPYING included with this distribution for more information.    
00022 */
00023 
00024 #include "PeakPicking.h"
00025 #include "maths/Polyfit.h"
00026 
00027 #include <iostream>
00028 #include <cstring>
00029 
00030 
00032 // Construction/Destruction
00034 
00035 PeakPicking::PeakPicking( PPickParams Config )
00036 {
00037     m_workBuffer = NULL;
00038     initialise( Config );
00039 }
00040 
00041 PeakPicking::~PeakPicking()
00042 {
00043     deInitialise();
00044 }
00045 
00046 void PeakPicking::initialise( PPickParams Config )
00047 {
00048     m_DFLength = Config.length ;
00049     Qfilta = Config.QuadThresh.a ;
00050     Qfiltb = Config.QuadThresh.b ;
00051     Qfiltc = Config.QuadThresh.c ;
00052         
00053     m_DFProcessingParams.length = m_DFLength; 
00054     m_DFProcessingParams.LPOrd = Config.LPOrd; 
00055     m_DFProcessingParams.LPACoeffs = Config.LPACoeffs; 
00056     m_DFProcessingParams.LPBCoeffs = Config.LPBCoeffs; 
00057     m_DFProcessingParams.winPre  = Config.WinT.pre;
00058     m_DFProcessingParams.winPost = Config.WinT.post; 
00059     m_DFProcessingParams.AlphaNormParam = Config.alpha;
00060     m_DFProcessingParams.isMedianPositive = false;
00061     m_DFProcessingParams.Delta = Config.delta; //add the delta threshold as an adjustable parameter
00062 
00063     m_DFSmoothing = new DFProcess( m_DFProcessingParams );
00064 
00065     m_workBuffer = new double[ m_DFLength ];
00066     memset( m_workBuffer, 0, sizeof(double)*m_DFLength);
00067 }
00068 
00069 void PeakPicking::deInitialise()
00070 {
00071     delete [] m_workBuffer;
00072     delete m_DFSmoothing;
00073     m_workBuffer = NULL;
00074 }
00075 
00076 void PeakPicking::process( double* src, unsigned int len, vector<int> &onsets )
00077 {
00078     if (len < 4) return;
00079 
00080     vector <double> m_maxima;   
00081 
00082     // Signal conditioning 
00083     m_DFSmoothing->process( src, m_workBuffer );
00084         
00085     for( unsigned int u = 0; u < len; u++)
00086     {
00087         m_maxima.push_back( m_workBuffer[ u ] );                
00088     }
00089         
00090     quadEval( m_maxima, onsets );
00091 
00092     for( int b = 0; b <  (int)m_maxima.size(); b++)
00093     {
00094         src[ b ] = m_maxima[ b ];
00095     }
00096 }
00097 
00098 int PeakPicking::quadEval( vector<double> &src, vector<int> &idx )
00099 {
00100     unsigned int maxLength;
00101 
00102     vector <int> m_maxIndex;
00103     vector <int> m_onsetPosition;
00104         
00105     vector <double> m_maxFit;
00106     vector <double> m_poly;
00107     vector <double> m_err;
00108 
00109     m_poly.push_back(0);
00110     m_poly.push_back(0);
00111     m_poly.push_back(0);
00112 
00113     for(  int t = -2; t < 3; t++)
00114     {
00115         m_err.push_back( (double)t );
00116     }
00117     for( unsigned int i = 2; i < src.size() - 2; i++)
00118     {
00119         if( (src[i] > src[i-1]) && (src[i] > src[i+1]) && (src[i] > 0) )
00120         {
00121 //          m_maxIndex.push_back(  i + 1 );
00122             m_maxIndex.push_back(i);
00123         }
00124     }
00125 
00126     maxLength = m_maxIndex.size();
00127 
00128     double selMax = 0;
00129 
00130     for( unsigned int j = 0; j < maxLength ; j++)
00131     {
00132         for (int k = -2; k <= 2; ++k)
00133         {
00134             selMax = src[ m_maxIndex[j] + k ] ;
00135             m_maxFit.push_back(selMax);                 
00136         }
00137 
00138         TPolyFit::PolyFit2(m_err, m_maxFit, m_poly);
00139 
00140         double f = m_poly[0];
00141         double h = m_poly[2];
00142 
00143         if (h < -Qfilta || f > Qfiltc)
00144         {
00145             idx.push_back(m_maxIndex[j]);
00146         }
00147                 
00148         m_maxFit.clear();
00149     }
00150 
00151     return 1;
00152 }