Browse Source

cmScore.h/c : Added the concept of 'markers' to support locating live recd/play fragments.

master
kpl 10 years ago
parent
commit
70dffe559b
2 changed files with 373 additions and 52 deletions
  1. 342
    45
      app/cmScore.c
  2. 31
    7
      app/cmScore.h

+ 342
- 45
app/cmScore.c View File

@@ -6,6 +6,7 @@
6 6
 #include "cmCtx.h"
7 7
 #include "cmMem.h"
8 8
 #include "cmMallocDebug.h"
9
+#include "cmLinkedHeap.h"
9 10
 #include "cmMidi.h"
10 11
 #include "cmLex.h"
11 12
 #include "cmCsv.h"
@@ -13,6 +14,7 @@
13 14
 #include "cmMidiFile.h"
14 15
 #include "cmAudioFile.h"
15 16
 #include "cmTimeLine.h"
17
+#include "cmText.h"
16 18
 #include "cmScore.h"
17 19
 #include "cmVectOpsTemplateMain.h"
18 20
 
@@ -41,7 +43,8 @@ enum
41 43
   kFracColScIdx      = 18,
42 44
   kDynColScIdx       = 19,
43 45
   kSectionColScIdx   = 20,
44
-  kRemarkColScIdx    = 21
46
+  kRecdPlayColScIdx  = 21,
47
+  kRemarkColScIdx    = 22
45 48
 };
46 49
 
47 50
 
@@ -75,6 +78,15 @@ typedef struct cmScSet_str
75 78
   struct cmScSet_str* link;   // 
76 79
 } cmScSet_t;
77 80
 
81
+typedef struct cmScMark_str
82
+{
83
+  cmMarkScMId_t      cmdId;
84
+  unsigned           labelSymId;
85
+  unsigned           scoreIdx;
86
+  unsigned           csvRowIdx;
87
+  struct cmScMark_str* link;
88
+} cmScMark_t;
89
+
78 90
 typedef struct
79 91
 {
80 92
   cmErr_t           err;
@@ -94,11 +106,15 @@ typedef struct
94 106
   cmScoreSection_t* sect;
95 107
   unsigned          sectCnt;
96 108
 
109
+  unsigned*         markLabelArray;    // one symId per unique cmScoreMarker_t.labelSymId;
110
+  unsigned          markLabelCnt; 
111
+
97 112
   unsigned          sciPitchLexTId; // sci pitch and section id lexer token id's
98 113
   unsigned          sectionLexTId;
99 114
 
100 115
   cmScSect_t*       sectList;       // lists used during parsing
101 116
   cmScSet_t*        setList;    
117
+  cmScMark_t*       markList;
102 118
 
103 119
   cmScoreSet_t*     sets;
104 120
   unsigned          setCnt;
@@ -313,6 +329,17 @@ unsigned _cmScLexSectionIdMatcher( const cmChar_t* cp, unsigned cn )
313 329
   return 0;
314 330
 }
315 331
 
332
+void _cmScFreeMarkList( cmScMark_t* markList )
333
+{
334
+  cmScMark_t* mp = markList;
335
+  while( mp!=NULL )
336
+  {
337
+    cmScMark_t* np = mp->link;
338
+    cmMemFree(mp);
339
+    mp = np;
340
+  }
341
+}
342
+
316 343
 void _cmScFreeSetList( cmScSet_t* setList )
317 344
 {
318 345
   cmScSet_t* tp = setList;
@@ -366,6 +393,8 @@ cmScRC_t _cmScFinalize( cmSc_t* p )
366 393
 
367 394
   _cmScFreeSetList(p->setList);
368 395
 
396
+  _cmScFreeMarkList(p->markList);
397
+
369 398
   if( p->loc != NULL )
370 399
   {
371 400
     for(i=0; i<p->locCnt; ++i)
@@ -373,12 +402,23 @@ cmScRC_t _cmScFinalize( cmSc_t* p )
373 402
       cmMemFree(p->loc[i].evtArray);
374 403
       if( p->loc[i].begSectPtr != NULL )
375 404
         cmMemFree(p->loc[i].begSectPtr->setArray);
405
+
406
+      // free the marker list assoc'd with this location
407
+      cmScoreMarker_t* smp = p->loc[i].markList;
408
+      while( smp!=NULL )
409
+      {
410
+        cmScoreMarker_t* np = smp->link;
411
+        cmMemFree(smp);
412
+        smp = np;
413
+      }
414
+
376 415
     }
377 416
     cmMemFree(p->loc);
378 417
   }
