Browse Source

cmProc4.h/c: Added cmScMatch and cmScMatcher to replace cmScAlign.

master
kevin 11 years ago
parent
commit
0819c27f8e
2 changed files with 1326 additions and 172 deletions
  1. 1176
    171
      cmProc4.c
  2. 150
    1
      cmProc4.h

+ 1176
- 171
cmProc4.c
File diff suppressed because it is too large
View File


+ 150
- 1
cmProc4.h View File

@@ -196,7 +196,156 @@ void ed_free(ed_r* r);
196 196
 
197 197
 // Main test function.
198 198
 void ed_main();
199
+
199 200
 //=======================================================================================================================
201
+enum 
202
+{ 
203
+  kSmMinIdx, 
204
+  kSmSubIdx, // 'substitute' - may or may not match
205
+  kSmDelIdx, // 'delete'     - delete a MIDI note 
206
+  kSmInsIdx, // 'insert'     - insert a space in the score 
207
+  kSmCnt 
208
+};
209
+
210
+enum
211
+{
212
+  kSmMatchFl = 0x01,
213
+  kSmTransFl = 0x02
214
+};
215
+
216
+// Dynamic Programming (DP) matrix element
217
+typedef struct
218
+{
219
+  unsigned v[kSmCnt]; // 
220
+  unsigned flags;
221
+} cmScMatchVal_t;
222
+
223
+// List record used to track a path through the DP matrix p->m[,]
224
+typedef struct cmScMatchPath_str
225
+{
226
+  unsigned                  code;
227
+  unsigned                  ri;
228
+  unsigned                  ci;
229
+  unsigned                  flags;
230
+  unsigned                  locIdx;
231
+  struct cmScMatchPath_str* next;
232
+} cmScMatchPath_t;
233
+
234
+typedef struct cmScMatchEvt_str
235
+{
236
+  unsigned pitch;
237
+} cmScMatchEvt_t;
238
+
239
+// Score location record. 
240
+typedef struct
241
+{
242
+  unsigned        evtCnt;       // 
243
+  cmScMatchEvt_t* evtV;         // evtV[evtCnt]
244
+  unsigned        scLocIdx;     // scH score location index
245
+  int             barNumb;      // bar number of this location
246
+} cmScMatchLoc_t;
247
+
248
+typedef struct
249
+{
250
+  cmObj            obj;
251
+  cmScH_t          scH;         //
252
+  unsigned         locN;        //
253
+  cmScMatchLoc_t*  loc;         // loc[locN] 
254
+  unsigned         mrn;         // max row count (midi)
255
+  unsigned         rn;          // cur row count
256
+  unsigned         mcn;         // max column count (score)
257
+  unsigned         cn;          // cur column count
258
+  unsigned         mmn;         // max length of midiBuf[]    (mrn-1)
259
+  unsigned         msn;         // max length of score window (mcn-1)
260
+  cmScMatchVal_t*  m;           // m[mrn,mcn]  DP matrix
261
+  unsigned         pn;          // mrn+mcn
262
+  cmScMatchPath_t* p_mem;       // pmem[ 2*pn ];
263
+  cmScMatchPath_t* p_avl;       // available path record linked list
264
+  cmScMatchPath_t* p_cur;       // current path linked list
265
+  cmScMatchPath_t* p_opt;       // p_opt[pn] current best alignment 
266
+  double           opt_cost;    // p_opt cost set by cmScMatchExec() 
267
+} cmScMatch;
268
+
269
+cmScMatch* cmScMatchAlloc( cmCtx* c, cmScMatch* p, cmScH_t scH, unsigned maxScWndN, unsigned maxMidiWndN );
270
+cmRC_t     cmScMatchFree(  cmScMatch** pp );
271
+cmRC_t     cmScMatchInit(  cmScMatch* p, cmScH_t scH, unsigned maxScWndN, unsigned maxMidiWndN );
272
+cmRC_t     cmScMatchFinal( cmScMatch* p );
273
+
274
+// Returns cmEofRC if scLocIdx + locN > p->locN - note that this is not necessarily an error.
275
+// The optimal path p_opt[] will only be updated if the edit cost is less than min_cost.
276
+// Set min_cost to DBL_MAX to force p_opt[] to be updated.
277
+cmRC_t     cmScMatchExec(  cmScMatch* p, unsigned scLocIdx, unsigned locN, const unsigned* midiPitchV, unsigned midiPitchN, double min_cost );
278
+
279
+ //=======================================================================================================================
280
+
281
+ typedef struct
282
+ {
283
+   unsigned locIdx; // location assoc'd with this MIDI evt (cmInvalidIdx if not a positive-match)
284
+   unsigned cbCnt;  // count of times this event has been sent via the callback
285
+   unsigned mni;    // unique identifier for this event since previous call to cmScAlignReset().
286
+   unsigned smpIdx; // time stamp of this event
287
+   unsigned pitch;  // MIDI note pitch
288
+   unsigned vel;    //  "    "   velocity
289
+ } cmScMatcherMidi_t;
290
+
291
+ typedef struct
292
+ {
293
+   unsigned locIdx;
294
+   unsigned mni;
295
+   unsigned pitch;
296
+   unsigned vel;
297
+   bool     tpFl;   // true positive     
298
+   bool     fpFl;   // false positive
299
+ } cmScMatcherResult_t;
300
+
301
+ typedef struct
302
+ {
303
+   cmObj              obj;
304
+   cmScMatch*         mp;
305
+   unsigned           mn;
306
+   cmScMatcherMidi_t* midiBuf;  // midiBuf[mn]
307
+
308
+   cmScMatcherResult_t* res;    // res[rn]
309
+   unsigned             rn;     // length of res[]
310
+   unsigned             ri;     // next avail res[] recd.
311
+
312
+   double             s_opt;          // 
313
+   unsigned           missCnt;        // count of consecutive trailing non-matches
314
+   unsigned           esi;            // index into loc[] of the last positive match. 
315
+   unsigned           mni;            // track the count of MIDI events since the last call to cmScMatcherReset()
316
+   unsigned           mbi;            // index of oldest MIDI event in midiBuf[]; 0 when the buffer is full.
317
+   unsigned           begSyncLocIdx;  // start of score window, in mp->loc[], of best match in previous scan
318
+   unsigned           stepCnt;        // count of forward/backward score loc's to examine for a match during cmScMatcherStep().
319
+   unsigned           maxMissCnt;     // max. number of consecutive non-matches during step prior to executing a scan.
320
+   unsigned           scanCnt;        // count of time scan was executed inside cmScMatcherStep()
321
+} cmScMatcher;
322
+
323
+
324
+cmScMatcher* cmScMatcherAlloc( cmCtx* c, cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN );
325
+cmRC_t       cmScMatcherFree(  cmScMatcher** pp );
326
+cmRC_t       cmScMatcherInit(  cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN );
327
+cmRC_t       cmScMatcherFinal( cmScMatcher* p );
328
+void         cmScMatcherReset( cmScMatcher* p );
329
+bool         cmScMatcherInputMidi(  cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
330
+
331
+// Slide a score window scanCnt times, beginning at 'bsi',
332
+// looking for the best match to p->midiBuf[].  The score window
333
+// contain scWndN (p->mp->mcn-1) score locations.
334
+// Returns the index into p->mp->loc[] of the start of the best
335
+// match score window. The score associated
336
+// with this match is stored in s_opt.
337
+unsigned   cmScMatcherScan( cmScMatcher* p, unsigned bsi, unsigned scanCnt );
338
+
339
+// Step forward/back by p->stepCnt from p->esi.
340
+// p->esi must therefore be valid prior to calling this function.
341
+// If more than p->maxMissCnt consecutive MIDI events are 
342
+// missed then automatically run cmScAlignScan().
343
+// Return cmEofRC if the end of the score is encountered.
344
+// Return cmSubSysFailRC if an internal scan resync. failed.
345
+cmRC_t     cmScMatcherStep(  cmScMatcher* p );
346
+
347
+cmRC_t     cmScMatcherExec(  cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
348
+
200 349
 
201 350
  
202 351
 //=======================================================================================================================
@@ -335,7 +484,7 @@ unsigned   cmScAlignScan( cmScAlign* p, unsigned scanCnt );
335 484
 // Return cmSubSysFailRC if an internal scan resync. failed.
336 485
 cmRC_t     cmScAlignStep(  cmScAlign* p );
337 486
 
338
-unsigned   cmScAlignScanToTimeLineEvent( cmScAlign* p, cmTlH_t tlH, cmTlObj_t* top, unsigned endSmpIdx );
487
+unsigned   cmScAlignScanToTimeLineEvent( cmScMatcher* p, cmTlH_t tlH, cmTlObj_t* top, unsigned endSmpIdx );
339 488
 
340 489
 // Given a score, a time-line, and a marker on the time line scan the
341 490
 // entire score looking for the best match between the first 'midiN'

Loading…
Cancel
Save