Parcourir la source

cmScoreProc.h : Completed the cmSpAssocProc_t based processing.

Added kNoteNoSpid and kFailSpId messages to the score tracking processor callback.
master
Kevin Larke il y a 9 ans
Parent
révision
e5dbc44c61
1 fichiers modifiés avec 226 ajouts et 53 suppressions
  1. 226
    53
      app/cmScoreProc.c

+ 226
- 53
app/cmScoreProc.c Voir le fichier

@@ -20,33 +20,23 @@
20 20
 #include "cmProcObj.h"
21 21
 #include "cmProc4.h"
22 22
 
23
-enum
24
-{
25
-  kOkSpRC,
26
-  kJsonFailSpRC,
27
-  kScoreFailSpRC,
28
-  kTimeLineFailSpRC,
29
-  kScoreMatchFailSpRC,
30
-  kFileFailSpRC,
31
-  kProcFailSpRC
32
-};
33
-
34 23
 typedef enum
35 24
 {
36
-  kBeginSectionSpId,
37
-  kEndSectionSpId
25
+  kBeginSectionSpId,  // tlObjPtr points to a cmTlMarker_t object.
26
+  kEndSectionSpId,    // tlObjPtr is NULL.
27
+  kNoteOnSpId,        // tlObjPtr points to a cmTlMidiEvt_t note-on object.
28
+  kFailSpId           // tlObjPtr points to a cmTlMarker_t object (This section score tracking failed.)
38 29
 } cmScoreProcSelId_t;
39 30
 
40 31
 struct cmSp_str;
41 32
 
42
-typedef cmSpRC_t (*cmScoreProcCb_t)( void* arg, struct cmSp_str* p, cmScoreProcSelId_t id, cmTlMarker_t* curMarkPtr );
33
+typedef cmSpRC_t (*cmScoreProcCb_t)( void* arg, struct cmSp_str* p, cmScoreProcSelId_t id, cmTlObj_t* tlObjPtr );
43 34
 
44 35
 typedef struct cmSp_str
45 36
 {
46 37
   cmErr_t         err;          // score proc object error state
47 38
   cmCtx*          ctx;          // application context
48 39
   cmScH_t         scH;          // score object
49
-  const cmChar_t* tlFn;         // time-line filename
50 40
   cmTlH_t         tlH;          // time-line object
51 41
   cmJsonH_t       jsH;          // 
52 42
   unsigned*       dynArray;     // dynArray[dynCnt] dynamics reference array
@@ -54,8 +44,8 @@ typedef struct cmSp_str
54 44
   double          srate;        // 
55 45
   cmScMatcher*    match;        // score follower
56 46
 
57
-  cmScMatcherCb_t  matchCb;     // score follower callback
58
-  cmScoreProcCb_t  procCb;      // score processor callback
47
+  cmScoreProcCb_t  procCb;      // score processor callback - called whenever a new 'marker' section or note-on is about to be processed
48
+  cmScMatcherCb_t  matchCb;     // score follower callback  - called whenever the score follower detects a matched event
59 49
   void*            cbArg;       // callback arg. for both matchCb and procCb.
60 50
 
61 51
 } cmSp_t;
@@ -81,7 +71,13 @@ cmSpRC_t _cmJsonReadDynArray( cmJsonH_t jsH, unsigned** dynArray, unsigned* dynC
81 71
   return kOkSpRC;  
82 72
 }
83 73
 