379 418
 
419
+  
380 420
   cmMemPtrFree(&p->dynRefArray);
381
-
421
+  cmMemFree(p->markLabelArray);
382 422
   cmMemFree(p->sect);
383 423
   cmMemFree(p->fn);
384 424
   cmMemFree(p->array);
@@ -557,6 +597,79 @@ cmScRC_t _cmScParseAttr(cmSc_t* p, unsigned scoreIdx, const cmChar_t* text, unsi
557 597
   return kOkScRC;
558 598
 }
559 599
 
600
+// Parse a record/playback string
601
+cmScRC_t _cmScParseMarkers( cmSc_t* p, unsigned scoreIdx, const cmChar_t* text, unsigned rowIdx )
602
+{
603
+  const cmChar_t* cp = text;
604
+  const cmChar_t* ip;
605
+  const cmChar_t* ep;
606
+
607
+  // if no symbol table has been registered then don't bother storing markers.
608
+  // (NOTE - THIS IS A HACK BECAUSE THE SCORE OBJECT USED IN THE cmdIf DOES NOT HAVE
609
+  // A SYMBOL TABLE - WE COULD EASILY ADD ONE IF IT EVENTUALLY NEEDS ACCESS TO THE MARKERS
610
+  // - OR A SYMBOL TABLE COULD BE ADDED TO THE SCORE ITSELF.)
611
+  if( cmSymTblIsValid(p->stH) == false )
612
+    return kOkScRC;
613
+
614
+  // go to command/id space
615
+  if((ip = cmTextNextWhiteOrEosC(text)) == NULL )
616
+    goto errLabel;
617
+
618
+  // goto label 
619
+  if((ip = cmTextNextNonWhiteC(ip)) == NULL )
620
+    goto errLabel;
621
+
622
+  // goto end of label
623
+  if((ep = cmTextNextWhiteOrEosC(ip)) == NULL )
624
+    goto errLabel;
625
+  else
626
+  {
627
+    unsigned n =  (ep-ip)+1;
628
+    cmChar_t markTextStr[n+1];
629
+    strncpy(markTextStr,ip,n);
630
+
631
+    // for each command code
632
+    // (there may be more than one character)
633
+    for(; *cp && !isspace(*cp); ++cp)
634
+    {
635
+      cmMarkScMId_t cmdId = kInvalidScMId;
636
+
637
+      switch( *cp )
638
+      {
639
+        case 'c': cmdId = kRecdBegScMId; break;
640
+        case 'e': cmdId = kRecdEndScMId; break;
641
+        case 'p': cmdId = kPlayBegScMId; break;
642
+        case 'd': cmdId = kPlayEndScMId; break;
643
+        case 'f': cmdId = kFadeScMId;    break;
644
+        default:
645
+          return cmErrMsg(&p->err,kSyntaxErrScRC,"Unrecognized marker command character '%c' at row index %i.",*cp,rowIdx);
646
+      }
647
+
648
+      cmScMark_t* mp       = cmMemAllocZ(cmScMark_t,1);
649
+      mp->cmdId      = cmdId;
650
+      mp->labelSymId = cmSymTblRegisterSymbol(p->stH,markTextStr);
651
+      mp->scoreIdx   = scoreIdx;
652
+      mp->csvRowIdx  = rowIdx;
653
+
654
+      // insert the new mark at the end of the list
655
+      if( p->markList == NULL )
656
+        p->markList = mp;
657
+      else
658
+      {
659
+        cmScMark_t* ep = p->markList;
660
+        while( ep->link != NULL )
661
+          ep = ep->link;
662
+
663
+        ep->link = mp;
664
+      }    
665
+    }
666
+  }
667
+  return kOkScRC;
668
+
669
+ errLabel:
670
+  return cmErrMsg(&p->err,kSyntaxErrScRC,"Invalid record/playback field ('%s') on row index:%i.",cmStringNullGuard(text),rowIdx);
671
+}
672
+
560 673
 void _cmScPrintSets( const cmChar_t* label, cmScSet_t* setList )
