Переглянути джерело

cmProc4.h/c: Add cmMeas.vsi and callback args to cmScMatcher.

master
kevin 11 роки тому
джерело
коміт
56249c2f40
2 змінених файлів з 191 додано та 121 видалено
  1. 142
    102
      cmProc4.c
  2. 49
    19
      cmProc4.h

+ 142
- 102
cmProc4.c Переглянути файл

1910
 
1910
 
1911
 
1911
 
1912
 //=======================================================================================================================
1912
 //=======================================================================================================================
1913
-cmScMatcher* cmScMatcherAlloc( cmCtx* c, cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN )
1913
+cmScMatcher* cmScMatcherAlloc( cmCtx* c, cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN, cmScMatcherCb_t cbFunc, void* cbArg )
1914
 {
1914
 {
1915
   cmScMatcher* op = cmObjAlloc(cmScMatcher,c,p);
1915
   cmScMatcher* op = cmObjAlloc(cmScMatcher,c,p);
1916
 
1916
 
1919
 
1919
 
1920
   if( srate != 0 )
1920
   if( srate != 0 )
1921
   {
1921
   {
1922
-    if( cmScMatcherInit(op,srate,scH,scWndN,midiWndN) != cmOkRC )
1922
+    if( cmScMatcherInit(op,srate,scH,scWndN,midiWndN,cbFunc,cbArg) != cmOkRC )
1923
       cmScMatcherFree(&op);
1923
       cmScMatcherFree(&op);
1924
   }
1924
   }
1925
 
1925
 
1944
 
1944
 
1945
 }
1945
 }
1946
 
1946
 
1947
-cmRC_t cmScMatcherInit(  cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN )
1947
+cmRC_t cmScMatcherInit(  cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN, cmScMatcherCb_t cbFunc, void* cbArg )
1948
 {
1948
 {
1949
   cmRC_t rc;
1949
   cmRC_t rc;
1950
   if((rc = cmScMatcherFinal(p)) != cmOkRC )
1950
   if((rc = cmScMatcherFinal(p)) != cmOkRC )
1956
   if(( rc = cmScMatchInit(p->mp,scH,scWndN,midiWndN)) != cmOkRC )
1956
   if(( rc = cmScMatchInit(p->mp,scH,scWndN,midiWndN)) != cmOkRC )
1957
     return rc;
1957
     return rc;
1958
 
1958
 
1959
+  p->cbFunc     = cbFunc;
1960
+  p->cbArg      = cbArg;
1959
   p->mn         = midiWndN;
1961
   p->mn         = midiWndN;
1960
   p->midiBuf    = cmMemResize(cmScMatchMidi_t,p->midiBuf,p->mn);
1962
   p->midiBuf    = cmMemResize(cmScMatchMidi_t,p->midiBuf,p->mn);
1961
   p->stepCnt    = 3;
1963
   p->stepCnt    = 3;
1962
   p->maxMissCnt = p->stepCnt+1;
1964
   p->maxMissCnt = p->stepCnt+1;
1963
   p->rn         = 2 * cmScoreEvtCount(scH);
1965
   p->rn         = 2 * cmScoreEvtCount(scH);
1964
   p->res        = cmMemResizeZ(cmScMatcherResult_t,p->res,p->rn);
1966
   p->res        = cmMemResizeZ(cmScMatcherResult_t,p->res,p->rn);
1965
-  
1966
-  cmScMatcherReset(p);
1967
+  p->printFl    = false;
1968
+
1969
+  cmScMatcherReset(p,0);
1967
 
1970
 
1968
   return rc;
1971
   return rc;
1969
 }
1972
 }
1973
   return cmScMatchFinal(p->mp);
1976
   return cmScMatchFinal(p->mp);
1974
 }
1977
 }
1975
 
1978
 
1976
-void cmScMatcherReset( cmScMatcher* p )
1979
+cmRC_t cmScMatcherReset( cmScMatcher* p, unsigned scLocIdx )
1977
 {
1980
 {
1978
   p->mbi           = p->mp->mmn;
1981
   p->mbi           = p->mp->mmn;
1979
   p->mni           = 0;
1982
   p->mni           = 0;
1982
   p->missCnt       = 0;
1985
   p->missCnt       = 0;
1983
   p->scanCnt       = 0;
1986
   p->scanCnt       = 0;
1984
   p->ri            = 0;
1987
   p->ri            = 0;
1988
+  p->eli           = cmInvalidIdx;
1989
+  p->ili           = 0;
1990
+
1991
+  // convert scLocIdx to an index into p->mp->loc[]
1992
+  unsigned i;
1993
+  for(i=0; i<p->mp->locN; ++i)
1994
+    if( p->mp->loc[i].scLocIdx == scLocIdx )
1995
+      p->ili = i;
1996
+
1997
+  return cmOkRC;
1985
 }
1998
 }
1986
 
1999
 
1987
 bool cmScMatcherInputMidi(  cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 )
2000
 bool cmScMatcherInputMidi(  cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 )
2016
   bool                  fpFl    = locIdx==cmInvalidIdx || matchFl==false;
2029
   bool                  fpFl    = locIdx==cmInvalidIdx || matchFl==false;
2017
   cmScMatcherResult_t * rp      = NULL;
2030
   cmScMatcherResult_t * rp      = NULL;
2018
   unsigned              i;
2031
   unsigned              i;
2032
+  cmScMatcherResult_t   r;
2019
 
2033
 
2020
   assert( tpFl==false || (tpFl==true && locIdx != cmInvalidIdx ) );
2034
   assert( tpFl==false || (tpFl==true && locIdx != cmInvalidIdx ) );
2021
 
2035
 
2038
 