84
-cmSpRC_t _cmScoreProcInit( cmCtx_t* ctx, cmSp_t* p, const cmChar_t* rsrcFn, cmScoreProcCb_t procCb, cmScMatcherCb_t matchCb, void* cbArg  )
74
+cmSpRC_t _cmScoreProcInit( 
75
+  cmCtx_t*        ctx, 
76
+  cmSp_t*         p, 
77
+  const cmChar_t* rsrcFn, 
78
+  cmScoreProcCb_t procCb, 
79
+  cmScMatcherCb_t matchCb, 
80
+  void*           cbArg  )
85 81
 {
86 82
   cmSpRC_t        rc     = kOkSpRC;
87 83
   const cmChar_t* scFn   = NULL;
@@ -143,7 +139,7 @@ cmSpRC_t _cmScoreProcInit( cmCtx_t* ctx, cmSp_t* p, const cmChar_t* rsrcFn, cmSc
143 139
     goto errLabel;
144 140
   }
145 141
 
146
-  p->ctx  = cmCtxAlloc(NULL, &ctx->rpt, cmLHeapNullHandle, cmSymTblNullHandle );
142
+  p->ctx     = cmCtxAlloc(NULL, &ctx->rpt, cmLHeapNullHandle, cmSymTblNullHandle );
147 143
   p->matchCb = matchCb;
148 144
   p->procCb  = procCb;
149 145
   p->cbArg   = cbArg;
@@ -153,6 +149,8 @@ cmSpRC_t _cmScoreProcInit( cmCtx_t* ctx, cmSp_t* p, const cmChar_t* rsrcFn, cmSc
153 149
 }
154 150
 
155 151
 
152
+// This function iterates through each sequence and advances
153
+// to each 'begin-marker' position.  
156 154
 cmSpRC_t _cmScoreProcProcess(cmCtx_t* ctx, cmSp_t* sp)
157 155
 {
158 156
   cmSpRC_t rc     = kOkSpRC;
@@ -199,21 +197,22 @@ cmSpRC_t _cmScoreProcProcess(cmCtx_t* ctx, cmSp_t* sp)
199 197
 
200 198
       cmRptPrintf(&ctx->rpt,"Processing loc:%i seq:%i %s %s\n",locPtr->index,seqId,cmStringNullGuard(markPtr->obj.name),cmStringNullGuard(markPtr->text));
201 199
 
202
-      // inform the score processor that we are about to start a new section
203
-      if( sp->procCb( sp->cbArg, sp, kBeginSectionSpId, markPtr ) != kOkSpRC )
200
+      // reset the score matcher to begin searching at the bar location
201
+      if( cmScMatcherReset(sp->match, locPtr->index ) != cmOkRC )
204 202
       {
205
-        cmErrMsg(&sp->err,kProcFailSpRC,"The score process object failed on reset.");
203
+        cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The score matcher reset failed on location: %i.",locPtr->index);
206 204
         continue;
207 205
       }
208 206
 
209
-      // reset the score matcher to begin searching at the bar location
210
-      if( cmScMatcherReset(sp->match, locPtr->index ) != cmOkRC )
207
+      // inform the score processor that we are about to start a new section
208
+      if( sp->procCb( sp->cbArg, sp, kBeginSectionSpId, o0p ) != kOkSpRC )
211 209
       {
212
-        cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The score matcher reset failed on location: %i.",locPtr->index);
210
+        cmErrMsg(&sp->err,kProcFailSpRC,"The score process object failed on reset.");
213 211
         continue;
214 212
       }
215 213
 
216
-      cmTlObj_t* o1p = o0p;
214
+      cmTlObj_t* o1p   = o0p;
215
+      bool       errFl = false;
217 216
 
218 217
       // as long as more MIDI events are available get the next MIDI msg 
219 218
       while( (rc == kOkSpRC) && (o1p = cmTimeLineNextTypeObj(sp->tlH, o1p, seqId, kMidiEvtTlId )) != NULL )
@@ -225,9 +224,11 @@ cmSpRC_t _cmScoreProcProcess(cmCtx_t* ctx, cmSp_t* sp)
225 224
         if( mep->obj.seqSmpIdx != cmInvalidIdx && mep->obj.seqSmpIdx > markEndSmpIdx )
226 225
           break;
227 226
         
228
-        // if the time line MIDI msg a note-on
227
+        // if the time line MIDI msg is a note-on
229 228
         if( mep->msg->status == kNoteOnMdId )
230 229
         {
230
+          sp->procCb( sp->cbArg, sp, kNoteOnSpId,  o1p );
231
+
231 232
           cmRC_t cmRC = cmScMatcherExec(sp->match, mep->obj.seqSmpIdx, mep->msg->status, mep->msg->u.chMsgPtr->d0, mep->msg->u.chMsgPtr->d1, NULL );
232 233
 
233 234
           switch( cmRC )
@@ -240,12 +241,15 @@ cmSpRC_t _cmScoreProcProcess(cmCtx_t* ctx, cmSp_t* sp)
240 241
 
241 242
             case cmInvalidArgRC: // p->eli was not set correctly
242 243
               rc = cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The score matcher failed due to an invalid argument.");
243
-              goto errLabel;
244
+              errFl = true;
244 245
               break;
245 246
 
246 247
             case cmSubSysFailRC: // scan resync failed
247 248
               rc = cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The score matcher failed on resync.");
248
-              cmScMatcherPrint(sp->match);
249
+
250
+              sp->procCb( sp->cbArg, sp, kFailSpId, o0p );
251
+
252
+              //cmScMatcherPrint(sp->match);
249 253
               //goto errLabel;
250 254
               break;
251 255
 
@@ -259,6 +263,11 @@ cmSpRC_t _cmScoreProcProcess(cmCtx_t* ctx, cmSp_t* sp)
259 263
       if( sp->procCb( sp->cbArg, sp, kEndSectionSpId, NULL ) != kOkSpRC )
260 264
         cmErrMsg(&sp->err,kProcFailSpRC,"The score process object failed on reset.");
261 265
 
266
+      // error flag is used to break out of the loop after the 'end-section' is called
267
+      // so that the user defined processes has a chance to clean-up 
268
+      if( errFl )
269
+        goto errLabel;
270
+
262 271
       rc = kOkSpRC;
263 272
     }
264 273
   }
@@ -477,7 +486,7 @@ void _cmSpMatchMeasCb( cmScMatcher* p, void* arg, cmScMatcherResult_t* rp )
477 486
 }
478 487
 
479 488
 // measurement proc callback
480
-cmSpRC_t  _cmSpProcMeasCb( void* arg, cmSp_t* sp, cmScoreProcSelId_t id, cmTlMarker_t* curMarkPtr )
489
+cmSpRC_t  _cmSpProcMeasCb( void* arg, cmSp_t* sp, cmScoreProcSelId_t id, cmTlObj_t* tlObjPtr )
481 490
 {
482 491
   cmSpRC_t         rc = kOkSpRC;
483 492
   _cmSpMeasProc_t* m = (_cmSpMeasProc_t*)arg;
@@ -490,11 +499,17 @@ cmSpRC_t  _cmSpProcMeasCb( void* arg, cmSp_t* sp, cmScoreProcSelId_t id, cmTlMar
490 499
       if( cmScMeasReset(m->meas) != cmOkRC )
491 500
         rc = cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The score performance evaluation object failed on reset.");
492 501
 
493
-      m->curMarkPtr = curMarkPtr;
502
+      m->curMarkPtr = cmTimeLineMarkerObjPtr(sp->tlH,tlObjPtr);
503
+      break;
504
+
505
+    case kNoteOnSpId:
494 506
       break;
495 507
 
496 508
     case kEndSectionSpId:
497 509
       break;
510
+
511
+    case kFailSpId:
512
+      break;
498 513
   }
499 514
 
500 515
   return rc;
@@ -559,54 +574,211 @@ cmSpRC_t _cmScoreProcGenAllMeasurementsMain(cmCtx_t* ctx)
559 574
 }
560 575
 
561 576
 //==================================================================================================