561 674
 {
562 675
   printf("%s\n",label);
@@ -598,7 +711,7 @@ cmScRC_t _cmScParseNoteOn( cmSc_t* p, unsigned rowIdx, cmScoreEvt_t* s, unsigned
598 711
     return cmErrMsg(&p->err,kSyntaxErrScRC,"Expected a scientific pitch value");
599 712
           
600 713
   if((midiPitch = cmSciPitchToMidi(sciPitch)) == kInvalidMidiPitch)
601
-   return cmErrMsg(&p->err,kSyntaxErrScRC,"Unable to convert the scientific pitch '%s' to a MIDI value. ");
714
+    return cmErrMsg(&p->err,kSyntaxErrScRC,"Unable to convert the scientific pitch '%s' to a MIDI value. ");
602 715
 
603 716
   // it is possible that note delta-secs field is empty - so default to 0
604 717
   if((secs =  cmCsvCellDouble(p->cH, rowIdx, kSecsColScIdx )) == DBL_MAX) // Returns DBL_MAX on error.
@@ -658,6 +771,14 @@ cmScRC_t _cmScParseNoteOn( cmSc_t* p, unsigned rowIdx, cmScoreEvt_t* s, unsigned
658 771
     durSecs = 0.25;
659 772
 
660 773
 
774
+  // parse the recd/play markers
775
+  if((attr = cmCsvCellText(p->cH,rowIdx,kRecdPlayColScIdx)) != NULL )
776
+  {
777
+    if((rc = _cmScParseMarkers(p,scoreIdx,attr,rowIdx)) != kOkScRC )
778
+      return rc;
779
+  } 
780
+
781
+
661 782
   s->type       = kNonEvtScId;
662 783
   s->secs       = secs;
663 784
   s->pitch      = midiPitch;
@@ -870,6 +991,8 @@ cmScRC_t _cmScProcSets( cmSc_t* p )
870 991
 }
871 992
 
872 993
 
994
+
995
+
873 996
 cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
874 997
 {
875 998
   cmScRC_t rc = kOkScRC;
@@ -935,6 +1058,153 @@ cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
935 1058
   return rc;
936 1059
 }
937 1060
 
1061
+const cmScoreLoc_t*  _cmScFindMarkLoc( cmSc_t* p, cmMarkScMId_t cmdId, unsigned labelSymId, const cmScoreMarker_t** markRef )
1062
+{
1063
+  unsigned i;
1064
+  for(i=0; i<p->locCnt; ++i)
1065
+  {
1066
+    cmScoreMarker_t* smp = p->loc[i].markList;
1067
+    for(; smp!=NULL; smp=smp->link)
1068
+    {
1069
+      if( smp->markTypeId==cmdId && smp->labelSymId==labelSymId )
1070
+        return p->loc + i;
1071
+
1072
+      if( markRef != NULL )
1073
+        *markRef = smp;
1074
+    }
1075
+  }
1076
+  return NULL;
1077
+}
1078
+
1079
+unsigned _cmScMarkerLabelIndex( cmSc_t* p, unsigned labelSymId )
1080
+{
1081
+  unsigned i;
1082
+  for(i=0; i<p->markLabelCnt; ++i)
1083
+    if( p->markLabelArray[i] == labelSymId )
1084
+      return i;
1085
+
1086
+  return cmInvalidIdx;
1087
+}
1088
+
1089
+
1090
+// Verify that the record/play begin/end and fade markers fall in the correct time order.
1091
+// (e.g. 'begin' must be before 'end' and 'fade' must be between and 'begin' and 'end').
1092
+cmScRC_t _cmScValidateMarkers( cmSc_t* p )
1093
+{
1094
+  cmScRC_t rc = kOkScRC;
1095
+  unsigned i;
1096
+
1097
+  for(i=0; i<p->locCnt; ++i)
1098
+  {
1099
+    cmScoreMarker_t* sm0p = p->loc[i].markList;
1100
+    for(; sm0p!=NULL; sm0p=sm0p->link)
1101
+    {
1102
+      const cmScoreLoc_t* sl0p;
1103
+      const cmScoreLoc_t* sl1p;
1104
+
1105
+      switch( sm0p->markTypeId )
1106
+      {
1107
+        case kRecdBegScMId:
1108
+          if((sl0p = _cmScFindMarkLoc(p,kRecdEndScMId, sm0p->labelSymId, NULL )) == NULL )
1109
+            rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record begin' marker at CSV row index %i does not have an associated 'record end' marker.",sm0p->csvRowIdx);
1110
+          else
1111
+            if( sl0p->index <= p->loc[i].index )
1112
+              rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record end' marker comes before associated with the 'record begin' marker at CSV row index %i.",sm0p->csvRowIdx);
1113
+          break;
1114
+          
1115
+        case kRecdEndScMId:
1116
+          if((sl0p = _cmScFindMarkLoc(p,kRecdBegScMId, sm0p->labelSymId, NULL )) == NULL )
1117
+            rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record end' marker at CSV row index %i does not have an associated 'record begin' marker.",sm0p->csvRowIdx);
1118
+          else
1119
+            if( sl0p->index > p->loc[i].index )
1120
+              rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record begin' marker comes after the associated with the 'record end' marker at CSV row index %i.",sm0p->csvRowIdx);
1121
+          break;
1122
+          
1123
+        case kFadeScMId:
1124
+          if((sl0p = _cmScFindMarkLoc(p,kRecdBegScMId, sm0p->labelSymId, NULL )) == NULL )
1125
+            rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i does not have an associated 'record begin' marker.",sm0p->csvRowIdx);
1126
+          else
1127
+            if((sl1p = _cmScFindMarkLoc(p,kRecdEndScMId, sm0p->labelSymId, NULL )) == NULL )
1128
+              rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i does not have an associated 'record end' marker.",sm0p->csvRowIdx);
1129
+            else
1130
+              if( sl0p->index > p->loc[i].index || sl1p->index < p->loc[i].index )
1131
+                rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i is not between it's associated 'record begin' and 'record end' markers.",sm0p->csvRowIdx);
1132
+          break;
1133
+          
1134
+        case kPlayBegScMId:
1135
+          if((sl0p = _cmScFindMarkLoc(p,kPlayEndScMId, sm0p->labelSymId, NULL )) == NULL )
1136
+            rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play begin' marker at CSV row index %i does not have an associated 'play end' marker.",sm0p->csvRowIdx);
1137
+          else
1138
+            if( sl0p->index <= p->loc[i].index )
1139
+              rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play end' marker comes before associated with the 'play begin' marker at CSV row index %i.",sm0p->csvRowIdx);
1140
+          break;
1141
+
1142
+        case kPlayEndScMId:
1143
+          if((sl0p = _cmScFindMarkLoc(p,kPlayBegScMId, sm0p->labelSymId, NULL )) == NULL )
1144
+            rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play end' marker at CSV row index %i does not have an associated 'play begin' marker.",sm0p->csvRowIdx);
1145
+          else
1146
+            if( sl0p->index > p->loc[i].index )
1147
+              rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play begin' marker comes after the associated with the 'play end' marker at CSV row index %i.",sm0p->csvRowIdx);
1148
+          break;
1149
+
1150
+        default:
1151
+          break;
1152
+
1153
+      }
1154
+    }
1155
+  }
1156
+
1157
+  return rc;
1158
+}
1159
+
1160
+
1161
+
1162
+cmScRC_t _cmScProcMarkers( cmSc_t* p )
1163
+{
1164
+  // for each marker in the p->markList 
1165
+  // (p->markList is created by _cmScParseMarkers() during CSV file parsing.)
1166
+  cmScMark_t* mp = p->markList;
1167
+  for(; mp!=NULL; mp=mp->link)
1168
+  {
1169
+    assert( mp->scoreIdx < p->cnt );
1170
+
1171
+    // get the score location assoc'd with this marker
1172
+    unsigned locIdx = p->array[ mp->scoreIdx ].locIdx;
1173
+    assert( locIdx < p->locCnt );
1174
+
1175
+    cmScoreLoc_t*    slp = p->loc + locIdx;
1176
+
1177
+    // create a cmScoreMarker record.
1178
+    cmScoreMarker_t* smp = cmMemAllocZ(cmScoreMarker_t,1);
1179
+    smp->markTypeId  = mp->cmdId;
1180
+    smp->labelSymId  = mp->labelSymId;
1181
+    smp->csvRowIdx   = mp->csvRowIdx;
1182
+    smp->scoreLocPtr = slp; 
1183
+
1184
+    // attach the new scoreMarker record to the assoc'd score loc. recd
1185
+    if( slp->markList == NULL )
1186
+      slp->markList = smp;
1187
+    else
1188
+    {
1189
+      cmScoreMarker_t* sm0p = slp->markList;
1190
+      while( sm0p->link != NULL )
1191
+        sm0p = sm0p->link;
1192
+      sm0p->link = smp;
1193
+    }
1194
+
1195
+    // if the id represented by this marker
1196
+    if( _cmScMarkerLabelIndex(p,smp->labelSymId) == cmInvalidIdx )
1197
+    {
1198
+      p->markLabelArray = cmMemResizeP(unsigned,p->markLabelArray,p->markLabelCnt+1);
1199
+      p->markLabelArray[p->markLabelCnt] = smp->labelSymId;
1200
+      p->markLabelCnt += 1;
1201
+    }
1202
+  }
1203
+
1204
+  // validate the markers 
1205
+  return _cmScValidateMarkers(p);
1206
+}
1207
+
938 1208
 cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
939 1209
 {
940 1210
   cmScRC_t    rc         = kOkScRC;
@@ -1164,6 +1434,9 @@ cmScRC_t cmScoreInitialize( cmCtx_t* ctx, cmScH_t* hp, const cmChar_t* fn, doubl
1164 1434
   if((rc = _cmScProcSections(p,p->sectList)) != kOkScRC )
1165 1435
     goto errLabel;
1166 1436
 
1437
+  if((rc = _cmScProcMarkers(p)) != kOkScRC )
1438
+    goto errLabel;
1439
+  
1167 1440
   // load the dynamic reference array
1168 1441
   if( dynRefArray != NULL && dynRefCnt > 0)
1169 1442
   {
@@ -1409,6 +1682,30 @@ unsigned cmScoreSetCount( cmScH_t h )
1409 1682
   return p->setCnt;
1410 1683
 }
1411 1684
 
1685
+unsigned      cmScoreMarkerLabelCount( cmScH_t h )
1686
+{
1687
+  cmSc_t* p = _cmScHandleToPtr(h);
1688
+  return p->markLabelCnt;
1689
+}
1690
+
1691
+unsigned      cmScoreMarkerLabelSymbolId( cmScH_t h, unsigned idx )
1692
+{
1693
+  cmSc_t* p = _cmScHandleToPtr(h);
1694
+  assert( idx < p->markLabelCnt );
1695
+  return p->markLabelArray[idx];
1696
+}
1697
+
1698
+const cmScoreMarker_t* cmScoreMarker( cmScH_t h, cmMarkScMId_t markMId, unsigned labelSymId )
1699
+{
1700
+  cmSc_t* p = _cmScHandleToPtr(h);
1701
+  const cmScoreMarker_t* smp = NULL;
1702
+  if( _cmScFindMarkLoc(p, markMId, labelSymId, &smp ) == NULL )
1703
+    return NULL;
1704
+
1705
+  return smp;
1706
+}
1707
+
1708
+
1412 1709
 cmScRC_t      cmScoreSeqNotify( cmScH_t h )
1413 1710
 {
1414 1711
   cmScRC_t  rc = kOkScRC;
@@ -1502,7 +1799,7 @@ void _cmScPerfSortTimes( unsigned *v, unsigned n )
1502 1799
         fl = true;
1503 1800
       }
1504 1801
     }
1505
-   --n;
1802
+    --n;
1506 1803
   }
1507 1804
 }
1508 1805
 
@@ -1568,13 +1865,13 @@ bool _cmScPerfEven(cmSc_t* p, cmScoreSet_t* stp, bool printMissFl)
1568 1865
   if(printFl)
1569 1866
   {
1570 1867
     /*
1571
-    for(i=0; i<stp->eleCnt; ++i)
1572
-    {
1868
+      for(i=0; i<stp->eleCnt; ++i)
1869
+      {
1573 1870
       printf("%i %i ",i,v[i]);
1574 1871
       if( i > 0 )
1575
-        printf("%i ", d[i-1]);
1872
+      printf("%i ", d[i-1]);
1576 1873
       printf("\n");
1577
-    }
1874
+      }
1578 1875
     */
1579 1876
     printf("%s EVENESS:%f\n",sortFl?"SORTED ":"",stp->value);
1580 1877
   }
@@ -2110,42 +2407,42 @@ cmScRC_t      cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const c
2110 2407
       goto errLabel;
2111 2408
     }
