|
@@ -200,7 +200,7 @@ void ed_main();
|
200
|
200
|
//=======================================================================================================================
|
201
|
201
|
enum
|
202
|
202
|
{
|
203
|
|
- kSmMinIdx,
|
|
203
|
+ kSmMinIdx, //
|
204
|
204
|
kSmSubIdx, // 'substitute' - may or may not match
|
205
|
205
|
kSmDelIdx, // 'delete' - delete a MIDI note
|
206
|
206
|
kSmInsIdx, // 'insert' - insert a space in the score
|
|
@@ -220,24 +220,25 @@ enum
|
220
|
220
|
// Dynamic Programming (DP) matrix element
|
221
|
221
|
typedef struct
|
222
|
222
|
{
|
223
|
|
- unsigned v[kSmCnt]; //
|
224
|
|
- unsigned flags;
|
|
223
|
+ unsigned v[kSmCnt]; // cost for each operation
|
|
224
|
+ unsigned flags; // cmSmMatchFl | cmSmTransFl
|
225
|
225
|
} cmScMatchVal_t;
|
226
|
226
|
|
227
|
227
|
// List record used to track a path through the DP matrix p->m[,]
|
228
|
228
|
typedef struct cmScMatchPath_str
|
229
|
229
|
{
|
230
|
|
- unsigned code;
|
231
|
|
- unsigned ri;
|
232
|
|
- unsigned ci;
|
233
|
|
- unsigned flags;
|
234
|
|
- unsigned locIdx;
|
235
|
|
- struct cmScMatchPath_str* next;
|
|
230
|
+ unsigned code; // kSmXXXIdx
|
|
231
|
+ unsigned ri; // matrix row index
|
|
232
|
+ unsigned ci; // matrix col index
|
|
233
|
+ unsigned flags; // cmSmMatchFl | cmSmTransFl
|
|
234
|
+ unsigned locIdx; // p->loc index or cmInvalidIdx
|
|
235
|
+ struct cmScMatchPath_str* next; //
|
236
|
236
|
} cmScMatchPath_t;
|
237
|
237
|
|
238
|
238
|
typedef struct cmScMatchEvt_str
|
239
|
239
|
{
|
240
|
|
- unsigned pitch;
|
|
240
|
+ unsigned pitch; //
|
|
241
|
+ unsigned scEvtIdx; // scScore event index
|
241
|
242
|
} cmScMatchEvt_t;
|
242
|
243
|
|
243
|
244
|
// Score location record.
|
|
@@ -251,8 +252,8 @@ typedef struct
|
251
|
252
|
|
252
|
253
|
typedef struct
|
253
|
254
|
{
|
254
|
|
- cmObj obj;
|
255
|
|
- cmScH_t scH; //
|
|
255
|
+ cmObj obj; //
|
|
256
|
+ cmScH_t scH; // cmScore handle
|
256
|
257
|
unsigned locN; //
|
257
|
258
|
cmScMatchLoc_t* loc; // loc[locN]
|
258
|
259
|
unsigned mrn; // max row count (midi)
|
|
@@ -275,17 +276,17 @@ cmRC_t cmScMatchFree( cmScMatch** pp );
|
275
|
276
|
cmRC_t cmScMatchInit( cmScMatch* p, cmScH_t scH, unsigned maxScWndN, unsigned maxMidiWndN );
|
276
|
277
|
cmRC_t cmScMatchFinal( cmScMatch* p );
|
277
|
278
|
|
278
|
|
-// Returns cmEofRC if scLocIdx + locN > p->locN - note that this is not necessarily an error.
|
|
279
|
+// Returns cmEofRC if locIdx + locN > p->locN - note that this is not necessarily an error.
|
279
|
280
|
// The optimal path p_opt[] will only be updated if the edit cost is less than min_cost.
|
280
|
281
|
// Set min_cost to DBL_MAX to force p_opt[] to be updated.
|
281
|
|
-cmRC_t cmScMatchExec( cmScMatch* p, unsigned scLocIdx, unsigned locN, const unsigned* midiPitchV, unsigned midiPitchN, double min_cost );
|
|
282
|
+cmRC_t cmScMatchExec( cmScMatch* p, unsigned locIdx, unsigned locN, const unsigned* midiPitchV, unsigned midiPitchN, double min_cost );
|
282
|
283
|
|
283
|
284
|
//=======================================================================================================================
|
284
|
285
|
|
285
|
286
|
typedef struct
|
286
|
287
|
{
|
287
|
288
|
unsigned locIdx; // location assoc'd with this MIDI evt (cmInvalidIdx if not a positive-match)
|
288
|
|
- unsigned cbCnt; // count of times this event has been sent via the callback
|
|
289
|
+ //unsigned cbCnt; // count of times this event has been sent via the callback
|
289
|
290
|
unsigned mni; // unique identifier for this event since previous call to cmScAlignReset().
|
290
|
291
|
unsigned smpIdx; // time stamp of this event
|
291
|
292
|
unsigned pitch; // MIDI note pitch
|
|
@@ -296,40 +297,47 @@ cmRC_t cmScMatchExec( cmScMatch* p, unsigned scLocIdx, unsigned locN, const
|
296
|
297
|
{
|
297
|
298
|
unsigned locIdx;
|
298
|
299
|
unsigned mni;
|
|
300
|
+ unsigned smpIdx;
|
299
|
301
|
unsigned pitch;
|
300
|
302
|
unsigned vel;
|
301
|
303
|
unsigned flags;
|
302
|
304
|
} cmScMatcherResult_t;
|
303
|
305
|
|
304
|
|
- typedef struct
|
|
306
|
+struct cmScMatcher_str;
|
|
307
|
+typedef void (*cmScMatcherCb_t)( struct cmScMatcher_str* p, void* arg, cmScMatcherResult_t* rp );
|
|
308
|
+
|
|
309
|
+ typedef struct cmScMatcher_str
|
305
|
310
|
{
|
306
|
|
- cmObj obj;
|
307
|
|
- cmScMatch* mp;
|
308
|
|
- unsigned mn;
|
309
|
|
- cmScMatcherMidi_t* midiBuf; // midiBuf[mn]
|
|
311
|
+ cmObj obj;
|
|
312
|
+ cmScMatcherCb_t cbFunc;
|
|
313
|
+ void* cbArg;
|
|
314
|
+ cmScMatch* mp;
|
|
315
|
+ unsigned mn;
|
|
316
|
+ cmScMatcherMidi_t* midiBuf; // midiBuf[mn]
|
310
|
317
|
|
311
|
318
|
cmScMatcherResult_t* res; // res[rn]
|
312
|
319
|
unsigned rn; // length of res[]
|
313
|
320
|
unsigned ri; // next avail res[] recd.
|
314
|
321
|
|
315
|
|
- double s_opt; //
|
316
|
|
- unsigned missCnt; // count of consecutive trailing non-matches
|
317
|
|
- unsigned esi; // index into loc[] of the last positive match.
|
318
|
|
- unsigned mni; // track the count of MIDI events since the last call to cmScMatcherReset()
|
319
|
|
- unsigned mbi; // index of oldest MIDI event in midiBuf[]; 0 when the buffer is full.
|
320
|
|
- unsigned begSyncLocIdx; // start of score window, in mp->loc[], of best match in previous scan
|
321
|
|
- unsigned stepCnt; // count of forward/backward score loc's to examine for a match during cmScMatcherStep().
|
322
|
|
- unsigned maxMissCnt; // max. number of consecutive non-matches during step prior to executing a scan.
|
323
|
|
- unsigned scanCnt; // count of time scan was executed inside cmScMatcherStep()
|
|
322
|
+ double s_opt; //
|
|
323
|
+ unsigned missCnt; // count of consecutive trailing non-matches
|
|
324
|
+ unsigned esi; // index into loc[] of the last positive match.
|
|
325
|
+ unsigned mni; // track the count of MIDI events since the last call to cmScMatcherReset()
|
|
326
|
+ unsigned mbi; // index of oldest MIDI event in midiBuf[]; 0 when the buffer is full.
|
|
327
|
+ unsigned begSyncLocIdx; // start of score window, in mp->loc[], of best match in previous scan
|
|
328
|
+ unsigned stepCnt; // count of forward/backward score loc's to examine for a match during cmScMatcherStep().
|
|
329
|
+ unsigned maxMissCnt; // max. number of consecutive non-matches during step prior to executing a scan.
|
|
330
|
+ unsigned scanCnt; // count of time scan was executed inside cmScMatcherStep()
|
324
|
331
|
} cmScMatcher;
|
325
|
332
|
|
326
|
333
|
|
|
334
|
+
|
327
|
335
|
cmScMatcher* cmScMatcherAlloc( cmCtx* c, cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN );
|
328
|
336
|
cmRC_t cmScMatcherFree( cmScMatcher** pp );
|
329
|
337
|
cmRC_t cmScMatcherInit( cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN );
|
330
|
338
|
cmRC_t cmScMatcherFinal( cmScMatcher* p );
|
331
|
339
|
void cmScMatcherReset( cmScMatcher* p );
|
332
|
|
-bool cmScMatcherInputMidi( cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
|
|
340
|
+bool cmScMatcherInputMidi( cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
|
333
|
341
|
|
334
|
342
|
// Slide a score window scanCnt times, beginning at 'bsi',
|
335
|
343
|
// looking for the best match to p->midiBuf[]. The score window
|
|
@@ -350,185 +358,64 @@ cmRC_t cmScMatcherStep( cmScMatcher* p );
|
350
|
358
|
cmRC_t cmScMatcherExec( cmScMatcher* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
|
351
|
359
|
|
352
|
360
|
|
353
|
|
-
|
354
|
|
-//=======================================================================================================================
|
355
|
|
-enum
|
356
|
|
-{
|
357
|
|
- kSaMinIdx,
|
358
|
|
- kSaSubIdx, // 'substitute' - may or may not match
|
359
|
|
- kSaDelIdx, // 'delete' - delete a MIDI note
|
360
|
|
- kSaInsIdx, // 'insert' - insert a space in the score
|
361
|
|
- kSaCnt
|
362
|
|
-};
|
363
|
|
-
|
364
|
|
-// Dynamic Programming (DP) matrix element
|
365
|
|
-typedef struct
|
366
|
|
-{
|
367
|
|
- unsigned v[kSaCnt]; //
|
368
|
|
- bool matchFl; // if this is a substitute; is it also a match?
|
369
|
|
- bool transFl; // if this is a substitute; is this the second element in a reversed pair?
|
370
|
|
-} cmScAlignVal_t;
|
371
|
|
-
|
372
|
|
-// List record used to track a path through the DP matrix p->m[,]
|
373
|
|
-typedef struct cmScAlignPath_str
|
374
|
|
-{
|
375
|
|
- unsigned code;
|
376
|
|
- unsigned ri;
|
377
|
|
- unsigned ci;
|
378
|
|
- bool matchFl;
|
379
|
|
- bool transFl;
|
380
|
|
- unsigned locIdx;
|
381
|
|
- struct cmScAlignPath_str* next;
|
382
|
|
-} cmScAlignPath_t;
|
383
|
|
-
|
384
|
|
-// Score note event record
|
385
|
|
-typedef struct
|
386
|
|
-{
|
387
|
|
- unsigned pitch;
|
388
|
|
-} cmScAlignScEvt_t;
|
389
|
|
-
|
390
|
|
-// Score location record.
|
391
|
|
-typedef struct
|
392
|
|
-{
|
393
|
|
- unsigned evtCnt; //
|
394
|
|
- cmScAlignScEvt_t* evtV; // evtV[evtCnt]
|
395
|
|
- unsigned scLocIdx; // scH score location index
|
396
|
|
- int barNumb; // bar number of this location
|
397
|
|
-} cmScAlignLoc_t;
|
398
|
|
-
|
399
|
|
-typedef struct
|
400
|
|
-{
|
401
|
|
- unsigned locIdx; // location assoc'd with this MIDI evt (cmInvalidIdx if not a positive-match)
|
402
|
|
- unsigned cbCnt; // count of times this event has been sent via the callback
|
403
|
|
- unsigned mni; // unique identifier for this event since previous call to cmScAlignReset().
|
404
|
|
- unsigned smpIdx; // time stamp of this event
|
405
|
|
- unsigned pitch; // MIDI note pitch
|
406
|
|
- unsigned vel; // " " velocity
|
407
|
|
-} cmScAlignMidiEvt_t;
|
408
|
|
-
|
409
|
|
-typedef struct
|
410
|
|
-{
|
411
|
|
- unsigned locIdx; // loc[] sync. location
|
412
|
|
- unsigned smpIdx; //
|
413
|
|
- unsigned mni; // MIDI event unique index
|
414
|
|
- unsigned pitch; // MIDI event pitch which may not match the score event pitch
|
415
|
|
- unsigned vel; // " " velocity
|
416
|
|
- bool matchFl;
|
417
|
|
- bool transFl;
|
418
|
|
- bool foundFl;
|
419
|
|
-} cmScAlignResult_t;
|
420
|
|
-
|
421
|
|
-//
|
422
|
|
-typedef void (*cmScAlignCb_t)( void* cbArg, unsigned scLocIdx, unsigned mni, unsigned pitch, unsigned vel );
|
423
|
|
-
|
424
|
|
-typedef struct
|
425
|
|
-{
|
426
|
|
- cmObj obj;
|
427
|
|
- cmScAlignCb_t cbFunc; //
|
428
|
|
- void* cbArg; //
|
429
|
|
- cmScH_t scH; //
|
430
|
|
- double srate; //
|
431
|
|
- unsigned locN; // length of loc[]
|
432
|
|
- cmScAlignLoc_t* loc; // loc[locN] score array
|
433
|
|
- unsigned rn; // length of midiBuf[] (mn+1)
|
434
|
|
- unsigned cn; // length of score window (scWndN+1)
|
435
|
|
- unsigned mn; // length of midiBuf[] (rn-1)
|
436
|
|
- cmScAlignMidiEvt_t* midiBuf; // midiBuf[ mn ]
|
437
|
|
- unsigned mbi; // index of first element in midiBuf[] - this is required because the MIDI buf fills from the end to the beginning
|
438
|
|
- unsigned mni; // index of event in midiBuf[p->mn] - increments on each note inserted into midiBuf[] - zeroed by cmScAlignReset().
|
439
|
|
-
|
440
|
|
- cmScAlignVal_t* m; // m[rn,cn]
|
441
|
|
- unsigned pn; // rn+cn
|
442
|
|
- cmScAlignPath_t* p_mem; // pmem[ 2*pn ];
|
443
|
|
- cmScAlignPath_t* p_avl; // available path record linked list
|
444
|
|
- cmScAlignPath_t* p_cur; // current path linked list
|
445
|
|
- cmScAlignPath_t* p_opt; // p_opt[pn] current best alignment
|
446
|
|
- double s_opt; // score of the current best alignment
|
447
|
|
- unsigned esi; // loc[] index of latest positive match
|
448
|
|
- unsigned missCnt; // count of consecutive trailing MIDI events without positive matches
|
449
|
|
- unsigned scanCnt;
|
450
|
|
-
|
451
|
|
- bool printFl;
|
452
|
|
-
|
453
|
|
- unsigned begScanLocIdx; // begin the search at this score locations scWnd[begScanLocIdx:begScanLocIdx+p->cn-1]
|
454
|
|
- unsigned begSyncLocIdx; // initial sync location
|
455
|
|
-
|
456
|
|
- unsigned resN; // count of records in res[] == 2*cmScoreEvtCount()
|
457
|
|
- cmScAlignResult_t* res; // res[resN]
|
458
|
|
- unsigned ri; //
|
459
|
|
-
|
460
|
|
- int stepCnt; // count of loc[] locations to step ahead/back during a cmScAlignStep() operation.
|
461
|
|
- int maxStepMissCnt; // max. consecutive trailing non-positive matches before a scan takes place.
|
462
|
|
-
|
463
|
|
-
|
464
|
|
-} cmScAlign;
|
465
|
|
-
|
466
|
|
-cmScAlign* cmScAlignAlloc( cmCtx* ctx, cmScAlign* p, cmScAlignCb_t cbFunc, void* cbArg, cmReal_t srate, cmScH_t scH, unsigned midiN, unsigned scWndN );
|
467
|
|
-cmRC_t cmScAlignFree( cmScAlign** pp );
|
468
|
|
-cmRC_t cmScAlignInit( cmScAlign* p, cmScAlignCb_t cbFunc, void* cbArg, cmReal_t srate, cmScH_t scH, unsigned midiN, unsigned scWndN );
|
469
|
|
-cmRC_t cmScAlignFinal( cmScAlign* p );
|
470
|
|
-void cmScAlignReset( cmScAlign* p, unsigned begScanLocIdx );
|
471
|
|
-
|
472
|
|
-cmRC_t cmScAlignExec( cmScAlign* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
|
473
|
|
-
|
474
|
|
-bool cmScAlignInputMidi( cmScAlign* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1 );
|
475
|
|
-
|
476
|
|
-// Scan from p->begScanLocIdx to the end of the score looking
|
477
|
|
-// for the best match to p->midiBuf[].
|
478
|
|
-// Returns the score location index which best matches the
|
479
|
|
-// first note p->midiBuf[]. The score associated
|
480
|
|
-// with this match is stored in s_opt.
|
481
|
|
-unsigned cmScAlignScan( cmScAlign* p, unsigned scanCnt );
|
482
|
|
-
|
483
|
|
-// Step forward/back by p->stepCnt from p->esi.
|
484
|
|
-// If more than p->maxStepMissCnt consecutive MIDI events are
|
485
|
|
-// missed then automatically run cmScAlignScan().
|
486
|
|
-// Return cmEofRC if the end of the score is encountered.
|
487
|
|
-// Return cmSubSysFailRC if an internal scan resync. failed.
|
488
|
|
-cmRC_t cmScAlignStep( cmScAlign* p );
|
489
|
|
-
|
490
|
|
-unsigned cmScAlignScanToTimeLineEvent( cmScMatcher* p, cmTlH_t tlH, cmTlObj_t* top, unsigned endSmpIdx );
|
491
|
|
-
|
492
|
|
-// Given a score, a time-line, and a marker on the time line scan the
|
493
|
|
-// entire score looking for the best match between the first 'midiN'
|
494
|
|
-// notes in each marker region and the score.
|
495
|
|
-void cmScAlignScanMarkers( cmRpt_t* rpt, cmTlH_t tlH, cmScH_t scH );
|
496
|
|
-
|
497
|
361
|
//=======================================================================================================================
|
498
|
362
|
|
499
|
363
|
typedef struct
|
500
|
364
|
{
|
501
|
365
|
unsigned mni;
|
|
366
|
+ unsigned scEvtIdx;
|
502
|
367
|
unsigned locIdx;
|
|
368
|
+ unsigned smpIdx;
|
503
|
369
|
unsigned pitch;
|
504
|
370
|
unsigned vel;
|
505
|
|
- unsigned smpIdx;
|
506
|
371
|
} cmScMeasMidi_t;
|
507
|
372
|
|
|
373
|
+
|
508
|
374
|
typedef struct
|
509
|
375
|
{
|
510
|
|
- cmScoreSet_t* set; // A pointer to defining score set
|
511
|
|
- unsigned bli; // Begin index into sap->loc[].
|
512
|
|
- unsigned eli; // End index into sap->loc[].
|
513
|
|
- unsigned bmi; // Begin index into midi[].
|
514
|
|
- unsigned emi; // End index into midi[].
|
515
|
|
- double* val; // val[sap->eleCnt]
|
|
376
|
+ unsigned bsei; // begin score event index
|
|
377
|
+ unsigned esei; // end score event index
|
|
378
|
+
|
|
379
|
+ unsigned bsli; //
|
|
380
|
+ unsigned esli; // end score loc index
|
|
381
|
+
|
|
382
|
+ unsigned bli; //
|
|
383
|
+ unsigned eli; //
|
|
384
|
+
|
516
|
385
|
} cmScMeasSet_t;
|
517
|
386
|
|
518
|
387
|
typedef struct
|
519
|
388
|
{
|
520
|
389
|
cmObj obj;
|
521
|
|
- cmScAlign* sap;
|
522
|
|
- unsigned mn;
|
523
|
|
- cmScMeasMidi_t* midi;
|
|
390
|
+ cmScMatch* mp;
|
|
391
|
+ unsigned mi; // next avail recd in midiBuf[]
|
|
392
|
+ unsigned mn; // length of of midiBuf[]
|
|
393
|
+ cmScMeasMidi_t* midiBuf; // midiBuf[mn]
|
|
394
|
+
|
|
395
|
+ unsigned sn; // length of set[]
|
|
396
|
+ cmScMeasSet_t* set; // set[sn]
|
|
397
|
+
|
|
398
|
+ unsigned nsi; // next set index
|
|
399
|
+ unsigned nsli; // next score location index
|
|
400
|
+
|
|
401
|
+
|
524
|
402
|
} cmScMeas;
|
525
|
403
|
|
526
|
|
-cmScMeas* cmScMeasAlloc( cmCtx* c, cmScMeas* p, double srate, cmScH_t scH );
|
|
404
|
+cmScMeas* cmScMeasAlloc( cmCtx* c, cmScMeas* p, cmScH_t scH );
|
527
|
405
|
cmRC_t cmScMeasFree( cmScMeas** pp );
|
528
|
|
-cmRC_t cmScMeasInit( cmScMeas* p, double srate, cmScH_t scH );
|
|
406
|
+cmRC_t cmScMeasInit( cmScMeas* p, cmScH_t scH );
|
529
|
407
|
cmRC_t cmScMeasFinal( cmScMeas* p );
|
530
|
|
-cmRC_t cmScMeasExec( cmScMeas* p, unsigned smpIdx, unsigned status, cmMidiByte_t d0, cmMidiByte_t d1, unsigned scLocIdx );
|
|
408
|
+cmRC_t cmScMeasExec( cmScMeas* p, unsigned mni, unsigned locIdx, unsigned smpIdx, unsigned pitch, unsigned vel );
|
|
409
|
+
|
531
|
410
|
|
|
411
|
+//=======================================================================================================================
|
|
412
|
+
|
|
413
|
+unsigned cmScAlignScanToTimeLineEvent( cmScMatcher* p, cmTlH_t tlH, cmTlObj_t* top, unsigned endSmpIdx );
|
|
414
|
+
|
|
415
|
+// Given a score, a time-line, and a marker on the time line scan the
|
|
416
|
+// entire score looking for the best match between the first 'midiN'
|
|
417
|
+// notes in each marker region and the score.
|
|
418
|
+void cmScAlignScanMarkers( cmRpt_t* rpt, cmTlH_t tlH, cmScH_t scH );
|
532
|
419
|
|
533
|
420
|
#ifdef __cplusplus
|
534
|
421
|
}
|