577
+typedef struct cmSpAssoc_str
578
+{
579
+  unsigned              scEvtIdx; // score event index
580
+  unsigned              tlUid;    // time-line MIDI note-on object id
581
+  struct cmSpAssoc_str* link;
582
+} cmSpAssoc_t;
583
+
584
+typedef struct cmSpNoteMap_str
585
+{
586
+  unsigned                tlUid; // time-line MIDI note-on object id
587
+  unsigned                mni;  // assocated 'mni' returned in a cmScMatcherResult_t record
588
+  struct cmSpNoteMap_str* link;
589
+} cmSpNoteMap_t;
590
+
562 591
 typedef struct
563 592
 {
564
-  cmSp_t* sp; 
565
-} cmSpPerfProc_t;
593
+  cmCtx_t*       ctx;
594
+  cmSp_t*        sp; 
595
+  unsigned       mni;
596
+  bool           failFl;
597
+  cmJsonH_t      jsH;
598
+  cmJsonNode_t*  sectObj;
599
+  cmJsonNode_t*  array;
600
+
601
+  cmSpAssoc_t*   bap;  
602
+  cmSpAssoc_t*   eap;
603
+  cmSpNoteMap_t* bmp;
604
+  cmSpNoteMap_t* emp;
605
+
606
+  
607
+} cmSpAssocProc_t;
566 608
 
567
-void _cmSpMatchPerfCb( cmScMatcher* p, void* arg, cmScMatcherResult_t* rp )
609
+void _cmSpMatchAssocCb( cmScMatcher* p, void* arg, cmScMatcherResult_t* rp )
568 610
 {
569
-  cmSpPerfProc_t* m = (cmSpPerfProc_t*)arg;
611
+  cmSpAssocProc_t* m   = (cmSpAssocProc_t*)arg;
612
+
613
+  
614
+  if( cmJsonCreateFilledObject(m->jsH, m->array,
615
+      "mni",      kIntTId, rp->mni,
616
+      "scEvtIdx", kIntTId, rp->scEvtIdx,
617
+      "flags",    kIntTId, rp->flags, 
618
+      NULL ) == NULL )
619
+  {
620
+    cmErrMsg(&m->ctx->err,kJsonFailSpRC,"JSON association record create failed.");
621
+  }
622
+  
623
+  //cmScoreEvt_t*    sep = rp->scEvtIdx == -1 ? NULL : cmScoreEvt( m->sp->scH, rp->scEvtIdx );
624
+  //printf("%3i loc:%4i pitch=%3i %3i  flags=0x%x\n",rp->mni,rp->locIdx,rp->pitch,sep==NULL ? -1 : sep->pitch,rp->flags );
570 625
   
571 626
 }
572 627
 
573
-cmSpRC_t  _cmSpProcPerfCb( void* arg, cmSp_t* sp, cmScoreProcSelId_t id, cmTlMarker_t* curMarkPtr )
628
+cmSpRC_t  _cmSpProcAssocCb( void* arg, cmSp_t* sp, cmScoreProcSelId_t id, cmTlObj_t* tlObjPtr )
574 629
 {
575
-  cmSpPerfProc_t* m = (cmSpPerfProc_t*)arg;
630
+  cmSpRC_t         rc = kOkSpRC;
631
+  cmSpAssocProc_t* m  = (cmSpAssocProc_t*)arg;
632
+
633
+  switch( id )
634
+  {
635
+    case kBeginSectionSpId:
636
+      {
637
+        cmTlMarker_t* markPtr = cmTimeLineMarkerObjPtr( sp->tlH, tlObjPtr );
638
+        assert( markPtr != NULL );
639
+        m->mni    = 0;
640
+        m->failFl = false;
641
+
642
+        // insert a section object
643
+        if((m->sectObj = cmJsonInsertPairObject(m->jsH, cmJsonRoot(m->jsH), "section" )) == NULL )
644
+        {
645
+          rc = cmErrMsg(&m->ctx->err,kJsonFailSpRC,"Section insert failed on seq:%i '%s' : '%s'.", tlObjPtr->seqId, cmStringNullGuard(tlObjPtr->text),cmStringNullGuard(markPtr->text));
646
+          goto errLabel; 
647
+        }
648
+
649
+        // set the section time-line UID
650
+        if( cmJsonInsertPairInt(m->jsH, m->sectObj,"markerUid", tlObjPtr->uid ) != kOkJsRC )
651
+        {
652
+          rc = cmErrMsg(&m->ctx->err,kJsonFailSpRC,"Marker uid field insert failed on seq:%i '%s' : '%s'.", tlObjPtr->seqId, cmStringNullGuard(tlObjPtr->text),cmStringNullGuard(markPtr->text));
653
+          goto errLabel;           
654
+        }
655
+
656
+        // create an array to hold the assoc results
657
+        if(( m->array = cmJsonInsertPairArray(m->jsH, m->sectObj, "array")) == NULL )
658
+        {
659
+          rc = cmErrMsg(&m->ctx->err,kJsonFailSpRC,"Marker array field insert failed on seq:%i '%s' : '%s'.", tlObjPtr->seqId, cmStringNullGuard(tlObjPtr->text),cmStringNullGuard(markPtr->text));
660
+          goto errLabel;           
661
+        }          
662
+      }
663
+      break;
664
+
665
+    case kEndSectionSpId:
666
+      {
667
+        while( m->bmp != NULL )
668
+        {
669
+          cmSpNoteMap_t* nmp = m->bmp->link;
670
+          cmMemFree(m->bmp);
671
+          m->bmp = nmp;
672
+        }
673
+      
674
+        m->bmp = NULL;
675
+        m->emp = NULL;
576 676
 
677
+        if( cmJsonInsertPairInt( m->jsH, m->sectObj, "failFl", m->failFl ) != kOkJsRC )
678
+        {
679
+          rc = cmErrMsg(&m->ctx->err,kJsonFailSpRC,"JSON fail flag insert failed.");
680
+          goto errLabel;
681
+        }
682
+        
683
+      }
684
+      break;
685
+
686
+    case kNoteOnSpId:
687
+      {
688
+        // create a cmSpNoteMap_t record ...
689
+        cmSpNoteMap_t* map = cmMemAllocZ(cmSpNoteMap_t,1);
690
+        map->tlUid = tlObjPtr->uid;
691
+        map->mni   = m->mni;
692
+
693
+        // .. and insert it in the note-map list
694
+        if( m->emp == NULL )
695
+        {
696
+          m->bmp = map;
697
+          m->emp = map;
698
+        }
699
+        else
700
+        {
701
+          m->emp->link = map;
702
+          m->emp       = map;
703
+        }
704
+
705
+        m->mni += 1;
706
+      }
707
+      break;
708
+
709
+    case kFailSpId:
710
+      m->failFl = true;
711
+      break;
712
+
713
+  }
714
+
715
+ errLabel:
716
+  return rc;
577 717
 }
578 718
 
579
-cmSpRC_t _cmScoreProcGenPerfMain(cmCtx_t* ctx)
719
+cmSpRC_t _cmScoreProcGenAssocMain(cmCtx_t* ctx)
580 720
 {
581
-  const cmChar_t* rsrcFn = "/home/kevin/.kc/time_line.js";
582
-  const cmChar_t* outFn  = "/home/kevin/src/cmkc/src/kc/data/meas0.js";
583
-
584
-  cmSpRC_t        rc     = kOkSpRC;
585
-  cmSpPerfProc_t* m      = cmMemAllocZ(cmSpPerfProc_t,1);
586
-  cmSp_t          s;
587
-  cmSp_t*         sp     = &s;
721
+  const cmChar_t*  rsrcFn = "/home/kevin/.kc/time_line.js";
722
+  const cmChar_t*  outFn  = "/home/kevin/src/cmkc/src/kc/data/assoc0.js";
723
+  cmSpRC_t         rc     = kOkSpRC;
724
+  cmSpAssocProc_t* m      = cmMemAllocZ(cmSpAssocProc_t,1);
725
+  cmSp_t           s;
726
+  cmSp_t*          sp     = &s;
588 727
 
589 728
   memset(sp,0,sizeof(s));
590 729
 
591
-  cmRptPrintf(&ctx->rpt,"Score Performance Start\n");
730
+  m->ctx = ctx;
731
+
732
+  cmRptPrintf(&ctx->rpt,"Score Association Start\n");
733
+
734
+  // create a JSON object to hold the results
735
+  if( cmJsonInitialize(&m->jsH, ctx ) != kOkJsRC )
736
+  {
737
+    cmErrMsg(&m->ctx->err,kJsonFailSpRC,"Score association JSON output object create failed.");
738
+    goto errLabel;
739
+  }
740
+
741
+  // create the JSON root object
742
+  if( cmJsonCreateObject(m->jsH, NULL ) == NULL )
743
+  {
744
+    cmErrMsg(&m->ctx->err,kJsonFailSpRC,"Create JSON root object.");
745
+    goto errLabel;
746
+  }
592 747
 
593 748
   // initialize the score processor
594
-  if((rc = _cmScoreProcInit(ctx,sp,rsrcFn,_cmSpProcPerfCb,_cmSpMatchPerfCb,m)) != kOkSpRC )
749
+  if((rc = _cmScoreProcInit(ctx,sp,rsrcFn,_cmSpProcAssocCb,_cmSpMatchAssocCb, m)) != kOkSpRC )
595 750
     goto errLabel;
596 751
 
597 752
   m->sp = sp;
598 753
 
754
+  // store the time-line and score file name
755
+  if( cmJsonInsertPairs(m->jsH, cmJsonRoot(m->jsH), 
756
+      "tlFn",    kStringTId, cmTimeLineFileName( sp->tlH),
757
+      "scoreFn", kStringTId, cmScoreFileName( sp->scH ),
758
+      NULL ) != kOkJsRC )
759
+  {
760
+    cmErrMsg(&m->ctx->err,kJsonFailSpRC,"File name JSON field insertion failed.");
761
+    goto errLabel;
762
+  }
763
+
599 764
   // run the score processor
600 765
   _cmScoreProcProcess(ctx,sp);
601 766
 
602
-  // write the results of the performance evaluation
603
-  if((rc = _cmScWriteMeasFile(ctx, sp, m, outFn )) != kOkSpRC )
604
-    cmErrMsg(&sp->err,kFileFailSpRC,"The measurement output did not complete without errors."); 
767
+  cmRptPrintf(&ctx->rpt,"Writing results to '%s'.",outFn);
605 768
 
606
-  //cmScorePrint(sp.scH,&ctx->rpt);
607
-  //cmScorePrintLoc(sp.scH);
769
+  // write the results to a JSON file
770
+  if(cmJsonWrite(m->jsH, NULL, outFn ) != kOkJsRC )
771
+  {
772
+    cmErrMsg(&m->ctx->err,kJsonFailSpRC,"Score association output file write failed.");
773
+    goto errLabel;
774
+  }
608 775
  
609 776
  errLabel:
777
+  if( cmJsonFinalize(&m->jsH) != kOkJsRC )
778
+  {
779
+    cmErrMsg(&m->ctx->err,kJsonFailSpRC,"JSON finalize failed.");
780
+  }
781
+
610 782
   _cmScoreProcFinal(sp);
611 783
 
612 784
   cmMemFree(m);
@@ -625,7 +797,8 @@ cmSpRC_t cmScoreProc(cmCtx_t* ctx)
625 797
 {
626 798
   cmSpRC_t rc = kOkSpRC;
627 799
 
628
-  _cmScoreProcGenAllMeasurementsMain(ctx);
800
+  //_cmScoreProcGenAllMeasurementsMain(ctx);
801
+  _cmScoreProcGenAssocMain(ctx);
629 802
 
630 803
   return rc;
631 804
   

Chargement…
Annuler
Enregistrer