2112 2409
 
2113
-      switch( tmp->status )
2114
-      {
2115
-        case kNoteOnMdId:
2116
-          if( cmCsvInsertTextColAfter(csvH, cp, &cp, cmMidiToSciPitch(tmp->u.chMsgPtr->d0,NULL,0), lexTId ) != kOkCsvRC )
2117
-          {
2118
-            cmErrMsg(&err,kCsvFailScRC,"Error inserting 'opcode' column in '%s'.",cmStringNullGuard(scoreFn));
2119
-            goto errLabel;
2120
-          }
2121
-
2122
-        case kMetaStId:
2123
-          switch( tmp->metaId )
2124
-          {
2125
-            case kTimeSigMdId:
2126
-              if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->num, lexTId ) != kOkCsvRC )
2127
-              {
2128
-                cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. numerator column in '%s'.",cmStringNullGuard(scoreFn));
2129
-                goto errLabel;
2130
-              }
2131
-
2132
-              if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->den, lexTId ) != kOkCsvRC )
2133
-              {
2134
-                cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. denominator column in '%s'.",cmStringNullGuard(scoreFn));
2135
-                goto errLabel;
2136
-              }
2137
-              break;
2410
+    switch( tmp->status )
2411
+    {
2412
+      case kNoteOnMdId:
2413
+        if( cmCsvInsertTextColAfter(csvH, cp, &cp, cmMidiToSciPitch(tmp->u.chMsgPtr->d0,NULL,0), lexTId ) != kOkCsvRC )
2414
+        {
2415
+          cmErrMsg(&err,kCsvFailScRC,"Error inserting 'opcode' column in '%s'.",cmStringNullGuard(scoreFn));
2416
+          goto errLabel;
2417
+        }
2138 2418
 
2139
-            case kTempoMdId:
2140
-              if( cmCsvInsertUIntColAfter(csvH, cp, &cp, 60000000/tmp->u.iVal, lexTId ) != kOkCsvRC )
2141
-              {
2142
-                cmErrMsg(&err,kCsvFailScRC,"Error inserting 'tempo' in '%s'.",cmStringNullGuard(scoreFn));
2143
-                goto errLabel;
2144
-              }
2145
-              break;
2146
-          }
2419
+      case kMetaStId:
2420
+        switch( tmp->metaId )
2421
+        {
2422
+          case kTimeSigMdId:
2423
+            if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->num, lexTId ) != kOkCsvRC )
2424
+            {
2425
+              cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. numerator column in '%s'.",cmStringNullGuard(scoreFn));
2426
+              goto errLabel;
2427
+            }
2428
+
2429
+            if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->den, lexTId ) != kOkCsvRC )
2430
+            {
2431
+              cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. denominator column in '%s'.",cmStringNullGuard(scoreFn));
2432
+              goto errLabel;
2433
+            }
2434
+            break;
2435
+
2436
+          case kTempoMdId:
2437
+            if( cmCsvInsertUIntColAfter(csvH, cp, &cp, 60000000/tmp->u.iVal, lexTId ) != kOkCsvRC )
2438
+            {
2439
+              cmErrMsg(&err,kCsvFailScRC,"Error inserting 'tempo' in '%s'.",cmStringNullGuard(scoreFn));
2440
+              goto errLabel;
2441
+            }
2442
+            break;
2443
+        }
2147 2444
 
