Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/bpm/wavesegmentation.cpp

Go to the documentation of this file.
00001 // wavesegmentation.cpp: implementation of the Segmentation class.
00002 //
00004 
00005 #include "wavesegmentation.h"
00006 #include "float.h"
00007 #include "defs.h"
00008 
00010 // Main class for algorithm : Segmentation
00012 
00013 WaveSegmentation::WaveSegmentation()
00014 {
00015 
00016 }
00017 
00018 int WaveSegmentation::Process(double * psdf,int count,float * segPoints,int maxPoints)
00019 {
00020 
00021     Rhythmogram * rg=new Rhythmogram(psdf,count);
00022     selfsim * ss=new selfsim(rg);
00023     ShortestPath * sp=new ShortestPath(ss,10);
00024 
00025     int RetPoints = math_min(sp->length(),maxPoints);
00026 
00027     for(int i=0; i<RetPoints; i++)
00028         segPoints[i]=sp->getPoint(i);
00029     delete sp;
00030     delete ss;
00031     delete rg;
00032     return RetPoints;
00033 
00034 }
00035 
00036 WaveSegmentation::~WaveSegmentation()
00037 {
00038 
00039 }
00040 
00042 // Rhythmogram
00044 
00045 // Compute autocorrelation
00046 void Rhythmogram::acf(double * wav, int nwav, double * acf, int nacf) {
00047     int i, j;
00048     double normMax,normMin=0.0;
00049 
00050     for(i = 0; i < nacf; i++) {
00051         double sum = 0.0;
00052 
00053         for(j = 0; j < nwav - i; j++)
00054             sum += wav[j] * wav[j + i];
00055 
00056         // Normalization ratio w time lag i=0
00057         if (!i)
00058             normMax=sum;
00059 
00060         acf[i] = sum/normMax;
00061     }
00062 }
00063 
00064 double * Rhythmogram::column(int c)
00065 {
00066     return &_rhythmogram[c * r_height];
00067 }
00068 
00069 Rhythmogram::Rhythmogram(double * psdf, int count, double FeatureStepSize,
00070                          double HorzStepSize, double BlockSize, double HighRhythmIntv,
00071                          double LowRhythmIntv, double ZeroRhythmIntv)
00072 {
00073     r_height=(long)(HighRhythmIntv/FeatureStepSize);
00074     r_width=(long)((count*FeatureStepSize-BlockSize)/HorzStepSize);
00075     _rhythmogram=new double[r_width*r_height];
00076 
00077     long proc_length=(long)(BlockSize/FeatureStepSize);
00078 
00079     for (int k=0; k<r_width; k++)
00080     {
00081         acf(&psdf[(long)(k*HorzStepSize/FeatureStepSize)],proc_length,column(k),r_height);
00082         for (int i=0; i<ZeroRhythmIntv/FeatureStepSize; i++)
00083             column(k)[i]=0;
00084     }
00085 }
00086 
00087 Rhythmogram::~Rhythmogram()
00088 {
00089     delete [] _rhythmogram;
00090 }
00091 
00092 
00093 
00094 long Rhythmogram::height()
00095 {
00096     return r_height;
00097 }
00098 
00099 long Rhythmogram::width()
00100 {
00101     return r_width;
00102 }
00103 
00104 
00106 // selfsimilarity computed as euclidean distance
00108 selfsim::selfsim(Rhythmogram * rg)
00109 {
00110     s_size = rg->width();
00111     _selfsim = new double[s_size*s_size];
00112     for (int j=0; j<s_size; j++){
00113         for (int k=j; k<math_min(j+MAX_SEGMENT_SIZE+1,s_size); k++){
00114             double * colJ = rg->column(j);
00115             double * colK = rg->column(k);
00116             double rowsum=0;
00117             for (int row=0; row<rg->height(); row++){
00118                 double d=colJ[row]-colK[row];
00119                 rowsum += d*d;
00120             }
00121             column(j)[k]=sqrt(rowsum);
00122             column(k)[j]=column(j)[k];
00123         }
00124     }
00125     // Change to sums (weights to use for shortest path)
00126     int n;
00127     for (int k=0; k<math_min(s_size-2,MAX_SEGMENT_SIZE+2); k++)
00128         for(int m=k+2; m<s_size; m++){
00129             n=m-k-2;
00130             column(m)[n]+=column(m-1)[n] + column(m)[n+1] -column(m-1)[n+1];
00131             column(n)[m]=column(m)[n];
00132         }
00133 
00134 }
00135 
00136 selfsim::~selfsim()
00137 {
00138     delete [] _selfsim;
00139 }
00140 
00141 double * selfsim::column(int c)
00142 {
00143     return &_selfsim[c * s_size];
00144 }
00145 
00146 long selfsim::size()
00147 {
00148     return s_size;
00149 }
00150 
00152 // ShortestPath algo
00154 
00155 
00156 void relax(double * d, int i, int j, double a, int * py, double * dy)
00157 {
00158     *py=-1;
00159     *dy=0.0;
00160     if (d[j]>d[i]+a){
00161         *dy=d[i]+a;
00162         *py=i;            // Set backtrack path
00163     }
00164 }
00165 
00166 ShortestPath::ShortestPath(selfsim * ss,double Threshold,double HorzStepSize )
00167 {
00168     _HorzStepSize=HorzStepSize;
00169     int I  = ss->size();          //Length of sound file feature
00170     int * py = new int[I];
00171     double * d  = new double[I];
00172     segPoints=new int[I];
00173 
00174     for (int n=0; n<I; n++){   //Initialize vectors
00175         py[n]=-1;
00176         d[n]=DBL_MAX;
00177     }
00178 
00179     d[0]=0.0;
00180 
00181     for (int i=0; i<I-1; i++)
00182     {
00183         int limit=math_min(MAX_SEGMENT_SIZE+i,I-1);
00184         for (int j=i+1; j<=limit; j++)
00185         {
00186             double sum=ss->column(j)[i]*2;
00187             //printf("%lf\n",sum);
00188             int py2;
00189             double dy2;
00190             relax(d,i,j,Threshold+(1/(double)(j-i))*sum,&py2,&dy2);
00191             if (py2>-1){
00192                 //printf("py[%d]=%d\n",j,py2);
00193                 py[j]=py2;
00194                 d[j]=dy2;
00195             }
00196         }
00197     }
00198     nPoints=0;
00199     segPoints[nPoints++]=I-1;
00200     while(py[ segPoints[nPoints-1] ] != -1){
00201         segPoints[nPoints]=(int)py[segPoints[nPoints-1]];        // * HorzStepSize;
00202         nPoints++;
00203     }
00204     segPoints[0] = segPoints[0] ;    //* HorzStepSize;
00205     delete [] py;
00206     delete [] d;
00207 }
00208 
00209 float ShortestPath::getPoint(int n)
00210 {
00211     return (float)((double)segPoints[nPoints-n-1]*_HorzStepSize);
00212 }
00213 
00214 int ShortestPath::length()
00215 {
00216     return nPoints;
00217 }
00218 ShortestPath::~ShortestPath()
00219 {
00220     delete [] segPoints;
00221 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines