Browse Source

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

master
kevin 11 years ago
parent
commit
56249c2f40
2 changed files with 191 additions and 121 deletions
  1. 142
    102
      cmProc4.c
  2. 49
    19
      cmProc4.h

+ 142
- 102
cmProc4.c View File

@@ -1910,7 +1910,7 @@ void _cmScMatchPrintPath( cmScMatch* p, cmScMatchPath_t* cp, unsigned bsi, const
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 1915
   cmScMatcher* op = cmObjAlloc(cmScMatcher,c,p);
1916 1916
 
@@ -1919,7 +1919,7 @@ cmScMatcher* cmScMatcherAlloc( cmCtx* c, cmScMatcher* p, double srate, cmScH_t s
1919 1919
 
1920 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 1923
       cmScMatcherFree(&op);
1924 1924
   }
1925 1925
 
@@ -1944,7 +1944,7 @@ cmRC_t cmScMatcherFree(  cmScMatcher** pp )
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 1949
   cmRC_t rc;
1950 1950
   if((rc = cmScMatcherFinal(p)) != cmOkRC )
@@ -1956,14 +1956,17 @@ cmRC_t cmScMatcherInit(  cmScMatcher* p, double srate, cmScH_t scH, unsigned scW
1956 1956
   if(( rc = cmScMatchInit(p->mp,scH,scWndN,midiWndN)) != cmOkRC )
1957 1957
     return rc;
1958 1958
 
1959
+  p->cbFunc     = cbFunc;
1960
+  p->cbArg      = cbArg;
1959 1961
   p->mn         = midiWndN;
1960 1962
   p->midiBuf    = cmMemResize(cmScMatchMidi_t,p->midiBuf,p->mn);
1961 1963
   p->stepCnt    = 3;
1962 1964
   p->maxMissCnt = p->stepCnt+1;
1963 1965
   p->rn         = 2 * cmScoreEvtCount(scH);
1964 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 1971
   return rc;
1969 1972
 }
@@ -1973,7 +1976,7 @@ cmRC_t cmScMatcherFinal( cmScMatcher* p )
1973 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 1981
   p->mbi           = p->mp->mmn;
1979 1982
   p->mni           = 0;
@@ -1982,6 +1985,16 @@ void cmScMatcherReset( cmScMatcher* p )
1982 1985
   p->missCnt       = 0;
1983 1986
   p->scanCnt       = 0;
1984 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 2000
 bool cmScMatcherInputMidi(  cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 )
@@ -2016,6 +2029,7 @@ void _cmScMatcherStoreResult( cmScMatcher* p, unsigned locIdx, unsigned scEvtIdx
2016 2029
   bool                  fpFl    = locIdx==cmInvalidIdx || matchFl==false;
2017 2030
   cmScMatcherResult_t * rp      = NULL;
2018 2031
   unsigned              i;
2032
+  cmScMatcherResult_t   r;
2019 2033
 
2020 2034
   assert( tpFl==false || (tpFl==true && locIdx != cmInvalidIdx ) );
2021 2035
 
@@ -2038,8 +2052,16 @@ void _cmScMatcherStoreResult( cmScMatcher* p, unsigned locIdx, unsigned scEvtIdx
2038 2052
 
2039 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 2067
   rp->locIdx   = locIdx;
@@ -2060,33 +2082,28 @@ void cmScMatcherPrintPath( cmScMatcher* p )
2060 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 2087
   assert( p->mp != NULL && p->mp->mmn > 0 );
2066 2088
 
2067 2089
   unsigned i_opt = cmInvalidIdx;
2068 2090
   double   s_opt = DBL_MAX;
2069
-  cmRC_t  rc     = cmOkRC;
2091
+  cmRC_t   rc    = cmOkRC;
2070 2092
   unsigned i;
2071 2093
 
2072 2094
   // initialize the internal values set by this function
2073 2095
   p->missCnt = 0;
2074
-  p->esi     = cmInvalidIdx;
2096
+  p->eli     = cmInvalidIdx;
2075 2097
   p->s_opt   = DBL_MAX;
2076 2098
   
2077 2099
   // if the MIDI buf is not full
2078 2100
   if( p->mbi != 0 )
2079 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 2103
   // calc the edit distance from pitchV[] to a sliding score window
2087 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 2108
     switch(rc)
2092 2109
     {
@@ -2094,7 +2111,7 @@ unsigned   cmScMatcherScan( cmScMatcher* p, unsigned bsi, unsigned scanCnt )
2094 2111
         if( p->mp->opt_cost < s_opt )
2095 2112
         {
2096 2113
           s_opt = p->mp->opt_cost;
2097
-          i_opt = bsi + i;
2114
+          i_opt = bli + i;
2098 2115
         }
2099 2116
         break;
2100 2117
 
@@ -2104,7 +2121,6 @@ unsigned   cmScMatcherScan( cmScMatcher* p, unsigned bsi, unsigned scanCnt )
2104 2121
       default: // error state
2105 2122
         return cmInvalidIdx;
2106 2123
     }
2107
-
2108 2124
   }
2109 2125
           
2110 2126
   // store the cost assoc'd with i_opt
@@ -2115,10 +2131,10 @@ unsigned   cmScMatcherScan( cmScMatcher* p, unsigned bsi, unsigned scanCnt )
2115 2131
 
2116 2132
   // set the locIdx field in midiBuf[], trailing miss count and
2117 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 2136
   // if no positive matches were found
2121
-  if( p->esi == cmInvalidIdx )
2137
+  if( p->eli == cmInvalidIdx )
2122 2138
     i_opt = cmInvalidIdx;
2123 2139
   else
2124 2140
   {
@@ -2140,18 +2156,19 @@ cmRC_t     cmScMatcherStep(  cmScMatcher* p )
2140 2156
   unsigned pitch  = p->midiBuf[ p->mn-1 ].pitch;
2141 2157
   unsigned locIdx = cmInvalidIdx;
2142 2158
   unsigned pidx   = cmInvalidIdx;
2159
+
2143 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 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 2166
     return cmEofRC;
2150 2167
     
2151 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 2173
   else
2157 2174
   {
@@ -2159,16 +2176,16 @@ cmRC_t     cmScMatcherStep(  cmScMatcher* p )
2159 2176
     for(i=2; i<p->stepCnt; ++i)
2160 2177
     {
2161 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 2182
         break;
2166 2183
       }
2167 2184
 
2168 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 2189
         break;
2173 2190
       }
2174 2191
     }
@@ -2184,7 +2201,7 @@ cmRC_t     cmScMatcherStep(  cmScMatcher* p )
2184 2201
   else
2185 2202
   {
2186 2203
     p->missCnt = 0;
2187
-    p->esi     = locIdx;
2204
+    p->eli     = locIdx;
2188 2205
   }
2189 2206
 
2190 2207
   // store the result
@@ -2192,32 +2209,36 @@ cmRC_t     cmScMatcherStep(  cmScMatcher* p )
2192 2209
 
2193 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 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 2215
     ++p->scanCnt;
2199 2216
 
2200 2217
     // if the scan failed find a match
2201
-    if( bsi == cmInvalidIdx )
2218
+    if( bli == cmInvalidIdx )
2202 2219
       return cmCtxRtCondition( &p->obj, cmSubSysFailRC, "Scan resync. failed."); 
2203
-
2204 2220
   }
2205 2221
 
2206 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 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 2238
   // if the MIDI buffer transitioned to full then perform an initial scan sync.
2218 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 2242
       rc = cmInvalidArgRC; // signal init. scan sync. fail
2222 2243
     else
2223 2244
     {
@@ -2231,8 +2252,10 @@ cmRC_t     cmScMatcherExec(  cmScMatcher* p, unsigned smpIdx, unsigned status, c
2231 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 2261
 double cmScMatcherFMeas( cmScMatcher* p )
@@ -2603,6 +2626,8 @@ cmRC_t    cmScMeasInit(  cmScMeas* p, cmScH_t scH, double srate, const unsigned*
2603 2626
 
2604 2627
   //_cmScMeasPrint(p);
2605 2628
 
2629
+  cmScMeasReset(p);
2630
+
2606 2631
   return rc;
2607 2632
 }
2608 2633
 
@@ -2614,7 +2639,12 @@ cmRC_t    cmScMeasReset( cmScMeas* p )
2614 2639
   cmRC_t rc = cmOkRC;
2615 2640
   p->mii    = 0;
2616 2641
   p->nsi    = cmInvalidIdx;
2642
+  p->vsi    = cmInvalidIdx;
2617 2643
   p->nsli   = cmInvalidIdx;
2644
+
2645
+  unsigned i;
2646
+  for(i=0; i<p->sn; ++i)
2647
+    p->set[i].value = DBL_MAX;
2618 2648
   return rc;
2619 2649
 }
2620 2650
 
@@ -2761,6 +2791,7 @@ unsigned _cmScMeasTimeAlign( cmScMeas* p, cmScMeasSet_t* sp, cmScMatchMidi_t* m,
2761 2791
 
2762 2792
   assert(bn<=cn);
2763 2793
 
2794
+  // TODO: this copy should be eliminated
2764 2795
   // copy to output
2765 2796
   for(i=0; i<bn && i<cn; ++i)
2766 2797
     c[i] = b[i];
@@ -2900,11 +2931,49 @@ double _cmScMeasDyn( cmScMeas* p, cmScMeasSet_t* sp, cmScMatchMidi_t* m, unsigne
2900 2931
   return rp->value;
2901 2932
 }
2902 2933
 
2934
+
2903 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 2977
   int      i;
2909 2978
 
2910 2979
   if( n_mii == 0 )
@@ -2930,7 +2999,6 @@ void _cmScMeasMatch( cmScMeas* p, cmScMeasSet_t* sp, int n_mii )
2930 2999
 
2931 3000
   assert(mn>0);
2932 3001
 
2933
-
2934 3002
   // Create a copy of the the MIDI buffer to prevent the
2935 3003
   // p->midiBuf[].locIdx from being overwritten by cmScMatchDoSync().
2936 3004
   cmScMatchMidi_t mb[ mn ];
@@ -2944,11 +3012,13 @@ void _cmScMeasMatch( cmScMeas* p, cmScMeasSet_t* sp, int n_mii )
2944 3012
   // In general the first and last MIDI event should be assigned
2945 3013
   // to a score location - it's possible however that no MIDI
2946 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 3023
   // match MIDI to score
2954 3024
   if( cmScMatchExec(p->mp, bli, ln, mb, mn, min_cost ) != cmOkRC )
@@ -2958,65 +3028,32 @@ void _cmScMeasMatch( cmScMeas* p, cmScMeasSet_t* sp, int n_mii )
2958 3028
   if( cmScMatchDoSync(p->mp, bli, mb, mn, NULL ) == cmInvalidIdx )
2959 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 3031
   switch( sp->sp->varId )
2974 3032
   {
2975 3033
     case kEvenVarScId:  
2976
-      label = "even";  
2977
-      val   = _cmScMeasEven(p, sp, mb, mn, &r );
3034
+      sp->value = _cmScMeasEven(p, sp, mb, mn, &r );
2978 3035
       break;
2979 3036
 
2980 3037
     case kDynVarScId:   
2981
-      label = "dyn";   
2982
-      val   = _cmScMeasDyn(p, sp, mb, mn, &r );
3038
+      sp->value = _cmScMeasDyn(p, sp, mb, mn, &r );
2983 3039
       break;
2984 3040
 
2985 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 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 3057
 cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtIdx, unsigned flags, unsigned smpIdx, unsigned pitch, unsigned vel )
3021 3058
 {
3022 3059
   cmRC_t rc = cmOkRC;
@@ -3026,6 +3063,7 @@ cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtI
3026 3063
     return cmCtxRtCondition( &p->obj, cmEofRC, "The MIDI buffer is full."); 
3027 3064
 
3028 3065
   int n_mii = cmInvalidIdx;
3066
+  // locate the MIDI event assoc'd with 'mni'  ...
3029 3067
   if( p->mii>0 && mni <= p->midiBuf[p->mii-1].mni )
3030 3068
   {
3031 3069
     if( locIdx != cmInvalidIdx )
@@ -3038,7 +3076,7 @@ cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtI
3038 3076
         n_mii = cmInvalidIdx;
3039 3077
     }
3040 3078
   }
3041
-  else
3079
+  else // ... or push a new record onto p->midiBuf[]
3042 3080
   {
3043 3081
     n_mii = p->mii;
3044 3082
     ++p->mii;
@@ -3052,8 +3090,6 @@ cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtI
3052 3090
   p->midiBuf[n_mii].pitch    = pitch;
3053 3091
   p->midiBuf[n_mii].vel      = vel;
3054 3092
 
3055
-  //++p->mi;
3056
-
3057 3093
   if( locIdx == cmInvalidIdx )
3058 3094
     return cmOkRC;
3059 3095
 
@@ -3078,6 +3114,8 @@ cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtI
3078 3114
       return rc;
3079 3115
   }
3080 3116
 
3117
+  p->vsi = p->nsi;
3118
+
3081 3119
   // for each cmScore location between p->nsli and scLocIdx 
3082 3120
   for(; p->nsli<=scLocIdx && p->nsi < p->sn; ++p->nsli)
3083 3121
   {
@@ -3085,7 +3123,9 @@ cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned scEvtI
3085 3123
     // ahead of the next sets ending location.
3086 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 3130
       // advance the set index
3091 3131
       ++p->nsi;
@@ -3114,7 +3154,7 @@ cmRC_t cmScAlignScanToTimeLineEvent( cmScMatcher* p, cmTlH_t tlH, cmTlObj_t* top
3114 3154
     // if the time line MIDI msg a note-on
3115 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 3159
       switch( rc )
3120 3160
       {
@@ -3124,11 +3164,14 @@ cmRC_t cmScAlignScanToTimeLineEvent( cmScMatcher* p, cmTlH_t tlH, cmTlObj_t* top
3124 3164
         case cmEofRC:       // end of the score was encountered
3125 3165
           break;
3126 3166
 
3127
-        case cmInvalidArgRC: // p->esi was not set correctly
3167
+        case cmInvalidArgRC: // p->eli was not set correctly
3128 3168
           break;
3129 3169
 
3130 3170
         case cmSubSysFailRC: // scan resync failed
3131 3171
           break;
3172
+
3173
+        default:
3174
+          { assert(0); }
3132 3175
       }
3133 3176
     }
3134 3177
   }
@@ -3158,7 +3201,7 @@ void       cmScAlignScanMarkers(  cmRpt_t* rpt, cmTlH_t tlH, cmScH_t scH )
3158 3201
   unsigned     dynRefCnt    = sizeof(dynRefArray)/sizeof(dynRefArray[0]);
3159 3202
   cmCtx*       ctx          = cmCtxAlloc(NULL, rpt, cmLHeapNullHandle, cmSymTblNullHandle );
3160 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 3205
   double       scoreThresh  = 0.5;
3163 3206
   unsigned     candCnt      = 0;
3164 3207
   unsigned     initFailCnt  = 0;
@@ -3170,9 +3213,6 @@ void       cmScAlignScanMarkers(  cmRpt_t* rpt, cmTlH_t tlH, cmScH_t scH )
3170 3213
   cmTimeSpec_t t0,t1;
3171 3214
 
3172 3215
   cmTimeGet(&t0);
3173
-
3174
-  p->cbArg  = mp; // set the callback arg. 
3175
-  p->cbFunc = cmScMatcherCb; 
3176 3216
   
3177 3217
   // for each marker
3178 3218
   for(i=0; i<markN; ++i)
@@ -3199,7 +3239,7 @@ void       cmScAlignScanMarkers(  cmRpt_t* rpt, cmTlH_t tlH, cmScH_t scH )
3199 3239
 
3200 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 3243
     cmScMeasReset(mp);
3204 3244
 
3205 3245
     ++candCnt;

+ 49
- 19
cmProc4.h View File

@@ -335,47 +335,66 @@ typedef void (*cmScMatcherCb_t)( struct cmScMatcher_str* p, void* arg, cmScMatch
335 335
    unsigned             mn;
336 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 342
    double               s_opt;          // 
343 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 346
    unsigned             mni;            // track the count of MIDI events since the last call to cmScMatcherReset()
346 347
    unsigned             mbi;            // index of oldest MIDI event in midiBuf[]; 0 when the buffer is full.
347 348
    unsigned             begSyncLocIdx;  // start of score window, in mp->loc[], of best match in previous scan
348 349
    unsigned             stepCnt;        // count of forward/backward score loc's to examine for a match during cmScMatcherStep().
349 350
    unsigned             maxMissCnt;     // max. number of consecutive non-matches during step prior to executing a scan.
350 351
    unsigned             scanCnt;        // count of time scan was executed inside cmScMatcherStep()
352
+
353
+   bool                 printFl;
351 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 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 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 369
 // Returns the index into p->mp->loc[] of the start of the best
366 370
 // match score window. The score associated
367 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 376
 // If more than p->maxMissCnt consecutive MIDI events are 
373 377
 // missed then automatically run cmScAlignScan().
374 378
 // Return cmEofRC if the end of the score is encountered.
375 379
 // Return cmSubSysFailRC if an internal scan resync. failed.
376 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,13 +412,17 @@ typedef struct
393 412
   unsigned      bli;   // 
394 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 418
 } cmScMeasSet_t;
397 419
 
398 420
 typedef struct
399 421
 {
400 422
   cmObj            obj;
423
+  double           srate;    // 
401 424
   cmScMatch*       mp;       //
402
-  unsigned         mii;       // next avail recd in midiBuf[]
425
+  unsigned         mii;      // next avail recd in midiBuf[]
403 426
   unsigned         mn;       // length of of midiBuf[]
404 427
   cmScMatchMidi_t* midiBuf;  // midiBuf[mn]
405 428
 
@@ -409,15 +432,19 @@ typedef struct
409 432
   unsigned         dn;       // length of dynRef[]
410 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 440
 } cmScMeas;
417 441
 
442
+//
418 443
 // Notes:
444
+//
419 445
 // 1) midiBuf[] stores all MIDI notes for the duration of the performance
420 446
 // it is initialized to 2*score_event_count.
447
+//
421 448
 // 2) dynRef][ is the gives the MIDI velocity range for each dynamics
422 449
 // category: pppp-fff
423 450
 // 
@@ -428,6 +455,9 @@ cmRC_t    cmScMeasFree(  cmScMeas** pp );
428 455
 cmRC_t    cmScMeasInit(  cmScMeas* p, cmScH_t scH, double srate, const unsigned* dynRefArray, unsigned dynRefCnt );
429 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 461
 // This function is called for each input MIDI note which is assigned a
432 462
 // score location by cmScMatcher. 
433 463
 // 'mni' is the MIDI event index which uniquely identifies this MIDI event.

Loading…
Cancel
Save