2052
 
2039
   if( rp == NULL )
2053
   if( rp == NULL )
2040
   {
2054
   {
2041
-    rp = p->res + p->ri;
2042
-    ++p->ri;
2055
+    if( p->ri >= p->rn )
2056
+    {
2057
+      rp = &r;
2058
+      memset(rp,0,sizeof(r));
2059
+    }
2060
+    else
2061
+    {
2062
+      rp = p->res + p->ri;
2063
+      ++p->ri;
2064
+    }
2043
   }
2065
   }
2044
 
2066
 
2045
   rp->locIdx   = locIdx;
2067
   rp->locIdx   = locIdx;
2060
   _cmScMatchPrintPath(p->mp, p->mp->p_opt, p->begSyncLocIdx, p->midiBuf );
2082
   _cmScMatchPrintPath(p->mp, p->mp->p_opt, p->begSyncLocIdx, p->midiBuf );
2061
 }
2083
 }
2062
 
2084
 
2063
-unsigned   cmScMatcherScan( cmScMatcher* p, unsigned bsi, unsigned scanCnt )
2085
+unsigned   cmScMatcherScan( cmScMatcher* p, unsigned bli, unsigned scanCnt )
2064
 {
2086
 {
2065
   assert( p->mp != NULL && p->mp->mmn > 0 );
2087
   assert( p->mp != NULL && p->mp->mmn > 0 );
2066
 
2088
 
2067
   unsigned i_opt = cmInvalidIdx;
2089
   unsigned i_opt = cmInvalidIdx;
2068
   double   s_opt = DBL_MAX;
2090
   double   s_opt = DBL_MAX;
2069
-  cmRC_t  rc     = cmOkRC;
2091
+  cmRC_t   rc    = cmOkRC;
2070
   unsigned i;
2092
   unsigned i;
2071
 
2093
 
2072
   // initialize the internal values set by this function
2094
   // initialize the internal values set by this function
2073
   p->missCnt = 0;
2095
   p->missCnt = 0;
2074
-  p->esi     = cmInvalidIdx;
2096
+  p->eli     = cmInvalidIdx;
2075
   p->s_opt   = DBL_MAX;
2097
   p->s_opt   = DBL_MAX;
2076
   
2098
   
2077
   // if the MIDI buf is not full
2099
   // if the MIDI buf is not full
2078
   if( p->mbi != 0 )
2100
   if( p->mbi != 0 )
2079
     return cmInvalidIdx;
2101
     return cmInvalidIdx;
2080
 
2102
 
2081
-  // load a temporary MIDI pitch buffer for use by cmScMatch.
2082
-  //unsigned pitchV[p->mp->mmn];
2083
-  //for(i=0; i<p->mp->mmn; ++i)
2084
-  //  pitchV[i] = p->midiBuf[i].pitch;
2085
-
2086
   // calc the edit distance from pitchV[] to a sliding score window
2103
   // calc the edit distance from pitchV[] to a sliding score window
2087
   for(i=0; rc==cmOkRC && (scanCnt==cmInvalidCnt || i<scanCnt); ++i)
2104
   for(i=0; rc==cmOkRC && (scanCnt==cmInvalidCnt || i<scanCnt); ++i)
2088
   {      
2105
   {      
2089
-    rc = cmScMatchExec(p->mp, bsi + i, p->mp->msn, p->midiBuf, p->mp->mmn, s_opt );
2106
+    rc = cmScMatchExec(p->mp, bli + i, p->mp->msn, p->midiBuf, p->mp->mmn, s_opt );
2090
 
2107
 
2091
     switch(rc)
2108
     switch(rc)
2092
     {
2109
     {
2094
         if( p->mp->opt_cost < s_opt )
2111
         if( p->mp->opt_cost < s_opt )
2095
         {
2112
         {
2096
           s_opt = p->mp->opt_cost;
2113
           s_opt = p->mp->opt_cost;
2097
-          i_opt = bsi + i;
2114
+          i_opt = bli + i;
2098
         }
2115
         }
2099
         break;
2116
         break;
2100
 
2117
 
2104
       default: // error state
2121
       default: // error state
2105
         return cmInvalidIdx;
2122
         return cmInvalidIdx;
2106
     }
2123
     }
2107
-
2108
   }
2124
   }
2109
           
2125
           
2110
   // store the cost assoc'd with i_opt
2126
   // store the cost assoc'd with i_opt
2115
 
2131
 
2116
   // set the locIdx field in midiBuf[], trailing miss count and
2132
   // set the locIdx field in midiBuf[], trailing miss count and
2117
   // return the latest positive-match locIdx
2133
   // return the latest positive-match locIdx
2118
-  p->esi = cmScMatchDoSync(p->mp,i_opt,p->midiBuf,p->mp->mmn,&p->missCnt);
2134
+  p->eli = cmScMatchDoSync(p->mp,i_opt,p->midiBuf,p->mp->mmn,&p->missCnt);
2119
 
2135
 
2120
   // if no positive matches were found
2136
   // if no positive matches were found
2121
-  if( p->esi == cmInvalidIdx )
2137
+  if( p->eli == cmInvalidIdx )
2122
     i_opt = cmInvalidIdx;
2138
     i_opt = cmInvalidIdx;
2123
   else
2139
   else
2124
   {
2140
   {
2140
   unsigned pitch  = p->midiBuf[ p->mn-1 ].pitch;
2156
   unsigned pitch  = p->midiBuf[ p->mn-1 ].pitch;
2141
   unsigned locIdx = cmInvalidIdx;
2157
   unsigned locIdx = cmInvalidIdx;
2142
   unsigned pidx   = cmInvalidIdx;
2158
   unsigned pidx   = cmInvalidIdx;
2159
+
2143
   // the tracker must be sync'd to step
2160
   // the tracker must be sync'd to step
2144
-  if( p->esi == cmInvalidIdx )
2145
-    return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The p->esi value must be valid to perform a step operation."); 
2161
+  if( p->eli == cmInvalidIdx )
2162
+    return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The p->eli value must be valid to perform a step operation."); 
2146
 
2163
 
2147
   // if the end of the score has been reached
2164
   // if the end of the score has been reached
2148
-  if( p->esi + 1 >= p->mp->locN )
2165
+  if( p->eli + 1 >= p->mp->locN )
2149
     return cmEofRC;
2166
     return cmEofRC;
2150
     
2167
     
2151
   // attempt to match to next location first
2168
   // attempt to match to next location first
2152
-  if( (pidx = _cmScMatchIsMatchIndex(p->mp->loc + p->esi + 1, pitch)) != cmInvalidIdx )
2169
+  if( (pidx = _cmScMatchIsMatchIndex(p->mp->loc + p->eli + 1, pitch)) != cmInvalidIdx )
2153
   {
2170
   {
2154
-    locIdx = p->esi + 1;
2171
+    locIdx = p->eli + 1;
2155
   }
2172
   }
2156
   else
2173
   else
2157
   {
2174
   {
2159
     for(i=2; i<p->stepCnt; ++i)
2176
     for(i=2; i<p->stepCnt; ++i)
2160
     {
2177
     {
2161
       // go forward 
2178
       // go forward 
2162
-      if( p->esi+i < p->mp->locN && (pidx=_cmScMatchIsMatchIndex(p->mp->loc + p->esi + i, pitch))!=cmInvalidIdx )
2179
+      if( p->eli+i < p->mp->locN && (pidx=_cmScMatchIsMatchIndex(p->mp->loc + p->eli + i, pitch))!=cmInvalidIdx )
2163
       {
2180
       {
2164
-        locIdx = p->esi + i;
2181
+        locIdx = p->eli + i;
2165
         break;
2182
         break;
2166
       }
2183
       }
2167
 
2184
 
2168
       // go backward
2185
       // go backward
2169
-      if( p->esi >= (i-1)  && (pidx=_cmScMatchIsMatchIndex(p->mp->loc + p->esi - (i-1), pitch))!=cmInvalidIdx )
2186
+      if( p->eli >= (i-1)  && (pidx=_cmScMatchIsMatchIndex(p->mp->loc + p->eli - (i-1), pitch))!=cmInvalidIdx )
2170
       {
2187
       {
2171
-        locIdx = p->esi - (i-1);
2188
+        locIdx = p->eli - (i-1);
2172
         break;
2189
         break;
2173
       }
2190
       }
2174
     }
2191
     }
2184
   else
2201
   else
2185
   {
2202
   {
2186
     p->missCnt = 0;
2203
     p->missCnt = 0;
2187
-    p->esi     = locIdx;
2204
+    p->eli     = locIdx;
2188
   }
2205
   }
2189
 
2206
 
2190
   // store the result
2207
   // store the result
2192
 
2209
 
2193
   if( p->missCnt >= p->maxMissCnt )
2210
   if( p->missCnt >= p->maxMissCnt )
2194
   {
2211
   {
2195
-    unsigned begScanLocIdx = p->esi > p->mn ? p->esi - p->mn : 0;
2212
+    unsigned begScanLocIdx = p->eli > p->mn ? p->eli - p->mn : 0;
2196
     p->s_opt               = DBL_MAX;
2213
     p->s_opt               = DBL_MAX;
2197
-    unsigned bsi           = cmScMatcherScan(p,begScanLocIdx,p->mn*2);
2214
+    unsigned bli           = cmScMatcherScan(p,begScanLocIdx,p->mn*2);
2198
     ++p->scanCnt;
2215
     ++p->scanCnt;
2199
 
2216
 
2200
     // if the scan failed find a match
2217
     // if the scan failed find a match
2201
-    if( bsi == cmInvalidIdx )
2218
+    if( bli == cmInvalidIdx )
2202
       return cmCtxRtCondition( &p->obj, cmSubSysFailRC, "Scan resync. failed."); 
2219
       return cmCtxRtCondition( &p->obj, cmSubSysFailRC, "Scan resync. failed."); 
2203
-
2204
   }
2220
   }
2205
 
2221
 
2206
   return cmOkRC;
2222
   return cmOkRC;
2207
 }
2223
 }
2208
 
2224
 
2209
-cmRC_t     cmScMatcherExec(  cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 )
2225
+cmRC_t     cmScMatcherExec(  cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1, unsigned* scLocIdxPtr )
2210
 {
2226
 {
2211
-  bool   fl = p->mbi > 0;
2212
-  cmRC_t rc = cmOkRC;
2227
+  bool     fl  = p->mbi > 0;
2228
+  cmRC_t   rc  = cmOkRC;
2229
+  unsigned eli = p->eli;
2230
+
2231
+  if( scLocIdxPtr != NULL )
2232
+    *scLocIdxPtr = cmInvalidIdx;
2213
 
2233
 
2214
   // update the MIDI buffer with the incoming note
2234
   // update the MIDI buffer with the incoming note
2215
-  cmScMatcherInputMidi(p,smpIdx,status,d0,d1);
2235
+  if( cmScMatcherInputMidi(p,smpIdx,status,d0,d1) == false )
2236
+    return rc;
2216
 
2237
 
2217
   // if the MIDI buffer transitioned to full then perform an initial scan sync.
2238
   // if the MIDI buffer transitioned to full then perform an initial scan sync.
2218
   if( fl && p->mbi == 0 )
2239
   if( fl && p->mbi == 0 )
2219
   {
2240
   {
2220
-    if( (p->begSyncLocIdx = cmScMatcherScan(p,0,cmInvalidCnt)) == cmInvalidIdx )
2241
+    if( (p->begSyncLocIdx = cmScMatcherScan(p,p->ili,cmInvalidCnt)) == cmInvalidIdx )
2221
       rc = cmInvalidArgRC; // signal init. scan sync. fail
2242
       rc = cmInvalidArgRC; // signal init. scan sync. fail
2222
     else
2243
     else
2223
     {
2244
     {
2231
       rc = cmScMatcherStep(p);
2252
       rc = cmScMatcherStep(p);
2232
   }
2253
   }
2233
 
2254
 
2234
-  return rc;
2255
+  if( scLocIdxPtr!=NULL && p->eli != eli )
2256
+    *scLocIdxPtr = p->mp->loc[p->eli].scLocIdx;
2235
 
2257
 
2258
+  return rc;
2236
 }
2259
 }
2237
 
2260
 
2238
 double cmScMatcherFMeas( cmScMatcher* p )
2261
 double cmScMatcherFMeas( cmScMatcher* p )
2603
 
2626
 
2604
   //_cmScMeasPrint(p);
2627
   //_cmScMeasPrint(p);
2605
 
2628
 
2629
+  cmScMeasReset(p);
2630
+
2606
   return rc;
2631
   return rc;
2607
 }
2632
 }
2608
 
2633
 
2614
   cmRC_t rc = cmOkRC;
2639
   cmRC_t rc = cmOkRC;
2615
   p->mii    = 0;
2640
   p->mii    = 0;
2616
   p->nsi    = cmInvalidIdx;
2641
   p->nsi    = cmInvalidIdx;
2642
+  p->vsi    = cmInvalidIdx;
2617
   p->nsli   = cmInvalidIdx;
2643
   p->nsli   = cmInvalidIdx;
2644
+
2645
+  unsigned i;
2646
+  for(i=0; i<p->sn; ++i)
2647
+    p->set[i].value = DBL_MAX;
2618
   return rc;
2648
   return rc;
2619
 }
2649
 }
2620
 
2650
 
2761
 
2791
 
2762
   assert(bn<=cn);
2792
   assert(bn<=cn);
2763
 
2793
 
2794
+  // TODO: this copy should be eliminated
2764
   // copy to output
2795
   // copy to output
2765
   for(i=0; i<bn && i<cn; ++i)
2796
   for(i=0; i<bn && i<cn; ++i)
2766
     c[i] = b[i];
2797
     c[i] = b[i];
2900
   return rp->value;
2931
   return rp->value;
2901
 }
2932
 }
2902
 
2933
 
2934
+
2903
 unsigned MEAS_MATCH_CNT = 0;
2935
 unsigned MEAS_MATCH_CNT = 0;
2904
 
2936
 
2905
-void _cmScMeasMatch( cmScMeas* p, cmScMeasSet_t* sp, int n_mii )
2937
+void _cmScMeasPrintResult( cmScMeas* p,  cmScMeasSet_t* sp, _cmScMeasResult_t* rp, unsigned bli, const cmScMatchMidi_t* mb )
2938
+{
2939
+  const char* label = "<none>";
2940
+
2941
+  switch( sp->sp->varId )
2942
+  {
2943
+    case kEvenVarScId:  
2944
+      label = "even";  
2945
+      break;
2946
+
2947
+    case kDynVarScId:   
2948
+      label = "dyn";   
2949
+      break;
2950
+
2951
+    case kTempoVarScId: 
2952
+      label = "tempo"; 
2953
+      break;
2954
+  }
2955
+
2956
+  const cmChar_t* msg = "";
2957
+  if( rp->value == DBL_MAX )
2958
+  {
2959
+    msg       = "Measure FAILED.";
2960
+    sp->value = 0;
2961
+  }
2962
+  
2963
+  printf("%i set:%i %s bsli:%i esli:%i [set:%i match:%i] cost:%f val:%f %s",MEAS_MATCH_CNT, p->nsi, label, sp->bsli, sp->esli, rp->setN, rp->matchN, p->mp->opt_cost, sp->value, msg);
2964
+
2965
+  if( rp->tempo != 0 )
2966
+    printf(" tempo:%f ",rp->tempo);
2967
+
2968
+  printf("\n");
2969
+
2970
+  _cmScMatchPrintPath(p->mp, p->mp->p_opt, bli, mb );
2971
+
2972
+}
2973
+
2974
+void _cmScMeasCalcVal( cmScMeas* p, cmScMeasSet_t* sp, int n_mii )
2906
 {
2975
 {
2907
-  unsigned mn       = 0;
2976
+  unsigned mn = 0;
2908
   int      i;
2977
   int      i;
2909
 
2978
 
2910
   if( n_mii == 0 )
2979
   if( n_mii == 0 )
2930
 
2999
 
2931
   assert(mn>0);
3000
   assert(mn>0);
2932
 
3001
 
2933
-
2934
   // Create a copy of the the MIDI buffer to prevent the
3002
   // Create a copy of the the MIDI buffer to prevent the
2935
   // p->midiBuf[].locIdx from being overwritten by cmScMatchDoSync().
3003
   // p->midiBuf[].locIdx from being overwritten by cmScMatchDoSync().
2936
   cmScMatchMidi_t mb[ mn ];
3004
   cmScMatchMidi_t mb[ mn ];
2944
   // In general the first and last MIDI event should be assigned
3012
   // In general the first and last MIDI event should be assigned
2945
   // to a score location - it's possible however that no MIDI
3013
   // to a score location - it's possible however that no MIDI
2946
   // event's prior to the one at p->midiBuf[n_mii] were assigned.
3014
   // event's prior to the one at p->midiBuf[n_mii] were assigned.
2947
-  assert( (i==0 || p->midiBuf[i].locIdx!=cmInvalidIdx) && p->midiBuf[i+mn-1].locIdx!=cmInvalidIdx);
3015
+  assert( (i==0 || p->midiBuf[i].locIdx!=cmInvalidIdx) && p->midiBuf[i+mn-1].locIdx != cmInvalidIdx);
2948
 
3016
 
2949
-  unsigned bli      = p->midiBuf[i].locIdx;
2950
-  unsigned ln       = p->midiBuf[i+mn-1].locIdx - bli + 1;
2951
-  double   min_cost = DBL_MAX;
3017
+  unsigned          bli      = p->midiBuf[i].locIdx;
3018
+  unsigned          ln       = p->midiBuf[i+mn-1].locIdx - bli + 1;
3019
+  double            min_cost = DBL_MAX;
3020
+  _cmScMeasResult_t r;
3021
+  memset(&r,0,sizeof(r));
2952
 
3022
 
2953
   // match MIDI to score
3023
   // match MIDI to score
2954
   if( cmScMatchExec(p->mp, bli, ln, mb, mn, min_cost ) != cmOkRC )
3024
   if( cmScMatchExec(p->mp, bli, ln, mb, mn, min_cost ) != cmOkRC )
2958
   if( cmScMatchDoSync(p->mp, bli, mb, mn, NULL ) == cmInvalidIdx )
3028
   if( cmScMatchDoSync(p->mp, bli, mb, mn, NULL ) == cmInvalidIdx )
2959
     return;
3029
     return;
2960
   
3030
   
2961
-  // print the match result
2962
-  const char*      label    = "<none>";
2963
-  double           val      = DBL_MAX;
2964
-  double           tempoBpm = 0;
2965
-  _cmScMeasResult_t r;
2966
-  memset(&r,0,sizeof(r));
2967
-
2968
-  if( MEAS_MATCH_CNT == 12 )
2969
-  {
2970
-    //printf("blah\n");
2971
-  }
2972
-
2973
   switch( sp->sp->varId )
3031
   switch( sp->sp->varId )
2974
   {
3032
   {
2975
     case kEvenVarScId:  
3033
     case kEvenVarScId:  
2976
-      label = "even";  
2977
-      val   = _cmScMeasEven(p, sp, mb, mn, &r );
3034
+      sp->value = _cmScMeasEven(p, sp, mb, mn, &r );
2978
       break;
3035
       break;
2979
 
3036
 
2980
     case kDynVarScId:   
3037
     case kDynVarScId:   
2981
-      label = "dyn";   
2982
-      val   = _cmScMeasDyn(p, sp, mb, mn, &r );
3038
+      sp->value = _cmScMeasDyn(p, sp, mb, mn, &r );
2983
       break;
3039
       break;
2984
 
3040
 
2985
     case kTempoVarScId: 
3041
     case kTempoVarScId: 
2986
-      label    = "tempo"; 
2987
-      tempoBpm = _cmScMeasTempo(p, sp, mb, mn, &r );
2988
-      val      = tempoBpm;
3042
+      sp->value = _cmScMeasTempo(p, sp, mb, mn, &r );
2989
       break;
3043
       break;
2990
-  }
2991
 
3044
 
2992
-  if(1)
2993
-  {
2994
-    const cmChar_t* msg = "";
2995
-    if( val == DBL_MAX )
2996
-    {
2997
-      msg = "Measure FAILED.";
2998
-      val = 0;
2999
-    }
3000
-  
3001
-    printf("%i set:%i %s bsli:%i esli:%i [set:%i match:%i] cost:%f val:%f %s",MEAS_MATCH_CNT,p->nsi, label, sp->bsli, sp->esli, r.setN, r.matchN, p->mp->opt_cost, val, msg);
3002
-    if( r.tempo != 0 )
3003
-      printf(" tempo:%f ",r.tempo);
3004
-    printf("\n");
3005
-    _cmScMatchPrintPath(p->mp, p->mp->p_opt, bli, mb );
3045
+    default:
3046
+      { assert(0); }
3006
   }
3047
   }
3007
 
3048
 
3008
-  MEAS_MATCH_CNT++;
3049
+  sp->tempo = r.tempo;
3009
 
3050
 
3010
-}
3011
-/*
3012
-The first note in Bar 1 F4 should be marked with a 'e' - it isn't.
3051
+  // print the result
3052
+  _cmScMeasPrintResult(p, sp, &r, bli, mb );
3013
 
3053
 
3014
-Marker  Set   scli  Type    Note
3015
-4       8     48    even    very bad match produces an evenesss = 0.979 
3016
-10      12    69    even    bad match 
3017
-27      29    150   tempo   Tempo measured as 0.
3054
+  MEAS_MATCH_CNT++;
3055
+}
3018
 
3056
 
3019
- */
3020
 cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtIdx, unsigned flags, unsigned smpIdx, unsigned pitch, unsigned vel )
3057
 cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtIdx, unsigned flags, unsigned smpIdx, unsigned pitch, unsigned vel )
3021
 {
3058
 {
3022
   cmRC_t rc = cmOkRC;
3059
   cmRC_t rc = cmOkRC;
3026
     return cmCtxRtCondition( &p->obj, cmEofRC, "The MIDI buffer is full."); 
3063
     return cmCtxRtCondition( &p->obj, cmEofRC, "The MIDI buffer is full."); 
3027
 
3064
 
3028
   int n_mii = cmInvalidIdx;
3065
   int n_mii = cmInvalidIdx;
3066
+  // locate the MIDI event assoc'd with 'mni'  ...
3029
   if( p->mii>0 && mni <= p->midiBuf[p->mii-1].mni )
3067
   if( p->mii>0 && mni <= p->midiBuf[p->mii-1].mni )
3030
   {
3068
   {
3031
     if( locIdx != cmInvalidIdx )
3069
     if( locIdx != cmInvalidIdx )
3038
         n_mii = cmInvalidIdx;
3076
         n_mii = cmInvalidIdx;
3039
     }
3077
     }
3040
   }
3078
   }
3041
-  else
3079
+  else // ... or push a new record onto p->midiBuf[]
3042
   {
3080
   {
3043
     n_mii = p->mii;
3081
     n_mii = p->mii;
3044
     ++p->mii;
3082
     ++p->mii;
3052
   p->midiBuf[n_mii].pitch    = pitch;
3090
   p->midiBuf[n_mii].pitch    = pitch;
3053
   p->midiBuf[n_mii].vel      = vel;
3091
   p->midiBuf[n_mii].vel      = vel;
3054
 
3092
 
3055
-  //++p->mi;
3056
-
3057
   if( locIdx == cmInvalidIdx )
3093
   if( locIdx == cmInvalidIdx )
3058
     return cmOkRC;
3094
     return cmOkRC;
3059
 
3095
 
3078
       return rc;
3114
       return rc;
3079
   }
3115
   }
3080
 
3116
 
3117
+  p->vsi = p->nsi;
3118
+
3081
   // for each cmScore location between p->nsli and scLocIdx 
3119
   // for each cmScore location between p->nsli and scLocIdx 
3082
   for(; p->nsli<=scLocIdx && p->nsi < p->sn; ++p->nsli)
3120
   for(; p->nsli<=scLocIdx && p->nsi < p->sn; ++p->nsli)
3083
   {
3121
   {
3085
     // ahead of the next sets ending location.
3123
     // ahead of the next sets ending location.
3086
     while( cmMin(maxScLocIdx,p->set[p->nsi].esli+1) == p->nsli )
3124
     while( cmMin(maxScLocIdx,p->set[p->nsi].esli+1) == p->nsli )
3087
     {
3125
     {
3088
-      _cmScMeasMatch(p, p->set + p->nsi, n_mii );
3126
+
3127
+      // calculate the value assoc'd with p->set[p->nsi]
3128
+      _cmScMeasCalcVal(p, p->set + p->nsi, n_mii );
3089
 
3129
 
3090
       // advance the set index
3130
       // advance the set index
3091
       ++p->nsi;
3131
       ++p->nsi;
3114
     // if the time line MIDI msg a note-on
3154
     // if the time line MIDI msg a note-on
3115
     if( mep->msg->status == kNoteOnMdId )
3155
     if( mep->msg->status == kNoteOnMdId )
3116
     {
3156
     {
3117
-      rc = cmScMatcherExec(p, mep->obj.seqSmpIdx, mep->msg->status, mep->msg->u.chMsgPtr->d0, mep->msg->u.chMsgPtr->d1 );
3157
+      rc = cmScMatcherExec(p, mep->obj.seqSmpIdx, mep->msg->status, mep->msg->u.chMsgPtr->d0, mep->msg->u.chMsgPtr->d1, NULL );
3118
 
3158
 
3119
       switch( rc )
3159
       switch( rc )
3120
       {
3160
       {
3124
         case cmEofRC:       // end of the score was encountered
3164
         case cmEofRC:       // end of the score was encountered
3125
           break;
3165
           break;
3126
 
3166
 
3127
-        case cmInvalidArgRC: // p->esi was not set correctly
3167
+        case cmInvalidArgRC: // p->eli was not set correctly
3128
           break;
3168
           break;
3129
 
3169
 
3130
         case cmSubSysFailRC: // scan resync failed
3170
         case cmSubSysFailRC: // scan resync failed
3131
           break;
3171
           break;
3172
+
3173
+        default:
3174
+          { assert(0); }
3132
       }
3175
       }
3133
     }
3176
     }
3134
   }
3177
   }
3158
   unsigned     dynRefCnt    = sizeof(dynRefArray)/sizeof(dynRefArray[0]);
3201
   unsigned     dynRefCnt    = sizeof(dynRefArray)/sizeof(dynRefArray[0]);
3159
   cmCtx*       ctx          = cmCtxAlloc(NULL, rpt, cmLHeapNullHandle, cmSymTblNullHandle );
3202
   cmCtx*       ctx          = cmCtxAlloc(NULL, rpt, cmLHeapNullHandle, cmSymTblNullHandle );
3160
   cmScMeas*    mp           = cmScMeasAlloc(ctx,NULL,scH,srate,dynRefArray,dynRefCnt);
3203
   cmScMeas*    mp           = cmScMeasAlloc(ctx,NULL,scH,srate,dynRefArray,dynRefCnt);
3161
-  cmScMatcher* p            = cmScMatcherAlloc(ctx,NULL,srate,scH,scWndN,midiN);  
3204
+  cmScMatcher* p            = cmScMatcherAlloc(ctx,NULL,srate,scH,scWndN,midiN,cmScMatcherCb,mp);  
3162
   double       scoreThresh  = 0.5;
3205
   double       scoreThresh  = 0.5;
3163
   unsigned     candCnt      = 0;
3206
   unsigned     candCnt      = 0;
3164
   unsigned     initFailCnt  = 0;
3207
   unsigned     initFailCnt  = 0;
3170
   cmTimeSpec_t t0,t1;
3213
   cmTimeSpec_t t0,t1;
3171
 
3214
 
3172
   cmTimeGet(&t0);
3215
   cmTimeGet(&t0);
3173
-
3174
-  p->cbArg  = mp; // set the callback arg. 
3175
-  p->cbFunc = cmScMatcherCb; 
3176
   
3216
   
3177
   // for each marker
3217
   // for each marker
3178
   for(i=0; i<markN; ++i)
3218
   for(i=0; i<markN; ++i)
3199
 
3239
 
3200
     printf("=================== MARKER:%s ===================\n",markText);
3240
     printf("=================== MARKER:%s ===================\n",markText);
3201
     
3241
     
3202
-    cmScMatcherReset(p); // reset the score follower to the beginnig of the score
3242
+    cmScMatcherReset(p,0); // reset the score follower to the beginnig of the score
3203
     cmScMeasReset(mp);
3243
     cmScMeasReset(mp);
3204
 
3244
 
3205
     ++candCnt;
3245
     ++candCnt;

+ 49
- 19
cmProc4.h Переглянути файл

335
    unsigned             mn;
335
    unsigned             mn;
336
    cmScMatchMidi_t*     midiBuf;  // midiBuf[mn]
336
    cmScMatchMidi_t*     midiBuf;  // midiBuf[mn]
337
 
337
 
338
-   cmScMatcherResult_t* res;    // res[rn]
339
-   unsigned             rn;     // length of res[]
340
-   unsigned             ri;     // next avail res[] recd.
338
+   cmScMatcherResult_t* res;      // res[rn]
339
+   unsigned             rn;       // length of res[]
340
+   unsigned             ri;       // next avail res[] recd.
341
 
341
 
342
    double               s_opt;          // 
342
    double               s_opt;          // 
343
    unsigned             missCnt;        // count of consecutive trailing non-matches
343
    unsigned             missCnt;        // count of consecutive trailing non-matches
344
-   unsigned             esi;            // index into loc[] of the last positive match. 
344
+   unsigned             ili;            // index into loc[] to start scan following reset
345
+   unsigned             eli;            // index into loc[] of the last positive match. 
345
    unsigned             mni;            // track the count of MIDI events since the last call to cmScMatcherReset()
346
    unsigned             mni;            // track the count of MIDI events since the last call to cmScMatcherReset()
346
    unsigned             mbi;            // index of oldest MIDI event in midiBuf[]; 0 when the buffer is full.
347
    unsigned             mbi;            // index of oldest MIDI event in midiBuf[]; 0 when the buffer is full.
347
    unsigned             begSyncLocIdx;  // start of score window, in mp->loc[], of best match in previous scan
348
    unsigned             begSyncLocIdx;  // start of score window, in mp->loc[], of best match in previous scan
348
    unsigned             stepCnt;        // count of forward/backward score loc's to examine for a match during cmScMatcherStep().
349
    unsigned             stepCnt;        // count of forward/backward score loc's to examine for a match during cmScMatcherStep().
349
    unsigned             maxMissCnt;     // max. number of consecutive non-matches during step prior to executing a scan.
350
    unsigned             maxMissCnt;     // max. number of consecutive non-matches during step prior to executing a scan.
350
    unsigned             scanCnt;        // count of time scan was executed inside cmScMatcherStep()
351
    unsigned             scanCnt;        // count of time scan was executed inside cmScMatcherStep()
352
+
353
+   bool                 printFl;
351
 } cmScMatcher;
354
 } cmScMatcher;
352
 
355
 
353
 
356
 
354
 
357
 
355
-cmScMatcher* cmScMatcherAlloc( cmCtx* c, cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN );
358
+cmScMatcher* cmScMatcherAlloc( cmCtx* c, cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN, cmScMatcherCb_t cbFunc, void* cbArg );
356
 cmRC_t       cmScMatcherFree(  cmScMatcher** pp );
359
 cmRC_t       cmScMatcherFree(  cmScMatcher** pp );
357
-cmRC_t       cmScMatcherInit(  cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN );
360
+cmRC_t       cmScMatcherInit(  cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN, cmScMatcherCb_t cbFunc, void* cbArg );
358
 cmRC_t       cmScMatcherFinal( cmScMatcher* p );
361
 cmRC_t       cmScMatcherFinal( cmScMatcher* p );
359
-void         cmScMatcherReset( cmScMatcher* p );
360
-bool         cmScMatcherInputMidi( cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
361
 
362
 
362
-// Slide a score window scanCnt times, beginning at 'bsi',
363
-// looking for the best match to p->midiBuf[].  The score window
364
-// contain scWndN (p->mp->mcn-1) score locations.
363
+// 'scLocIdx' is a score index as used by cmScoreLoc(scH) not into p->mp->loc[].
364
+cmRC_t       cmScMatcherReset( cmScMatcher* p, unsigned scLocIdx );
365
+
366
+// Slide a score window scanCnt times, beginning at 'bli' (an
367
+// index int p->mp->loc[]) looking for the best match to p->midiBuf[].  
368
+// The score window contain scWndN (p->mp->mcn-1) score locations.
365
 // Returns the index into p->mp->loc[] of the start of the best
369
 // Returns the index into p->mp->loc[] of the start of the best
366
 // match score window. The score associated
370
 // match score window. The score associated
367
 // with this match is stored in s_opt.
371
 // with this match is stored in s_opt.
368
-unsigned   cmScMatcherScan( cmScMatcher* p, unsigned bsi, unsigned scanCnt );
372
+unsigned   cmScMatcherScan( cmScMatcher* p, unsigned bli, unsigned scanCnt );
369
 
373
 
370
-// Step forward/back by p->stepCnt from p->esi.
371
-// p->esi must therefore be valid prior to calling this function.
374
+// Step forward/back by p->stepCnt from p->eli.
375
+// p->eli must therefore be valid prior to calling this function.
372
 // If more than p->maxMissCnt consecutive MIDI events are 
376
 // If more than p->maxMissCnt consecutive MIDI events are 
373
 // missed then automatically run cmScAlignScan().
377
 // missed then automatically run cmScAlignScan().
374
 // Return cmEofRC if the end of the score is encountered.
378
 // Return cmEofRC if the end of the score is encountered.
375
 // Return cmSubSysFailRC if an internal scan resync. failed.
379
 // Return cmSubSysFailRC if an internal scan resync. failed.
376
 cmRC_t     cmScMatcherStep(  cmScMatcher* p );
380
 cmRC_t     cmScMatcherStep(  cmScMatcher* p );
377
 
381
 
378
-cmRC_t     cmScMatcherExec(  cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
382
+// This function calls cmScMatcherScan() and cmScMatcherStep() internally.
383
+// If 'status' is not kNonMidiMdId then the function returns without changing the
384
+// state of the object.
385
+// If the MIDI note passed by the call results in a successful match then
386
+// p->eli will be updated to the location in p->mp->loc[] of the latest 
387
+// match, the MIDI note in p->midiBuf[] associated with this match
388
+// will be assigned valid locIdx and scLocIdx values, and *scLocIdxPtr
389
+// will be set with the matched scLocIdx of the match.
390
+// If this call does not result in a successful match *scLocIdxPtr is set
391
+// to cmInvalidIdx.
392
+// Return:
393
+// cmOkRC  - Continue processing MIDI events.
394
+// cmEofRC - The end of the score was encountered.
395
+// cmInvalidArgRC - scan failed or the object was in an invalid state to attempt a match.
396
+// cmSubSysFailRC - a scan resync failed in cmScMatcherStep().
397
+cmRC_t     cmScMatcherExec(  cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1, unsigned* scLocIdxPtr );
379
 
398
 
380
 
399
 
381
 //=======================================================================================================================
400
 //=======================================================================================================================
393
   unsigned      bli;   // 
412
   unsigned      bli;   // 
394
   unsigned      eli;   //
413
   unsigned      eli;   //
395
 
414
 
415
+  double        value; // DBL_MAX if the value has not yet been set
416
+  double        tempo; // DBL_MAX until set
417
+
396
 } cmScMeasSet_t;
418
 } cmScMeasSet_t;
397
 
419
 
398
 typedef struct
420
 typedef struct
399
 {
421
 {
400
   cmObj            obj;
422
   cmObj            obj;
423
+  double           srate;    // 
401
   cmScMatch*       mp;       //
424
   cmScMatch*       mp;       //
402
-  unsigned         mii;       // next avail recd in midiBuf[]
425
+  unsigned         mii;      // next avail recd in midiBuf[]
403
   unsigned         mn;       // length of of midiBuf[]
426
   unsigned         mn;       // length of of midiBuf[]
404
   cmScMatchMidi_t* midiBuf;  // midiBuf[mn]
427
   cmScMatchMidi_t* midiBuf;  // midiBuf[mn]
405
 
428
 
409
   unsigned         dn;       // length of dynRef[]
432
   unsigned         dn;       // length of dynRef[]
410
   unsigned*        dynRef;   // dynRef[dn]  
433
   unsigned*        dynRef;   // dynRef[dn]  
411
 
434
 
412
-  unsigned         nsi;       // next set index
413
-  unsigned         nsli;      // next score location index
435
+  unsigned         nsi;      // next set index
436
+  unsigned         nsli;     // next score location index
437
+
438
+  unsigned         vsi;      // set[vsi:nsi-1] indicates sets with new values following a call to cmScMeasExec()
414
   
439
   
415
-  double           srate;     // sample rate from schore
416
 } cmScMeas;
440
 } cmScMeas;
