00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "common.h"
00020 #include "TimeFreqPeakConnectivity.h"
00021
00022 using std::max;
00023 using namespace Marsyas;
00024
00025
00026
00027
00028 static const mrs_real costInit = 1e30;
00029 static const mrs_natural listLenInit = 16;
00030 class DoubleListEntries
00031 {
00032 public:
00033 DoubleListEntries () : maxListLength(0),currListLength(0)
00034 {
00035 list = 0;
00036 AllocMem (listLenInit);
00037 };
00038 ~DoubleListEntries ()
00039 {
00040 FreeMem ();
00041 };
00042 mrs_natural GetNumIndices (mrs_natural row, mrs_natural col)
00043 {
00044 mrs_natural count = 0;
00045 for (mrs_natural i = 0; i < currListLength; i++)
00046 {
00047 if (row == list[i][kRow])
00048 if (col == list[i][kCol])
00049 count++;
00050 }
00051 return count;
00052 };
00053 mrs_natural GetIndex (mrs_natural row, mrs_natural col, mrs_natural index)
00054 {
00055 for (mrs_natural i = 0; i < currListLength; i++)
00056 {
00057 if (row == list[i][kRow]) {
00058 if (col == list[i][kCol]) {
00059 if (index == 0) {
00060 return list[i][kIdx];
00061 } else {
00062 index--;
00063 }
00064 }
00065 }
00066 }
00067 MRSASSERT(true);
00068 return -1;
00069 };
00070 mrs_bool IsInList (mrs_natural row, mrs_natural col, mrs_natural index)
00071 {
00072 for (mrs_natural i = 0; i < currListLength; i++)
00073 {
00074 if (row == list[i][kRow])
00075 if (col == list[i][kCol])
00076 if (index == list[i][kIdx])
00077 return true;
00078 }
00079 return false;
00080 };
00081 void AddIndex (mrs_natural row, mrs_natural col, mrs_natural index)
00082 {
00083 if (IsInList (row,col,index))
00084 return;
00085 if (currListLength == maxListLength -1)
00086 AllocMem (maxListLength<<1);
00087 list[currListLength][kRow] = row;
00088 list[currListLength][kCol] = col;
00089 list[currListLength][kIdx] = index;
00090 currListLength++;
00091 };
00092 void Reset ()
00093 {
00094 currListLength = 0;
00095 };
00096 private:
00097 void AllocMem(mrs_natural numNewListItems)
00098 {
00099 mrs_natural i;
00100 MRSASSERT(numNewListItems >= maxListLength);
00101 mrs_natural **tmpList = new mrs_natural* [numNewListItems];
00102 for (i = 0; i < maxListLength; i++)
00103 tmpList[i] = list[i];
00104 for (i = maxListLength; i < numNewListItems; i++)
00105 tmpList[i] = new mrs_natural [kNumListEntries];
00106
00107 delete [] list;
00108 list = tmpList;
00109 maxListLength = numNewListItems;
00110 return;
00111 };
00112 void FreeMem ()
00113 {
00114 for (mrs_natural i = 0; i < maxListLength; i++)
00115 delete [] list[i];
00116 delete [] list;
00117 };
00118
00119 enum ListEntries_t
00120 {
00121 kRow,
00122 kCol,
00123 kIdx,
00124
00125 kNumListEntries
00126 };
00127 mrs_natural **list;
00128 mrs_natural maxListLength,
00129 currListLength;
00130 };
00131
00132
00133 static inline mrs_natural MyMax (mrs_natural a , mrs_natural b)
00134 {
00135 return (a >= b) ? a : b;
00136 }
00137 static inline mrs_natural MyMin (mrs_natural a , mrs_natural b)
00138 {
00139 return (a <= b) ? a : b;
00140
00141 }
00142
00143 TimeFreqPeakConnectivity::TimeFreqPeakConnectivity(mrs_string name) : MarSystem("TimeFreqPeakConnectivity", name)
00144 {
00145 addControls();
00146
00147 tracebackIdx_ = 0;
00148 peakIndices_ = 0;
00149 path_ = 0;
00150 numBands_ = 0;
00151 multipleIndices = 0;
00152 }
00153
00154 TimeFreqPeakConnectivity::TimeFreqPeakConnectivity(const TimeFreqPeakConnectivity& a) : MarSystem(a)
00155 {
00156
00159
00160 ctrl_reso_ = getctrl("mrs_real/freqResolution");
00161
00162 tracebackIdx_ = 0;
00163 peakIndices_ = 0;
00164 path_ = 0;
00165 numBands_ = 0;
00166 multipleIndices = 0;
00167 }
00168
00169
00170 TimeFreqPeakConnectivity::~TimeFreqPeakConnectivity()
00171 {
00172 FreeMemory ();
00173 if (multipleIndices)
00174 delete multipleIndices;
00175 }
00176
00177 MarSystem*
00178 TimeFreqPeakConnectivity::clone() const
00179 {
00180
00181 return new TimeFreqPeakConnectivity(*this);
00182 }
00183
00184 void
00185 TimeFreqPeakConnectivity::addControls()
00186 {
00187 addctrl("mrs_string/frequencyIntervalInHz", "MARSYAS_EMPTY");
00188 setctrlState("mrs_string/frequencyIntervalInHz", true);
00189
00190 addctrl("mrs_bool/inBark", false);
00191 addctrl("mrs_real/freqResolution", 25., ctrl_reso_);
00192
00193
00194
00195 addctrl("mrs_natural/textureWindowSize", 0);
00196 }
00197
00198 void
00199 TimeFreqPeakConnectivity::AllocMemory (mrs_natural numSamples)
00200 {
00201 tracebackIdx_ = new unsigned char* [numBands_];
00202 peakIndices_ = new mrs_natural* [numBands_];
00203 for (mrs_natural i = 0; i < numBands_; i++)
00204 {
00205 tracebackIdx_[i] = new unsigned char [numSamples];
00206 peakIndices_[i] = new mrs_natural[numSamples];
00207 }
00208 path_ = new mrs_natural [numSamples];
00209
00210 if (multipleIndices == 0)
00211 multipleIndices = new DoubleListEntries ();
00212 else
00213 multipleIndices->Reset ();
00214 }
00215
00216 void
00217 TimeFreqPeakConnectivity::FreeMemory ()
00218 {
00219 if (tracebackIdx_)
00220 {
00221 for (mrs_natural i = 0; i < numBands_; i++)
00222 delete [] tracebackIdx_[i];
00223 delete [] tracebackIdx_;
00224 }
00225 if (peakIndices_)
00226 {
00227 for (mrs_natural i = 0; i < numBands_; i++)
00228 delete [] peakIndices_[i];
00229 delete [] peakIndices_;
00230 }
00231
00232 delete [] path_;
00233 }
00234
00235 void
00236 TimeFreqPeakConnectivity::myUpdate(MarControlPtr sender)
00237 {
00238 MRSDIAG("TimeFreqPeakConnectivity.cpp - TimeFreqPeakConnectivity:myUpdate");
00239
00241 MarSystem::myUpdate(sender);
00242
00243 mrs_natural numSamples;
00244 const mrs_bool isInBark = getctrl("mrs_bool/inBark")->to<mrs_bool>();
00245
00246 FreeMemory ();
00247
00248
00249 numSamples = inSamples_;
00250 if(getctrl("mrs_string/frequencyIntervalInHz")->to<mrs_string>() != "MARSYAS_EMPTY")
00251 {
00252 realvec conv(2);
00253 string2parameters(getctrl("mrs_string/frequencyIntervalInHz")->to<mrs_string>(), conv, '_');
00254 downFreq_ = (isInBark)? hertz2bark (conv(0)) : conv(0);
00255 upFreq_ = (isInBark)? hertz2bark (conv(1)) : conv(1);
00256 numBands_ = (mrs_natural)((upFreq_-downFreq_)/ctrl_reso_->to<mrs_real>() + .5);
00257 }
00258 else
00259 {
00260 numBands_ = 0;
00261 downFreq_ = 0;
00262 upFreq_ = 0;
00263 }
00264 textWinSize_ = getControl ("mrs_natural/textureWindowSize")->to<mrs_natural>();
00265
00266
00267 peakMatrix_.create (numBands_, textWinSize_);
00268 costMatrix_.create (numBands_, textWinSize_);
00269
00270 updControl ("mrs_natural/onObservations", inSamples_);
00271 updControl ("mrs_natural/onSamples", inSamples_);
00272
00273 AllocMemory (textWinSize_);
00274 }
00275
00276 void
00277 TimeFreqPeakConnectivity::myProcess(realvec& in, realvec& out)
00278 {
00279
00280 const mrs_real reso = ctrl_reso_->to<mrs_real>();
00281 const mrs_bool isInBark = getctrl("mrs_bool/inBark")->to<mrs_bool>();
00282
00283
00284 MRSASSERT(textWinSize_ >= in(1,inSamples_-1)-in(1,0));
00285 peakMatrix_.stretch(numBands_, textWinSize_);
00286
00287
00288 peakMatrix_.setval (1);
00289 for (t = 0; t < textWinSize_; t++)
00290 for (o=0; o < numBands_; o++)
00291 peakIndices_[o][t] = -1;
00292
00293
00294 for (t = 0; t < inSamples_; t++)
00295 {
00296 mrs_natural row = (isInBark)? Freq2RowIdx (in(0,t),reso) : Freq2RowIdx (bark2hertz(in(0,t)),reso),
00297 col = (mrs_natural)(in(1,t)-in(1,0)+.1);
00298 MRSASSERT(col >= 0 && col < textWinSize_);
00299 MRSASSERT(row >= 0 && row < numBands_);
00300
00301 if (peakIndices_[row][col] != -1)
00302 {
00303 multipleIndices->AddIndex (row,col,peakIndices_[row][col]);
00304 multipleIndices->AddIndex (row,col,t);
00305 peakIndices_[row][col] = -2;
00306 }
00307 else
00308 peakIndices_[row][col] = t;
00309 peakMatrix_(row, col) = 0;
00310 }
00311
00312
00313 out.setval (costInit);
00314
00315 #ifdef MATLAB_DBG_OUT
00316 #ifdef MARSYAS_MATLAB
00317 MATLAB_PUT(peakMatrix_, "peakMatrix");
00318 MATLAB_EVAL ("figure(1),imagesc(peakMatrix),colorbar");
00319 #endif
00320 #endif
00321
00322
00323 for (t = 0; t < inSamples_; t++)
00324 {
00325 for (o=inSamples_-1; o >= t;o--)
00326 {
00327
00328 if (out(t,o) != costInit)
00329 continue;
00330
00331
00332 mrs_natural rowt = (isInBark)? Freq2RowIdx (in(0,t),reso) : Freq2RowIdx (bark2hertz(in(0,t)),reso),
00333 rowo = (isInBark)? Freq2RowIdx (in(0,o),reso) : Freq2RowIdx (bark2hertz(in(0,o)),reso),
00334 colt = (mrs_natural)(in(1,t)-in(1,0)+.1),
00335 colo = (mrs_natural)(in(1,o)-in(1,0)+.1),
00336 pathLength;
00337
00338 MRSASSERT(colt >= 0 && colt < textWinSize_);
00339 MRSASSERT(colo >= 0 && colo < textWinSize_);
00340 MRSASSERT(rowt >= 0 && rowt < numBands_);
00341 MRSASSERT(rowo >= 0 && rowo < numBands_);
00342
00343
00344
00345 if ((t == o) || (rowt == rowo && colt == colo))
00346 {
00347 SetOutput(out, 0, rowt, colt, rowo, colo);
00348 continue;
00349 }
00350
00351
00352 if (abs(rowt - rowo) > abs(colt-colo))
00353 {
00354 SetOutput(out, 1, rowt, colt, rowo, colo);
00355 continue;
00356 }
00357
00358
00359 if (colo < colt)
00360 continue;
00361
00362
00363 CalcDp (peakMatrix_, rowt, colt, rowo, colo);
00364 pathLength = colo-colt+1;
00365
00366 #ifdef MATLAB_DBG_OUT
00367 #ifdef MARSYAS_MATLAB
00368 MATLAB_PUT(costMatrix_, "cost");
00369 MATLAB_EVAL ("figure(2),imagesc(cost,[0 10]),colorbar");
00370 #endif
00371 #endif
00372
00373
00374 for (mrs_natural i = 0; i < pathLength; i++)
00375 {
00376 if (peakMatrix_(path_[i],colt + i) > 0)
00377 {
00378 MRSASSERT(i>0);
00379 continue;
00380 }
00381 for (mrs_natural j = i; j < pathLength; j++)
00382 {
00383 if (peakMatrix_(path_[j],colt + j) > 0)
00384 continue;
00385
00386 mrs_real cost = (costMatrix_(path_[j],colt + j) - costMatrix_(path_[i],colt + i)) / (j-i+1);
00387 MRSASSERT (cost >= 0 && cost <=1);
00388
00389
00390 SetOutput(out, cost, path_[i], colt + i, path_[j], colt + j);
00391 }
00392 }
00393 }
00394 }
00395 multipleIndices->Reset ();
00396
00397
00398
00399
00400
00401
00402
00403 #ifdef SANITY_CHECK
00404 for (t=0; t < inSamples_;t++)
00405 for (o=0; o < inSamples_;o++)
00406 MRSASSERT (out(t,o) >= 0 && out(t,o) <=1);
00407 #endif
00408 #ifdef MATLAB_DBG_OUT
00409 #ifdef MARSYAS_MATLAB
00410 MATLAB_PUT(out, "out");
00411 MATLAB_EVAL ("figure(3),imagesc(out),colorbar");
00412 #endif
00413 #endif
00414
00415 }
00416
00417
00418 void TimeFreqPeakConnectivity::SetOutput(mrs_realvec &out, const mrs_real cost, mrs_natural idxRowA, mrs_natural idxColA, mrs_natural idxRowB, mrs_natural idxColB)
00419 {
00420 mrs_natural ml = 0,
00421 nl = 0,
00422 rowIdx = peakIndices_[idxRowA][idxColA],
00423 colIdx = peakIndices_[idxRowB][idxColB];
00424
00425 if (rowIdx == -2)
00426 {
00427 ml = multipleIndices->GetNumIndices (idxRowA, idxColA);
00428 MRSASSERT(ml>0);
00429 rowIdx = multipleIndices->GetIndex (idxRowA, idxColA, 0);
00430 }
00431 if (colIdx == -2)
00432 {
00433 nl = multipleIndices->GetNumIndices (idxRowB, idxColB);
00434 MRSASSERT(nl>0);
00435 colIdx = multipleIndices->GetIndex (idxRowB, idxColB, 0);
00436 }
00437
00438 if (out(rowIdx, colIdx) != costInit)
00439 {
00440 MRSASSERT(out(rowIdx, colIdx) == cost);
00441 return;
00442 }
00443
00444
00445
00446 out(rowIdx,colIdx) = cost;
00447 out(colIdx,rowIdx) = cost;
00448
00449
00450 if (ml > 0 || nl > 0)
00451 {
00452 mrs_natural m,n;
00453
00454
00455 if (ml * nl)
00456 {
00457 for (m = 0; m < ml; m++)
00458 {
00459 rowIdx = multipleIndices->GetIndex (idxRowA, idxColA, m);
00460 for (n = 0; n < nl; n++)
00461 {
00462 colIdx = multipleIndices->GetIndex (idxRowB, idxColB, n);
00463
00464
00465 out(rowIdx,colIdx) = cost;
00466 out(colIdx,rowIdx) = cost;
00467 }
00468 }
00469 }
00470 else if (ml > 0)
00471 {
00472 for (m = 0; m < ml; m++)
00473 {
00474 rowIdx = multipleIndices->GetIndex (idxRowA, idxColA, m);
00475
00476
00477 out(rowIdx,colIdx) = cost;
00478 out(colIdx,rowIdx) = cost;
00479 }
00480
00481 }
00482 else if (nl > 0)
00483 {
00484 for (n = 0; n < nl; n++)
00485 {
00486 colIdx = multipleIndices->GetIndex (idxRowB, idxColB, n);
00487
00488
00489 out(rowIdx,colIdx) = cost;
00490 out(colIdx,rowIdx) = cost;
00491 }
00492 }
00493 }
00494 }
00495
00496 mrs_natural TimeFreqPeakConnectivity::Freq2RowIdx (mrs_real barkFreq, mrs_real bres)
00497 {
00498 mrs_natural result = (mrs_natural)((barkFreq-downFreq_)/bres +.5);
00499
00500 if (result < 0)
00501 result = 0;
00502 if (result >= numBands_)
00503 result =numBands_-1;
00504
00505 return result;
00506 }
00507
00508 void TimeFreqPeakConnectivity::InitMatrix (mrs_realvec &Matrix, unsigned char **traceback, mrs_natural rowIdx, mrs_natural colIdx)
00509 {
00510 mrs_natural i,j,
00511 numRows = Matrix.getRows (),
00512 numCols = Matrix.getCols ();
00513 mrs_natural iCol;
00514
00515 Matrix.setval(0);
00516
00517 traceback[rowIdx][colIdx] = kFromLeft;
00518
00519
00520 for (i = 0; i < numRows; i++)
00521 {
00522 for (j = 0; j < colIdx; j++)
00523 {
00524 Matrix(i,j) = costInit;
00525 traceback[i][j] = kFromLeft;
00526 }
00527 }
00528
00529
00530 for (i = 0; i < rowIdx; i++)
00531 {
00532 iCol = MyMin (rowIdx - i + colIdx, numCols);
00533 for (j = colIdx; j < iCol; j++)
00534 {
00535 Matrix(i,j) = costInit;
00536 traceback[i][j] = kFromLeft;
00537 }
00538 }
00539
00540
00541 for (i = rowIdx + 1; i < numRows; i++)
00542 {
00543 iCol = MyMin (i - rowIdx + colIdx, numCols);
00544 for (j = colIdx; j < iCol; j++)
00545 {
00546 Matrix(i,j) = costInit;
00547 traceback[i][j] = kFromLeft;
00548 }
00549 }
00550
00551 }
00552
00553 void TimeFreqPeakConnectivity::CalcDp (mrs_realvec &Matrix, mrs_natural startr, mrs_natural startc, mrs_natural stopr, mrs_natural stopc)
00554 {
00555 mrs_natural i,j,
00556 numRows = Matrix.getRows (),
00557 numCols = Matrix.getCols ();
00558 mrs_real prevCost[kNumDirections] = {0,0,0};
00559
00560 costMatrix_.stretch ( numRows, numCols);
00561
00562
00563
00564 InitMatrix (costMatrix_, tracebackIdx_, startr, startc);
00565 costMatrix_(startr, startc) = Matrix(startr, startc);
00566
00567
00568 for (j = startc+1; j <= stopc; j++)
00569 {
00570 mrs_natural rowLoopStart = MyMax (0, startr - (j - startc)),
00571 rowLoopStop = MyMin (numRows, startr + (j-startc) + 1);
00572 for (i = rowLoopStart; i < rowLoopStop; i++)
00573 {
00574 prevCost[kFromLeft] = costMatrix_(i,j-1);
00575 prevCost[kFromUp] = (i >= numRows-1) ? costInit : costMatrix_(i+1, j-1);
00576 prevCost[kFromDown] = (i <= 0) ? costInit : costMatrix_(i-1, j-1);
00577
00578 costMatrix_(i,j) = Matrix(i,j) + dtwFindMin (prevCost, tracebackIdx_[i][j]);
00579 }
00580 }
00581
00582
00583 i = stopr;
00584 for (j = stopc; j >= startc; j--)
00585 {
00586 path_[j-startc] = i;
00587 i -= (kFromLeft - tracebackIdx_[i][j]);
00588 }
00589 }