2148
-      }
2445
+    }
2149 2446
 
2150 2447
 
2151 2448
   }
@@ -2157,10 +2454,10 @@ cmScRC_t      cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const c
2157 2454
   }
2158 2455
 
2159 2456
  errLabel:
2160
-   cmMidiFileClose(&mfH);
2161
-   cmCsvFinalize(&csvH);
2457
+  cmMidiFileClose(&mfH);
2458
+  cmCsvFinalize(&csvH);
2162 2459
 
2163
-   return rc;
2460
+  return rc;
2164 2461
 }
2165 2462
 
2166 2463
 void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )

+ 31
- 7
app/cmScore.h View File

@@ -36,12 +36,12 @@ extern "C" {
36 36
   // Flags used by cmScoreEvt_t.flags
37 37
   enum
38 38
   {
39
-    kEvenScFl    = 0x01,        // This note is marked for evenness measurement
40
-    kDynScFl     = 0x02,        // This note is marked for dynamics measurement
41
-    kTempoScFl   = 0x04,        // This note is marked for tempo measurement
42
-    kSkipScFl    = 0x08,        // This isn't a real event (e.g. tied note) skip over it
43
-    kGraceScFl   = 0x10,        // This is a grace note
44
-    kInvalidScFl = 0x20         // This note has a calculated time
39
+    kEvenScFl    = 0x001,        // This note is marked for evenness measurement
40
+    kDynScFl     = 0x002,        // This note is marked for dynamics measurement
41
+    kTempoScFl   = 0x004,        // This note is marked for tempo measurement
42
+    kSkipScFl    = 0x008,        // This isn't a real event (e.g. tied note) skip over it
43
+    kGraceScFl   = 0x010,        // This is a grace note
44
+    kInvalidScFl = 0x020         // This note has a calculated time
45 45
   };
46 46
 
47 47
 
@@ -103,7 +103,26 @@ extern "C" {
103 103
     double                 value;
104 104
     struct cmScoreSet_str* llink;      // cmScoreLoc_t setList link
105 105
   } cmScoreSet_t;
106
-  
106
+
107
+  typedef enum
108
+  {
109
+    kInvalidScMId,
110
+    kRecdBegScMId,
111
+    kRecdEndScMId,
112
+    kFadeScMId,
113
+    kPlayBegScMId,
114
+    kPlayEndScMId  
115
+  } cmMarkScMId_t;
116
+
117
+  // score markers
118
+  typedef struct cmScoreMarker_str
119
+  {
120
+    cmMarkScMId_t             markTypeId;  // marker type
121
+    unsigned                  labelSymId;  // marker label
122
+    struct cmScoreLoc_str*    scoreLocPtr; // score location of the marker
123
+    unsigned                  csvRowIdx;   // score CSV file line assoc'd w/ this marker
124
+    struct cmScoreMarker_str* link;        // cmScoreLoc_t.markList links
125
+  } cmScoreMarker_t;
107 126
 
108 127
   // All events which are simultaneous are collected into a single
109 128
   // cmScoreLoc_t record.
@@ -116,6 +135,7 @@ extern "C" {
116 135
     unsigned          barNumb;       // Bar number this event is contained by.                            
117 136
     cmScoreSet_t*     setList;       // Set's which end on this time location (linked through cmScoreSet_t.llink)
118 137
     cmScoreSection_t* begSectPtr;    // NULL if this location does not start a section
138
+    cmScoreMarker_t*  markList;      // List of markers assigned to this location
119 139
   } cmScoreLoc_t;
120 140
 
121 141
   typedef void (*cmScCb_t)( void* arg, const void* data, unsigned byteCnt );
@@ -170,6 +190,10 @@ extern "C" {
170 190
   // Return the count of sets.
171 191
   unsigned      cmScoreSetCount( cmScH_t h );
172 192
 
193
+  unsigned      cmScoreMarkerLabelCount( cmScH_t h );
194
+  unsigned      cmScoreMarkerLabelSymbolId( cmScH_t h, unsigned idx );
195
+  const cmScoreMarker_t* cmScoreMarker( cmScH_t h, cmMarkScMId_t markMId, unsigned labelSymId );
196
+
173 197
   // Make callbacks for all events in the score. The callbacks
174 198
   // contain cmScMsg_t records serialized as a byte stream.
175 199
   // Use cmScoreDecode() to convert the byte string to a

Loading…
Cancel
Save