417
 
441
 
442
+//
418
 // Notes:
443
 // Notes:
444
+//
419
 // 1) midiBuf[] stores all MIDI notes for the duration of the performance
445
 // 1) midiBuf[] stores all MIDI notes for the duration of the performance
420
 // it is initialized to 2*score_event_count.
446
 // it is initialized to 2*score_event_count.
447
+//
421
 // 2) dynRef][ is the gives the MIDI velocity range for each dynamics
448
 // 2) dynRef][ is the gives the MIDI velocity range for each dynamics
422
 // category: pppp-fff
449
 // category: pppp-fff
423
 // 
450
 // 
428
 cmRC_t    cmScMeasInit(  cmScMeas* p, cmScH_t scH, double srate, const unsigned* dynRefArray, unsigned dynRefCnt );
455
 cmRC_t    cmScMeasInit(  cmScMeas* p, cmScH_t scH, double srate, const unsigned* dynRefArray, unsigned dynRefCnt );
429
 cmRC_t    cmScMeasFinal( cmScMeas* p );
456
 cmRC_t    cmScMeasFinal( cmScMeas* p );
430
 
457
 
458
+// Empty MIDI buffer and set the next set nsi and nsli to zero.
459
+cmRC_t    cmScMeasReset( cmScMeas* p );
460
+
431
 // This function is called for each input MIDI note which is assigned a
461
 // This function is called for each input MIDI note which is assigned a
432
 // score location by cmScMatcher. 
462
 // score location by cmScMatcher. 
433
 // 'mni' is the MIDI event index which uniquely identifies this MIDI event.
463
 // 'mni' is the MIDI event index which uniquely identifies this MIDI event.

Завантаження…
Відмінити
Зберегти