![]() |
Mixxx
|
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