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