CircularPeakPicking.hxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2006 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #ifndef CircularPeakPicking_hxx
00023 #define CircularPeakPicking_hxx
00024 #include <list>
00025 #include <vector>
00026 
00027 namespace Simac
00028 {
00029 
00045 class CircularPeakPicking
00046 {
00047 public:
00048         typedef std::vector<std::pair<double, double> > PeakList;
00049 private:
00050         PeakList _output;
00051         unsigned int _maxSize;
00052         double _binSize;
00053         double _offset;
00054 public:
00055         CircularPeakPicking(unsigned chromagramSize, double binSize=1.0, double offset=0.0)
00056                 : _maxSize(chromagramSize), _binSize(binSize), _offset(offset)
00057         {
00058                 _output.reserve(chromagramSize);
00059         }
00070         std::pair<double,double> interpolate(double y0, double y1, double y2)
00071         {
00072                 // From the quadratic lagrange interpolation
00073                 // y=   y0(x1-x)(x2-x)/(x1-x0)(x2-x0) +
00074                 //    + y1(x-x0)(x2-x)/(x1-x0)(x2-x0) +
00075                 //    + y1(x2-x)(x-x0)/(x2-x1)(x2-x0) +
00076                 //    + y2(x-x1)(x-x0)/(x2-x1)(x2-x0)  =
00077                 //
00078                 // considering x0=0, x1=1 and x2=2
00079                 //
00080                 //  =   y0(x-1)(x-2)/2 +
00081                 //    - y1(x)(x-2)/2 +
00082                 //    - y1(x-2)(x)/2 +
00083                 //    + y2(x-1)(x)/2  =
00084                 //
00085                 //  =   y0(x-1)(x-2)/2 +
00086                 //    - y1(x-2)(x) +
00087                 //    + y2(x-1)(x)/2 =
00088                 //
00089                 //  = y0/2 (x^2 - 3x + 2) - y1 (x^2-2x) + y2/2 (x^2-x)
00090                 //  = (y0/2-y1+y2/2) x^2 + (-3*y0/2 + 2*y1 - y2/2) x + y0
00091 
00092                 double a = y0/2 - y1 + y2/2;
00093                 double b = y1 -y0 -a; // = -3*y0/2 + 2*y1 -y2/2;
00094                 double c = y0;
00095 
00096                 // From equating to zero the derivate of x*x*a + x*b + c        
00097                 double xmax = -b/(a*2);
00098                 // ymax = xmax*xmax*a + b*xmax + c =
00099                 //      = a*b*b/(4*a*a) -b*b/(2*a) + c =
00100                 //      = b*b/(4*a) -b*b/(2*a) + c =
00101                 //      = -b*b/(4*a) + c
00102                 double ymax = b*xmax/2 + y0;
00103 
00104                 return std::make_pair(xmax, ymax);
00105         }
00106         void doIt(const std::vector<double> & chromagram)
00107         {
00108                 _output.resize(0);
00109                 unsigned i0=_maxSize-2;
00110                 unsigned i1=_maxSize-1;
00111                 for (unsigned i=0; i<_maxSize; i0=i1, i1=i, i++)
00112                 {
00113                         // not equal to support plain two bins peaks
00114                         if (chromagram[i0] >  chromagram[i1]) continue;
00115                         if (chromagram[i ] >= chromagram[i1]) continue;
00116 
00117                         std::pair<double,double> interpoled=
00118                                 interpolate(chromagram[i0],chromagram[i1],chromagram[i]);
00119                         // Adding the base bin
00120                         interpoled.first+=i0;
00121                         // Folding to [0,_maxSize) interval
00122                         while (interpoled.first<0) interpoled.first +=_maxSize;
00123                         while (interpoled.first>=_maxSize) interpoled.first -=_maxSize;
00124                         // Scaling
00125                         interpoled.first*=_binSize;
00126                         // Shifting to the first bin position
00127                         interpoled.first+=_offset;
00128 
00129                         _output.push_back(interpoled);
00130                 }
00131         }
00132         const PeakList & output() const
00133         {
00134                 return _output;
00135         }
00136 };
00137 
00138 } // namespace Simac
00139 
00140 #endif// CircularPeakPicking_hxx
00141 
Generated by  doxygen 1.6.3