Sfoglia il codice sorgente

Merge branch 'master' of klarke.webfactional.com:webapps/git/repos/libcm with

spat lab mac.
master
kevin 11 anni fa
parent
commit
c946234fde
17 ha cambiato i file con 3772 aggiunte e 1891 eliminazioni
  1. 533
    25
      app/cmScore.c
  2. 36
    9
      app/cmScore.h
  3. 53
    5
      cmCsv.c
  4. 4
    0
      cmCsv.h
  5. 2053
    1491
      cmData.c
  6. 311
    263
      cmData.h
  7. 4
    0
      cmGrPage.h
  8. 84
    89
      cmLex.c
  9. 12
    3
      cmLex.h
  10. 1
    1
      cmMidiFile.h
  11. 353
    0
      cmProc4.c
  12. 49
    0
      cmProc4.h
  13. 3
    0
      cmStack.h
  14. 1
    0
      dsp/cmDspBuiltIn.c
  15. 260
    1
      dsp/cmDspKr.c
  16. 1
    0
      dsp/cmDspKr.h
  17. 14
    4
      dsp/cmDspPgmKr.c

+ 533
- 25
app/cmScore.c Vedi 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;
@@ -1036,27 +1306,30 @@ cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
1036 1306
         break;
1037 1307
     }
1038 1308
     
1039
-    if( secs != DBL_MAX )
1040
-      cur_secs = secs;
1309
+    if( rc == kOkScRC )
1310
+    {
1311
+      if( secs != DBL_MAX )
1312
+        cur_secs = secs;
1041 1313
 
1042
-    // form the section list
1043
-    if( j > 0 )
1044
-      if((rc = _cmScParseSectionColumn(p,i,j-1,p->sectList)) != kOkScRC )
1045
-        break;
1314
+      // form the section list
1315
+      if( j > 0 )
1316
+        if((rc = _cmScParseSectionColumn(p,i,j-1,p->sectList)) != kOkScRC )
1317
+          break;
1046 1318
 
1047
-    // the bar lines don't have times so set the time of the bar line to the
1048
-    // time of the first event in the bar.
1049
-    if( barEvtIdx != cmInvalidIdx && secs != DBL_MAX )
1050
-    {
1051
-      assert( p->array[ barEvtIdx ].type == kBarEvtScId );
1052
-      p->array[ barEvtIdx ].secs = secs;
1319
+      // the bar lines don't have times so set the time of the bar line to the
1320
+      // time of the first event in the bar.
1321
+      if( barEvtIdx != cmInvalidIdx && secs != DBL_MAX )
1322
+      {
1323
+        assert( p->array[ barEvtIdx ].type == kBarEvtScId );
1324
+        p->array[ barEvtIdx ].secs = secs;
1053 1325
 
1054
-      // handle the case where the previous bar had no events
1055
-      // BUG BUG BUG this is a hack which will fail if the first bar does not have events.
1056
-      if( barEvtIdx>=1 && p->array[ barEvtIdx-1].type == kBarEvtScId )
1057
-        p->array[ barEvtIdx-1].secs = secs;
1326
+        // handle the case where the previous bar had no events
1327
+        // BUG BUG BUG this is a hack which will fail if the first bar does not have events.
1328
+        if( barEvtIdx>=1 && p->array[ barEvtIdx-1].type == kBarEvtScId )
1329
+          p->array[ barEvtIdx-1].secs = secs;
1058 1330
 
1059
-      barEvtIdx = cmInvalidIdx;
1331
+        barEvtIdx = cmInvalidIdx;
1332
+      }
1060 1333
     }
1061 1334
     
1062 1335
   }
@@ -1164,6 +1437,9 @@ cmScRC_t cmScoreInitialize( cmCtx_t* ctx, cmScH_t* hp, const cmChar_t* fn, doubl
1164 1437
   if((rc = _cmScProcSections(p,p->sectList)) != kOkScRC )
1165 1438
     goto errLabel;
1166 1439
 
1440
+  if((rc = _cmScProcMarkers(p)) != kOkScRC )
1441
+    goto errLabel;
1442
+  
1167 1443
   // load the dynamic reference array
1168 1444
   if( dynRefArray != NULL && dynRefCnt > 0)
1169 1445
   {
@@ -1409,6 +1685,30 @@ unsigned cmScoreSetCount( cmScH_t h )
1409 1685
   return p->setCnt;
1410 1686
 }
1411 1687
 
1688
+unsigned      cmScoreMarkerLabelCount( cmScH_t h )
1689
+{
1690
+  cmSc_t* p = _cmScHandleToPtr(h);
1691
+  return p->markLabelCnt;
1692
+}
1693
+
1694
+unsigned      cmScoreMarkerLabelSymbolId( cmScH_t h, unsigned idx )
1695
+{
1696
+  cmSc_t* p = _cmScHandleToPtr(h);
1697
+  assert( idx < p->markLabelCnt );
1698
+  return p->markLabelArray[idx];
1699
+}
1700
+
1701
+const cmScoreMarker_t* cmScoreMarker( cmScH_t h, cmMarkScMId_t markMId, unsigned labelSymId )
1702
+{
1703
+  cmSc_t* p = _cmScHandleToPtr(h);
1704
+  const cmScoreMarker_t* smp = NULL;
1705
+  if( _cmScFindMarkLoc(p, markMId, labelSymId, &smp ) == NULL )
1706
+    return NULL;
1707
+
1708
+  return smp;
1709
+}
1710
+
1711
+
1412 1712
 cmScRC_t      cmScoreSeqNotify( cmScH_t h )
1413 1713
 {
1414 1714
   cmScRC_t  rc = kOkScRC;
@@ -1502,7 +1802,7 @@ void _cmScPerfSortTimes( unsigned *v, unsigned n )
1502 1802
         fl = true;
1503 1803
       }
1504 1804
     }
1505
-   --n;
1805
+    --n;
1506 1806
   }
1507 1807
 }
1508 1808
 
@@ -1568,13 +1868,13 @@ bool _cmScPerfEven(cmSc_t* p, cmScoreSet_t* stp, bool printMissFl)
1568 1868
   if(printFl)
1569 1869
   {
1570 1870
     /*
1571
-    for(i=0; i<stp->eleCnt; ++i)
1572
-    {
1871
+      for(i=0; i<stp->eleCnt; ++i)
1872
+      {
1573 1873
       printf("%i %i ",i,v[i]);
1574 1874
       if( i > 0 )
1575
-        printf("%i ", d[i-1]);
1875
+      printf("%i ", d[i-1]);
1576 1876
       printf("\n");
1577
-    }
1877
+      }
1578 1878
     */
1579 1879
     printf("%s EVENESS:%f\n",sortFl?"SORTED ":"",stp->value);
1580 1880
   }
@@ -1955,6 +2255,214 @@ void cmScorePrint( cmScH_t h, cmRpt_t* rpt )
1955 2255
   }
1956 2256
 }
1957 2257
 
2258
+cmScRC_t      cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* scoreFn )
2259
+{
2260
+  cmScRC_t      rc  = kOkScRC;
2261
+  cmMidiFileH_t mfH = cmMidiFileNullHandle;
2262
+  cmCsvH_t      csvH = cmCsvNullHandle;
2263
+  cmErr_t       err;
2264
+  cmChar_t*     titles[] = {"id","trk","evt","opcode","dticks","micros","status","meta","ch","d0","d1","arg0","arg1","bar","skip","even","grace","tempo","t frac","dyn","section","remark", NULL };
2265
+  
2266
+  cmErrSetup(&err,&ctx->rpt,"MIDI to Score");
2267
+
2268
+  if( cmMidiFileOpen(midiFn, &mfH, ctx ) != kOkMfRC )
2269
+    return cmErrMsg(&err,kMidiFileFailScRC,"Unable to open the MIDI file '%s'.",midiFn);
2270
+
2271
+  if( cmCsvInitialize(&csvH,ctx) != kOkCsvRC )
2272
+  {
2273
+    cmErrMsg(&err,kCsvFailScRC,"Unable to initialize the CSV file: '%s'.",scoreFn);
2274
+    goto errLabel;
2275
+  }
2276
+
2277
+  // Convert the track message 'dtick' field to delta-microseconds.
2278
+  cmMidiFileTickToMicros(mfH);
2279
+
2280
+
2281
+  unsigned                 msgCnt = cmMidiFileMsgCount(mfH);
2282
+  unsigned                 i;
2283
+  const cmMidiTrackMsg_t** tmpp   = cmMidiFileMsgArray(mfH);
2284
+  double                   acc_secs = 0;
2285
+  unsigned                lexTId = 0;
2286
+  cmCsvCell_t*            cp     = NULL;
2287
+    
2288
+
2289
+  if( cmCsvAppendRow(csvH, &cp, cmCsvInsertSymText(csvH,titles[0]), kStrCsvTFl, lexTId ) != kOkCsvRC )
2290
+  {
2291
+    cmErrMsg(&err,kCsvFailScRC,"Error inserting 'id' column in '%s'.",cmStringNullGuard(scoreFn));
2292
+    goto errLabel;
2293
+  }
2294
+
2295
+  for(i=1; titles[i]!=NULL; ++i)
2296
+  {
2297
+    if( cmCsvInsertTextColAfter(csvH, cp, &cp, titles[i], lexTId ) != kOkCsvRC )
2298
+    {
2299
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting column index '%i' label in '%s'.",i,cmStringNullGuard(scoreFn));
2300
+      goto errLabel;
2301
+    }
2302
+
2303
+  }    
2304
+
2305
+
2306
+
2307
+  for(i=0; i<msgCnt; ++i)
2308
+  {
2309
+    const cmMidiTrackMsg_t* tmp    = tmpp[i];
2310
+    const cmChar_t*         opStr  = NULL;
2311
+    unsigned                midiCh = 0;
2312
+    unsigned                d0     = 0;
2313
+    unsigned                d1     = 0;
2314
+    unsigned metaId = 0;
2315
+    double   dsecs  = (double)tmp->dtick / 1000000.0;
2316
+
2317
+    acc_secs += dsecs;
2318
+
2319
+    if( tmp->status == kMetaStId )
2320
+    {
2321
+      opStr  = cmMidiMetaStatusToLabel(tmp->metaId);
2322
+      metaId = tmp->metaId;
2323
+
2324
+      switch( tmp->metaId )
2325
+      {
2326
+        case kTempoMdId:
2327
+          d0 = tmp->u.iVal;
2328
+      }
2329
+    }
2330
+    else
2331
+    {
2332
+      opStr = cmMidiStatusToLabel(tmp->status);
2333
+      if( cmMidiIsChStatus( tmp->status ) )
2334
+      {
2335
+        midiCh = tmp->u.chMsgPtr->ch;
2336
+        d0     = tmp->u.chMsgPtr->d0;
2337
+        d1     = tmp->u.chMsgPtr->d1;
2338
+      }
2339
+    }
2340
+
2341
+    cp = NULL;
2342
+
2343
+    // skip note-off messages
2344
+    if( tmp->status == kNoteOffMdId )
2345
+      continue;
2346
+
2347
+    if( cmCsvAppendRow(csvH, &cp, cmCsvInsertSymUInt(csvH,i), kIntCsvTFl, lexTId ) != kOkCsvRC )
2348
+    {
2349
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'id' column in '%s'.",cmStringNullGuard(scoreFn));
2350
+      goto errLabel;
2351
+    }
2352
+
2353
+    if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->trkIdx, lexTId ) != kOkCsvRC )
2354
+    {
2355
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'trk' column in '%s'.",cmStringNullGuard(scoreFn));
2356
+      goto errLabel;
2357
+    }
2358
+
2359
+    if( cmCsvInsertUIntColAfter(csvH, cp, &cp, 0, lexTId ) != kOkCsvRC )
2360
+    {
2361
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'evt' column in '%s'.",cmStringNullGuard(scoreFn));
2362
+      goto errLabel;
2363
+    }
2364
+
2365
+    if( cmCsvInsertTextColAfter(csvH, cp, &cp, opStr, lexTId ) != kOkCsvRC )
2366
+    {
2367
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'opcode' column in '%s'.",cmStringNullGuard(scoreFn));
2368
+      goto errLabel;
2369
+    }
2370
+
2371
+    if( cmCsvInsertDoubleColAfter(csvH, cp, &cp, dsecs, lexTId ) != kOkCsvRC )
2372
+    {
2373
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'dticks' column in '%s'.",cmStringNullGuard(scoreFn));
2374
+      goto errLabel;
2375
+    }
2376
+
2377
+    if( cmCsvInsertDoubleColAfter(csvH, cp, &cp, acc_secs, lexTId ) != kOkCsvRC )
2378
+    {
2379
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'micros' column in '%s'.",cmStringNullGuard(scoreFn));
2380
+      goto errLabel;
2381
+    }
2382
+    
2383
+    if( cmCsvInsertHexColAfter(csvH, cp, &cp, tmp->status, lexTId ) != kOkCsvRC )
2384
+    {
2385
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'status' column in '%s'.",cmStringNullGuard(scoreFn));
2386
+      goto errLabel;
2387
+    }
2388
+
2389
+    if( cmCsvInsertUIntColAfter(csvH, cp, &cp, metaId, lexTId ) != kOkCsvRC )
2390
+    {
2391
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'meta' column in '%s'.",cmStringNullGuard(scoreFn));
2392
+      goto errLabel;
2393
+    }
2394
+
2395
+    if( cmCsvInsertUIntColAfter(csvH, cp, &cp, midiCh, lexTId ) != kOkCsvRC )
2396
+    {
2397
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'ch' column in '%s'.",cmStringNullGuard(scoreFn));
2398
+      goto errLabel;
2399
+    }
2400
+
2401
+    if( cmCsvInsertUIntColAfter(csvH, cp, &cp, d0, lexTId ) != kOkCsvRC )
2402
+    {
2403
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'd0' column in '%s'.",cmStringNullGuard(scoreFn));
2404
+      goto errLabel;
2405
+    }
2406
+
2407
+    if( cmCsvInsertUIntColAfter(csvH, cp, &cp, d1, lexTId ) != kOkCsvRC )
2408
+    {
2409
+      cmErrMsg(&err,kCsvFailScRC,"Error inserting 'd1' column in '%s'.",cmStringNullGuard(scoreFn));
2410
+      goto errLabel;
2411
+    }
2412
+
2413
+    switch( tmp->status )
2414
+    {
2415
+      case kNoteOnMdId:
2416
+        if( cmCsvInsertTextColAfter(csvH, cp, &cp, cmMidiToSciPitch(tmp->u.chMsgPtr->d0,NULL,0), lexTId ) != kOkCsvRC )
2417
+        {
2418
+          cmErrMsg(&err,kCsvFailScRC,"Error inserting 'opcode' column in '%s'.",cmStringNullGuard(scoreFn));
2419
+          goto errLabel;
2420
+        }
2421
+
2422
+      case kMetaStId:
2423
+        switch( tmp->metaId )
2424
+        {
2425
+          case kTimeSigMdId:
2426
+            if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->num, lexTId ) != kOkCsvRC )
2427
+            {
2428
+              cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. numerator column in '%s'.",cmStringNullGuard(scoreFn));
2429
+              goto errLabel;
2430
+            }
2431
+
2432
+            if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->den, lexTId ) != kOkCsvRC )
2433
+            {
2434
+              cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. denominator column in '%s'.",cmStringNullGuard(scoreFn));
2435
+              goto errLabel;
2436
+            }
2437
+            break;
2438
+
2439
+          case kTempoMdId:
2440
+            if( cmCsvInsertUIntColAfter(csvH, cp, &cp, 60000000/tmp->u.iVal, lexTId ) != kOkCsvRC )
2441
+            {
2442
+              cmErrMsg(&err,kCsvFailScRC,"Error inserting 'tempo' in '%s'.",cmStringNullGuard(scoreFn));
2443
+              goto errLabel;
2444
+            }
2445
+            break;
2446
+        }
2447
+
2448
+    }
2449
+
2450
+
2451
+  }
2452
+  
2453
+  if(  cmCsvWrite(csvH,scoreFn) != kOkCsvRC )
2454
+  {
2455
+    cmErrMsg(&err,kCsvFailScRC,"The score output file '%s' could not be written.",cmStringNullGuard(scoreFn));
2456
+    goto errLabel;
2457
+  }
2458
+
2459
+ errLabel:
2460
+  cmMidiFileClose(&mfH);
2461
+  cmCsvFinalize(&csvH);
2462
+
2463
+  return rc;
2464
+}
2465
+
1958 2466
 void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
1959 2467
 {
1960 2468
   cmScH_t h = cmScNullHandle;

+ 36
- 9
app/cmScore.h Vedi File

@@ -12,8 +12,8 @@ extern "C" {
12 12
     kSyntaxErrScRC,
13 13
     kInvalidIdxScRC,
14 14
     kTimeLineFailScRC,
15
-    kInvalidDynRefCntScRC
16
-  
15
+    kInvalidDynRefCntScRC,
16
+    kMidiFileFailScRC
17 17
   };
18 18
 
19 19
   enum
@@ -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
@@ -235,6 +259,9 @@ extern "C" {
235 259
 
236 260
   void          cmScorePrint( cmScH_t h, cmRpt_t* rpt );
237 261
 
262
+  // Generate a new score file from a MIDI file.
263
+  cmScRC_t      cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* scoreFn );
264
+
238 265
   void          cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn );
239 266
 
240 267
 

+ 53
- 5
cmCsv.c Vedi File

@@ -729,6 +729,20 @@ unsigned   cmCsvInsertSymUInt(   cmCsvH_t h, unsigned v )
729 729
   return cmInvalidId;
730 730
 }
731 731
 
732
+unsigned   cmCsvInsertSymHex(   cmCsvH_t h, unsigned v )
733
+{
734
+  const char* fmt = "0x%x";
735
+  unsigned    n   = snprintf(NULL,0,fmt,v)+1;
736
+  char        buf[n];
737
+
738
+  buf[0]= 0;
739
+  if( snprintf(buf,n,fmt,v) == n-1 )
740
+    return cmCsvInsertSymText(h,buf);
741
+  
742
+  _cmCsvError(_cmCsvHandleToPtr(h),kDataCvtErrCsvRC,"The unsigned int 0x%x could not be converted to text.",v);
743
+  return cmInvalidId;
744
+}
745
+
732 746
 unsigned   cmCsvInsertSymFloat(  cmCsvH_t h, float v )
733 747
 {
734 748
   const char* fmt = "%f";
@@ -812,6 +826,24 @@ cmCsvRC_t  cmCsvSetCellUInt(   cmCsvH_t h, unsigned row, unsigned col, unsigned
812 826
   return kOkCsvRC;  
813 827
 }
814 828
 
829
+cmCsvRC_t  cmCsvSetCellHex(   cmCsvH_t h, unsigned row, unsigned col, unsigned v )
830
+{
831
+  cmCsvCell_t* cp;
832
+  unsigned     symId;
833
+
834
+  if((cp = _cmCsvCellPtr(h,row,col)) == NULL )
835
+    return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
836
+
837
+  if((symId = cmCsvInsertSymHex(h,v)) == cmInvalidId )
838
+    return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
839
+  
840
+  cp->symId = symId;
841
+  cp->flags &= !kTypeTMask;
842
+  cp->flags |= kIntCsvTFl;
843
+
844
+  return kOkCsvRC;  
845
+}
846
+
815 847
 cmCsvRC_t  cmCsvSetCellFloat(  cmCsvH_t h, unsigned row, unsigned col, float v )
816 848
 {
817 849
   cmCsvCell_t* cp;
@@ -985,7 +1017,7 @@ cmCsvRC_t  cmCsvInsertTextColAfter(   cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
985 1017
   cmCsvCell_t* ncp;
986 1018
 
987 1019
   if( cellPtrPtr != NULL )
988
-    cellPtrPtr = NULL;
1020
+    *cellPtrPtr = NULL;
989 1021
 
990 1022
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
991 1023
     if((rc = cmCsvSetCellText(h, ncp->row, ncp->col, text )) == kOkCsvRC )
@@ -1001,7 +1033,7 @@ cmCsvRC_t  cmCsvInsertIntColAfter(    cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
1001 1033
   cmCsvCell_t* ncp;
1002 1034
 
1003 1035
   if( cellPtrPtr != NULL )
1004
-    cellPtrPtr = NULL;
1036
+    *cellPtrPtr = NULL;
1005 1037
 
1006 1038
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1007 1039
     if((rc = cmCsvSetCellInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
@@ -1017,7 +1049,7 @@ cmCsvRC_t  cmCsvInsertUIntColAfter(   cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
1017 1049
   cmCsvCell_t* ncp;
1018 1050
 
1019 1051
   if( cellPtrPtr != NULL )
1020
-    cellPtrPtr = NULL;
1052
+    *cellPtrPtr = NULL;
1021 1053
 
1022 1054
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1023 1055
     if((rc = cmCsvSetCellUInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
@@ -1027,13 +1059,29 @@ cmCsvRC_t  cmCsvInsertUIntColAfter(   cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
1027 1059
   return rc;
1028 1060
 }
1029 1061
 
1062
+cmCsvRC_t  cmCsvInsertHexColAfter(   cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val, unsigned lexTId )
1063
+{
1064
+  cmCsvRC_t    rc;
1065
+  cmCsvCell_t* ncp;
1066
+
1067
+  if( cellPtrPtr != NULL )
1068
+    *cellPtrPtr = NULL;
1069
+
1070
+  if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1071
+    if((rc = cmCsvSetCellHex(h, ncp->row, ncp->col, val )) == kOkCsvRC )
1072
+      if( cellPtrPtr != NULL )
1073
+        *cellPtrPtr = ncp;
1074
+  
1075
+  return rc;
1076
+}
1077
+
1030 1078
 cmCsvRC_t  cmCsvInsertFloatColAfter(  cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val, unsigned lexTId )
1031 1079
 {
1032 1080
   cmCsvRC_t    rc;
1033 1081
   cmCsvCell_t* ncp;
1034 1082
 
1035 1083
   if( cellPtrPtr != NULL )
1036
-    cellPtrPtr = NULL;
1084
+    *cellPtrPtr = NULL;
1037 1085
 
1038 1086
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1039 1087
     if((rc = cmCsvSetCellFloat(h, ncp->row, ncp->col, val )) == kOkCsvRC )
@@ -1049,7 +1097,7 @@ cmCsvRC_t  cmCsvInsertDoubleColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
1049 1097
   cmCsvCell_t* ncp;
1050 1098
 
1051 1099
   if( cellPtrPtr != NULL )
1052
-    cellPtrPtr = NULL;
1100
+    *cellPtrPtr = NULL;
1053 1101
 
1054 1102
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1055 1103
     if((rc = cmCsvSetCellDouble(h, ncp->row, ncp->col, val )) == kOkCsvRC )

+ 4
- 0
cmCsv.h Vedi File

@@ -109,13 +109,16 @@ extern "C" {
109 109
   unsigned   cmCsvInsertSymText(   cmCsvH_t h, const char* text );
110 110
   unsigned   cmCsvInsertSymInt(    cmCsvH_t h, int v );
111 111
   unsigned   cmCsvInsertSymUInt(   cmCsvH_t h, unsigned v );
112
+  unsigned   cmCsvInsertSymHex(    cmCsvH_t h, unsigned v );
112 113
   unsigned   cmCsvInsertSymFloat(  cmCsvH_t h, float v );
113 114
   unsigned   cmCsvInsertSymDouble( cmCsvH_t h, double v );  
114 115
 
116
+
115 117
   // Set the value associated with a cell.
116 118
   cmCsvRC_t  cmCsvSetCellText(   cmCsvH_t h, unsigned row, unsigned col, const char* text );
117 119
   cmCsvRC_t  cmCsvSetCellInt(    cmCsvH_t h, unsigned row, unsigned col, int v );
118 120
   cmCsvRC_t  cmCsvSetCellUInt(   cmCsvH_t h, unsigned row, unsigned col, unsigned v );
121
+  cmCsvRC_t  cmCsvSetCellHex(    cmCsvH_t h, unsigned row, unsigned col, unsigned v );
119 122
   cmCsvRC_t  cmCsvSetCellFloat(  cmCsvH_t h, unsigned row, unsigned col, float v );
120 123
   cmCsvRC_t  cmCsvSetCellDouble( cmCsvH_t h, unsigned row, unsigned col, double v );
121 124
 
@@ -134,6 +137,7 @@ extern "C" {
134 137
   cmCsvRC_t  cmCsvInsertTextColAfter(   cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, const char* val, unsigned lexTId );
135 138
   cmCsvRC_t  cmCsvInsertIntColAfter(    cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, int val,         unsigned lexTId );
136 139
   cmCsvRC_t  cmCsvInsertUIntColAfter(   cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val,    unsigned lexTId );
140
+  cmCsvRC_t  cmCsvInsertHexColAfter(    cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val,    unsigned lexTId );
137 141
   cmCsvRC_t  cmCsvInsertFloatColAfter(  cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val,       unsigned lexTId );
138 142
   cmCsvRC_t  cmCsvInsertDoubleColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, double val,      unsigned lexTId );
139 143
 

+ 2053
- 1491
cmData.c
File diff soppresso perché troppo grande
Vedi File


+ 311
- 263
cmData.h Vedi File

@@ -5,85 +5,129 @@
5 5
 extern "C" {
6 6
 #endif
7 7
 
8
+  /*
9
+    TODO:
10
+    0) Figure out a error handling scheme that does not rely on
11
+    a global errno.  This is not useful in multi-thread environments.
12
+    It might be ok to go with an 'all errors are fatal' model
13
+    (except in the var-args functions).
14
+    Consider the use of a context object for use with functions 
15
+    that can have runtime errors or need to allocate memory.
16
+
17
+    1) Implement the canConvert and willTruncate functions.
18
+
19
+    2) Make a set of cmDataAllocXXXPtr() functions which take
20
+    a flag indicating whether or not to dynamically allocate
21
+    the array space. This will allow dynamic allocattion to
22
+    occur at runtime.  Make var args functions for list and
23
+    record objects which also take this flag.
24
+    Whereever a function may be implemented using 
25
+    static/dynamic allocation this flag should be present.
26
+    (e.g. string allocation for pair labels)
27
+    This choice is common enough that it may be worth
28
+    suffixing function names with a capital letter to
29
+    be clear what the functions memory policy is.
30
+
31
+    3) Come up with a var-args format which allows a 
32
+    hierchy of records to be defined in one line.
33
+
34
+    4) Implement the serialization functions.
35
+
36
+    5) Implement an ascii string/parse format for writing/reading.
37
+
38
+    6) Implement fast lookup of record fields.
39
+
40
+    7) Allow for user defined types.  For example a 'matrix'
41
+    data type. This might be as simple as adding an extra 'user_tid' 
42
+    field to cmData_t.
43
+
44
+    8) Implement type specific cmDataGetRecordValueXXX() functions.
45
+
46
+    9) Implement cmDataIsEqual(), cmDataIsLtE(), ...
47
+
48
+   */
49
+
8 50
   enum
9 51
   {
10 52
     kOkDtRC = cmOkRC,
53
+    kAssertErrDtRC,
54
+    kConstErrDtRC,
11 55
     kCvtErrDtRC,
12
-    kVarArgErrDtRC,
13
-    kMissingFieldDtRC,
56
+    kInvalidContDtRC,
57
+    kInvalidTypeDtRC,
14 58
     kEolDtRC
15 59
   };
16 60
 
17
-  enum
61
+  typedef unsigned cmDtRC_t;
62
+
63
+  typedef enum
18 64
   {
19
-    kInvalidDtChar   = 0xff,
20
-    kInvalidDtUChar  = 0xff,
21
-    kInvalidDtShort  = 0xffff,
22
-    kInvalidDtUShort = 0xffff,
23
-    kInvalidDtInt    = 0xffffffff,
24
-    kInvalidDtUInt   = 0xffffffff,
25
-    kInvalidDtLong   = 0xffffffff,
26
-    kInvalidDtULong  = 0xffffffff,    
27
-  };
65
+    kInvalidTypeDtId,// 0
66
+    kNullDtId,       // 1 the data object exists but it has no data
67
+    kUCharDtId,      // 2
68
+    kCharDtId,       // 3
69
+    kUShortDtId,     // 4 
70
+    kShortDtId,      // 5
71
+    kUIntDtId,       // 6
72
+    kIntDtId,        // 7
73
+    kULongDtId,      // 8
74
+    kLongDtId,       // 9
75
+    kFloatDtId,      // 10 
76
+    kDoubleDtId,     // 11 
77
+    kStrDtId,        // 12 zero terminated string
78
+    kBlobDtId,       // 13 application defined raw memory object
79
+    kStructDtId      // 14 node is a pair,list, or recd
80
+  } cmDataTypeId_t;
81
+
28 82
 
29 83
   typedef enum
30 84
   {
31
-    kInvalidDtId,
32
-
33
-    kMinValDtId,
34
-
35
-    kNullDtId = kMinValDtId,
36
-    kUCharDtId,
37
-    kCharDtId,
38
-    kUShortDtId,
39
-    kShortDtId,
40
-    kUIntDtId,
41
-    kIntDtId,
42
-    kULongDtId,
43
-    kLongDtId,
44
-    kFloatDtId,
45
-    kDoubleDtId,
46
-
47
-    kStrDtId,
48
-    kConstStrDtId,
49
-    kMaxValDtId = kConstStrDtId,
50
-
51
-    kMinPtrDtId,
52
-    kUCharPtrDtId = kMinPtrDtId,  // cnt=array element count
53
-    kCharPtrDtId,
54
-    kUShortPtrDtId,
55
-    kShortPtrDtId,
56
-    kUIntPtrDtId,
57
-    kIntPtrDtId,
58
-    kULongPtrDtId,
59
-    kLongPtrDtId,
60
-    kFloatPtrDtId,
61
-    kDoublePtrDtId,
62
-    kVoidPtrDtId,
63
-    kMaxPtrDtId = kVoidPtrDtId,
64
-
65
-    kMinStructDtId,
66
-    kListDtId = kMinStructDtId, // children nodes are array elements, cnt=child count
67
-    kPairDtId,                  // key/value pairs, cnt=2, first child is key, second is value
68
-    kRecordDtId,                // children nodes are pairs, cnt=pair count
69
-    kMaxStructDtId,
70
-
71
-    kOptArgDtFl = 0x80000000
72
-  } cmDataFmtId_t;
85
+    kInvalidCntDtId, // 0 
86
+    kScalarDtId,     // 1
87
+    kArrayDtId,      // 2
88
+    kPairDtId,       // 3
89
+    kListDtId,       // 4
90
+    kRecordDtId      // 5
91
+  } cmDataContainerId_t;
73 92
 
74 93
   enum
75 94
   {
76
-    kDynObjDtFl = 0x01,  // object was dynamically allocated
77
-    kDynPtrDtFl = 0x02   // ptr array was dynamically allocated
95
+    kNoFlagsDtFl = 0x00,
96
+
97
+    // Indicate that the memory used by the data object
98
+    // was dynamically allocated and should be released
99
+    // by cmDataFree().
100
+    kFreeObjDtFl   = 0x01,
101
+
102
+    // Indicate that the memory used by strings, blobs 
103
+    // and arrays should be freed by cmDataFree().
104
+    kFreeValueDtFl = 0x02, 
105
+
106
+    // Indicate that the value of the object cannot be changed.
107
+    // (but the object could be reassigned as a new type).
108
+    kConstValueDtFl = 0x04,
109
+
110
+    // Indicate that the type of the object cannot be changed.
111
+    // (but the value may be changed).
112
+    kConstObjDtFl  = 0x08,
113
+
114
+    // Indicate that the array or string should not be 
115
+    // internally reallocated but rather the source pointer
116
+    // should be taken as the new value of the object.
117
+    kNoCopyDtFl = 0x10, 
118
+
119
+
78 120
   };
79 121
 
122
+
80 123
   typedef struct cmData_str
81 124
   {
82
-    cmDataFmtId_t      tid;       // data format id
83
-    unsigned           flags;     // 
84
-    struct cmData_str* parent;    // this childs parent
85
-    struct cmData_str* sibling;   // this childs left sibling
86
-    unsigned           cnt;       // array ele count
125
+    cmDataTypeId_t      tid;       // data format id
126
+    cmDataContainerId_t cid;       // container id
127
+    unsigned            flags;     // 
128
+    struct cmData_str*  parent;    // this childs parent
129
+    struct cmData_str*  sibling;   // this childs left sibling
130
+    unsigned            cnt;       // byte cnt for strings/blobs and ele count for arrays
87 131
 
88 132
     union
89 133
     {
@@ -99,10 +143,10 @@ extern "C" {
99 143
       double            d;
100 144
 
101 145
       cmChar_t*         z;
102
-      const cmChar_t*  cz;
103 146
 
104 147
       void*             vp;
105 148
 
149
+      /*
106 150
       char*             cp;
107 151
       unsigned char*   ucp;
108 152
       short*            sp;
@@ -113,97 +157,117 @@ extern "C" {
113 157
       unsigned long*   ulp;
114 158
       float*            fp;
115 159
       double*           dp;
160
+      */
116 161
 
117
-
118
-      struct cmData_str* child; // first child (array,record,pair)
162
+      struct cmData_str* child; // first child (list,record,pair)
119 163
     } u;
120 164
   
121 165
   } cmData_t;
122 166
 
123
-  typedef unsigned cmDtRC_t;
124
-
125 167
   extern cmData_t cmDataNull;
126 168
 
127
-  bool cmDataIsValue(  const cmData_t* p );
128
-  bool cmDataIsPtr(    const cmData_t* p );
129
-  bool cmDataIsStruct( const cmData_t* p ); // is a pair,list or record
169
+  const cmChar_t*  cmDataTypeToLabel( cmDataTypeId_t tid );
170
+  cmDataTypeId_t   cmDataLabelToType( const cmChar_t* typeLabelStr );
130 171
 
131
-  /*
132
-    TODO:
133
-    0) Figure out a error handling scheme that does not rely on
134
-    a global errno.  This is not useful in multi-thread environments.
135
-    It might be ok to go with an 'all errors are fatal' model
136
-    (except in the var-args functions).
137
-    Consider the use of a context object for use with functions 
138
-    that can have runtime errors or need to allocate memory.
172
+  // Returns 1 for kStrDtId.
173
+  // Returns cmInvalidCnt if tid is not recognized.
174
+  unsigned         dmDataByteWidth( cmDataTypeId_t tid );
139 175
 
140
-    1) Implement the canConvert and willTruncate functions.
176
+  const cmChar_t*      cmDataContainerIdToLabel( cmDataContainerId_t tid );
177
+  cmDataContainerId_t  cmDataLabelToContainerId( const cmChar_t* contLabelStr );
141 178
 
142
-    2) Make a set of cmDataAllocXXXPtr() functions which take
143
-    a flag indicating whether or not to dynamically allocate
144
-    the array space. This will allow dynamic allocattion to
145
-    occur at runtime.  Make var args functions for list and
146
-    record objects which also take this flag.
147
-    Where ever a function may be implemented using 
148
-    static/dynamic allocation this flag should be present.
149
-    (e.g. string allocation for pair labels)
150
-    This choice is common enough that it may be worth
151
-    suffixing function names with a capital letter to
152
-    be clear what the functions memory policy is.
153
-
154
-    3) Come up with a var-args format which allows a 
155
-    hierchy of records to be defined in one line.
179
+  bool cmDataIsConstObj( const cmData_t* d );
180
+  void cmDataEnableConstObj( cmData_t* d, bool enaFl );
156 181
 
157
-    4) Implement the serialization functions.
182
+  bool cmDataIsConstValue( const cmData_t* d );
183
+  void cmDataEnableConstValue( cmData_t* d, bool enaFl );
158 184
 
159
-    5) Implement an ascii string/parse format for writing/reading.
185
+  bool cmDataIsFreeValue( const cmData_t* d );
186
+  void cmDataEnableFreeValue( cmData_t* d, bool enaFl );
160 187
 
161
-    6) Implement fast lookup of record fields.
188
+  // Returns true if this is a scalar or array node.
189
+  bool cmDataIsLeaf( const cmData_t* d);
162 190
 
163
-    7) Allow for user defined types.  For example a 'matrix'
164
-    data type. This might be as simple as adding an extra 'user_tid' 
165
-    field to cmData_t.
191
+  // Return true if this is NOT a scalar or array node.
192
+  bool cmDataIsStruct( const cmData_t* d );
193
+  
194
+  
166 195
 
167
-    8) Implement type specific cmDataGetRecordValueXXX() functions.
196
+  //----------------------------------------------------------------------------
197
+  // Scalar related functions
198
+  //
168 199
 
169
-    9) Implement cmDataIsEqual(), cmDataIsLtE(), ...
200
+  // Dynamically allocate a scalar object and set it's value.
201
+  // The 'flags' argument may include kConstValueDtFl and kConstObjDtFl.
202
+  // The string and blob constructors may also use the
203
+  // kNoCopyDtFl and the kFreeValueDtFl.
204
+
205
+  // Generic:
206
+  // 'byteCnt' is ignored for all types other than strings and blobs.
207
+  cmDtRC_t cmDataNewScalar( cmData_t* parent, cmDataTypeId_t tid, unsigned flags, void* vp, unsigned byteCnt, cmData_t** ref );
208
+
209
+  // Type specific
210
+  cmDtRC_t cmDataNewNull(     cmData_t* parent, unsigned flags,                   cmData_t** ref );
211
+  cmDtRC_t cmDataNewChar(     cmData_t* parent, unsigned flags, char v,           cmData_t** ref );
212
+  cmDtRC_t cmDataNewUChar(    cmData_t* parent, unsigned flags, unsigned char v,  cmData_t** ref );
213
+  cmDtRC_t cmDataNewShort(    cmData_t* parent, unsigned flags, short v,          cmData_t** ref );
214
+  cmDtRC_t cmDataNewUShort(   cmData_t* parent, unsigned flags, unsigned short v, cmData_t** ref );
215
+  cmDtRC_t cmDataNewInt(      cmData_t* parent, unsigned flags, int v,            cmData_t** ref );
216
+  cmDtRC_t cmDataNewUInt(     cmData_t* parent, unsigned flags, unsigned int v,   cmData_t** ref );
217
+  cmDtRC_t cmDataNewLong(     cmData_t* parent, unsigned flags, long v,           cmData_t** ref );
218
+  cmDtRC_t cmDataNewULong(    cmData_t* parent, unsigned flags, unsigned long v,  cmData_t** ref );
219
+  cmDtRC_t cmDataNewFloat(    cmData_t* parent, unsigned flags, float v,          cmData_t** ref );
220
+  cmDtRC_t cmDataNewDouble(   cmData_t* parent, unsigned flags, double v,         cmData_t** ref );
221
+  cmDtRC_t cmDataNewStr(      cmData_t* parent, unsigned flags, cmChar_t* str,       cmData_t** ref );
222
+  cmDtRC_t cmDataNewConstStr( cmData_t* parent, unsigned flags, const cmChar_t* str, cmData_t** ref );
223
+  cmDtRC_t cmDataNewStrN(     cmData_t* parent, unsigned flags, cmChar_t* str,       unsigned charCnt, cmData_t** ref );
224
+  cmDtRC_t cmDataNewConstStrN(cmData_t* parent, unsigned flags, const cmChar_t* str, unsigned charCnt, cmData_t** ref );
225
+  cmDtRC_t cmDataNewBlob(     cmData_t* parent, unsigned flags, void* vp,            unsigned byteCnt, cmData_t** ref );
226
+  cmDtRC_t cmDataNewConstBlob(cmData_t* parent, unsigned flags, const void* vp,      unsigned byteCnt, cmData_t** ref );
227
+ 
170 228
 
171
-   */
172 229
 
173
-  bool canConvertType( cmDataFmtId_t srcId, cmDataFmtId_t dstId );
174
-  bool willTruncate(   cmDataFmtId_t srcId, cmDataFmtId_t dstId );
175
-  bool canConvertObj(  const cmData_t* srcObj, cmData_t* dstObj );
176
-  bool willTruncateObj(const cmData_t* srcObj, cmData_t* dstObj );
177
-    
230
+  // Set the value and type of an existing scalar object.
231
+  // These functions begin by releasing any resources held by *p
232
+  // prior to resetting the type and value of the object.
233
+  // The 'flags' argument to cmDataSetStr() and cmDataSetConstStr() 
234
+  // may use the kNoCopyDtFl and the kFreeValueDtFl
235
+  cmDtRC_t  cmDataSetScalarValue( cmData_t* d, cmDataTypeId_t tid, void* vp, unsigned byteCnt, unsigned flags );
178 236
   
179
-
180
-  // Get the value of an object without conversion.
181
-  // The data type id must match the return type or the
182
-  // conversion must be an automatic C conversion.
183
-  char            cmDataChar(      const cmData_t* p );
184
-  unsigned char   cmDataUChar(     const cmData_t* p );
185
-  short           cmDataShort(     const cmData_t* p );
186
-  unsigned short  cmDataUShort(    const cmData_t* p );
187
-  int             cmDataInt(       const cmData_t* p );
188
-  unsigned int    cmDataUInt(      const cmData_t* p );
189
-  long            cmDataLong(      const cmData_t* p );
190
-  unsigned long   cmDataULong(     const cmData_t* p );
191
-  float           cmDataFloat(     const cmData_t* p );
192
-  double          cmDataDouble(    const cmData_t* p );
193
-  cmChar_t*       cmDataStr(       const cmData_t* p );
194
-  const cmChar_t* cmDataConstStr(  const cmData_t* p );
195
-  void*           cmDataVoidPtr(   const cmData_t* p );
196
-  char*           cmDataCharPtr(   const cmData_t* p );
197
-  unsigned char*  cmDataUCharPtr(  const cmData_t* p );
198
-  short*          cmDataShortPtr(  const cmData_t* p );
199
-  unsigned short* cmDataUShortPtr( const cmData_t* p );
200
-  int*            cmDataIntPtr(    const cmData_t* p );
201
-  unsigned int*   cmDataUIntPtr(   const cmData_t* p );
202
-  long*           cmDataLongPtr(   const cmData_t* p );
203
-  unsigned long*  cmDataULongPtr(  const cmData_t* p );
204
-  float*          cmDataFloatPtr(  const cmData_t* p );
205
-  double*         cmDataDoublePtr( const cmData_t* p );
206
-
237
+  cmDtRC_t cmDataSetNull(      cmData_t* p );
238
+  cmDtRC_t cmDataSetChar(      cmData_t* p, char v );
239
+  cmDtRC_t cmDataSetUChar(     cmData_t* p, unsigned char v );
240
+  cmDtRC_t cmDataSetShort(     cmData_t* p, short v );
241
+  cmDtRC_t cmDataSetUShort(    cmData_t* p, unsigned short v );
242
+  cmDtRC_t cmDataSetInt(       cmData_t* p, int v );
243
+  cmDtRC_t cmDataSetUInt(      cmData_t* p, unsigned int v );
244
+  cmDtRC_t cmDataSetLong(      cmData_t* p, long v );
245
+  cmDtRC_t cmDataSetULong(     cmData_t* p, unsigned long v );
246
+  cmDtRC_t cmDataSetFloat(     cmData_t* p, float v );
247
+  cmDtRC_t cmDataSetDouble(    cmData_t* p, double v );
248
+  cmDtRC_t cmDataSetStr(       cmData_t* p, unsigned flags, cmChar_t* s );
249
+  cmDtRC_t cmDataSetConstStr(  cmData_t* p, unsigned flags, const cmChar_t* s );
250
+  cmDtRC_t cmDataSetStrN(      cmData_t* p, unsigned flags, cmChar_t* s, unsigned charCnt );
251
+  cmDtRC_t cmDataSetConstStrN( cmData_t* p, unsigned flags, const cmChar_t* s, unsigned charCnt );
252
+  cmDtRC_t cmDataSetBlob(      cmData_t* p, unsigned flags, void* v, unsigned byteCnt );
253
+  cmDtRC_t cmDataSetConstBlob( cmData_t* p, unsigned flags, const void* v, unsigned byteCnt );
254
+
255
+  // Get the value of an object. No conversion is applied the
256
+  // type must match exactly or an error is generated.
257
+  cmDtRC_t cmDataChar(      const cmData_t* p, char* v );
258
+  cmDtRC_t cmDataUChar(     const cmData_t* p, unsigned char* v );
259
+  cmDtRC_t cmDataShort(     const cmData_t* p, short* v );
260
+  cmDtRC_t cmDataUShort(    const cmData_t* p, unsigned short* v );
261
+  cmDtRC_t cmDataInt(       const cmData_t* p, int* v );
262
+  cmDtRC_t cmDataUInt(      const cmData_t* p, unsigned int* v );
263
+  cmDtRC_t cmDataLong(      const cmData_t* p, long* v );
264
+  cmDtRC_t cmDataULong(     const cmData_t* p, unsigned long* v );
265
+  cmDtRC_t cmDataFloat(     const cmData_t* p, float* v );
266
+  cmDtRC_t cmDataDouble(    const cmData_t* p, double* v );
267
+  cmDtRC_t cmDataStr(       const cmData_t* p, cmChar_t** v );
268
+  cmDtRC_t cmDataConstStr(  const cmData_t* p, const cmChar_t** v );
269
+  cmDtRC_t cmDataBlob(      const cmData_t* p, cmChar_t** v, unsigned* byteCntRef );
270
+  cmDtRC_t cmDataConstBlob( const cmData_t* p, const cmChar_t** v, unsigned* byteCntRef );
207 271
 
208 272
   // Get the value of an object with conversion.
209 273
   cmDtRC_t cmDataGetChar(      const cmData_t* p, char* v );
@@ -217,125 +281,96 @@ extern "C" {
217 281
   cmDtRC_t cmDataGetFloat(     const cmData_t* p, float* v );
218 282
   cmDtRC_t cmDataGetDouble(    const cmData_t* p, double* v );
219 283
 
220
-  // Returns the pointer - does not copy the data.
221
-  cmDtRC_t cmDataGetStr(       const cmData_t* p, char** v );
222
-  cmDtRC_t cmDataGetConstStr(  const cmData_t* p, const char** v );
223
-  cmDtRC_t cmDataGetVoidPtr(   const cmData_t* p, void** v );
224
-  cmDtRC_t cmDataGetCharPtr(   const cmData_t* p, char** v );
225
-  cmDtRC_t cmDataGetUCharPtr(  const cmData_t* p, unsigned char** v );
226
-  cmDtRC_t cmDataGetShortPtr(  const cmData_t* p, short** v );
227
-  cmDtRC_t cmDataGetUShortPtr( const cmData_t* p, unsigned short** v );
228
-  cmDtRC_t cmDataGetIntPtr(    const cmData_t* p, int** v );
229
-  cmDtRC_t cmDataGetUIntPtr(   const cmData_t* p, unsigned int** v );
230
-  cmDtRC_t cmDataGetLongPtr(   const cmData_t* p, long** v );
231
-  cmDtRC_t cmDataGetULongPtr(  const cmData_t* p, unsigned long** v );
232
-  cmDtRC_t cmDataGetFloatPtr(  const cmData_t* p, float** v );
233
-  cmDtRC_t cmDataGetDoublePtr( const cmData_t* p, double** v );
234
-
235
-
236
-  // Set the value and type of an existing scalar object. 
284
+
285
+  //----------------------------------------------------------------------------
286
+  // Array related functions
287
+  //
288
+
289
+  // Notes:
290
+  // 1) string arrays are arrays of string pointers.
291
+  // 2) blob arrays (array of void pointers) are not supported because
292
+  //    there is no direct way to determine the length of each blob
293
+  //    and therefore they cannot be internally duplicated - a special scheme
294
+  //    could be devised (length goes in first 4 bytes) to make this 
295
+  //    work but we will defer that until the need arises.
296
+
297
+  //
298
+  // Dynamically allocate a new array data object.
299
+  //
300
+  // eleCnt referes to the number of elements in the array pointed
301
+  // to by 'vp'.  The number of bytes pointed to by 'vp' is then
302
+  // cmDataByteWidth(tid)*eleCnt.
303
+  //
304
+  // If no flags are set then the array pointed to by 'vp' is reallocated
305
+  // and kDataFreeDtFl is set.
306
+  //
307
+  // If kFreeValueDtFl is set then the object will take responsibility for
308
+  // releasing the memory pointed to by 'vp' when the object is destroyed
309
+  // or the array is reassigned.  
310
+  //
311
+  // If kNoCopyDtFl is set then 'vp' becomes the internal array
312
+  // value (vp[cnt]) is NOT reallocated). In this case the client is
313
+  // responsibile for eventually releasing the associated memory - when
314
+  // the data object is no longer valid.
315
+  cmDtRC_t cmDataNewArray(  cmData_t* parent, cmDataTypeId_t tid, void* vp, unsigned eleCnt, unsigned flags, cmData_t** ref );
316
+
317
+  cmDtRC_t cmDataNewCharArray(     cmData_t* parent, char* v,           unsigned eleCnt, unsigned flags, cmData_t** ref );
318
+  cmDtRC_t cmDataNewUCharArray(    cmData_t* parent, unsigned char* v,  unsigned eleCnt, unsigned flags, cmData_t** ref );
319
+  cmDtRC_t cmDataNewShortArray(    cmData_t* parent, short* v,          unsigned eleCnt, unsigned flags, cmData_t** ref );
320
+  cmDtRC_t cmDataNewUShortArray(   cmData_t* parent, unsigned short* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
321
+  cmDtRC_t cmDataNewIntArray(      cmData_t* parent, int* v,            unsigned eleCnt, unsigned flags, cmData_t** ref );
322
+  cmDtRC_t cmDataNewUIntArray(     cmData_t* parent, unsigned int* v,   unsigned eleCnt, unsigned flags, cmData_t** ref );
323
+  cmDtRC_t cmDataNewLongArray(     cmData_t* parent, long* v,           unsigned eleCnt, unsigned flags, cmData_t** ref );
324
+  cmDtRC_t cmDataNewULongArray(    cmData_t* parent, unsigned long* v,  unsigned eleCnt, unsigned flags, cmData_t** ref );
325
+  cmDtRC_t cmDataNewFloatArray(    cmData_t* parent, float* v,          unsigned eleCnt, unsigned flags, cmData_t** ref );
326
+  cmDtRC_t cmDataNewDoubleArray(   cmData_t* parent, double* v,         unsigned eleCnt, unsigned flags, cmData_t** ref );
327
+  cmDtRC_t cmDataNewStrArray(      cmData_t* parent, cmChar_t** v,      unsigned eleCnt, unsigned flags, cmData_t** ref );
328
+  cmDtRC_t cmDataNewConstStrArray( cmData_t* parent, const cmChar_t** v,unsigned eleCnt, unsigned flags, cmData_t** ref );
329
+
330
+  // Set the value and type of an existing scalar object.
331
+  //
237 332
   // These functions begin by releasing any resources held by *p
238 333
   // prior to resetting the type and value of the object.
239
-  cmData_t* cmDataSetNull(      cmData_t* p );
240
-  cmData_t* cmDataSetChar(      cmData_t* p, char v );
241
-  cmData_t* cmDataSetUChar(     cmData_t* p, unsigned char v );
242
-  cmData_t* cmDataSetShort(     cmData_t* p, short v );
243
-  cmData_t* cmDataSetUShort(    cmData_t* p, unsigned short v );
244
-  cmData_t* cmDataSetInt(       cmData_t* p, int v );
245
-  cmData_t* cmDataSetUInt(      cmData_t* p, unsigned int v );
246
-  cmData_t* cmDataSetLong(      cmData_t* p, long v );
247
-  cmData_t* cmDataSetULong(     cmData_t* p, unsigned long v );
248
-  cmData_t* cmDataSetFloat(     cmData_t* p, float v );
249
-  cmData_t* cmDataSetDouble(    cmData_t* p, double v );
250
-  cmData_t* cmDataSetStr(       cmData_t* p, cmChar_t* s );
251
-  cmData_t* cmDataSetConstStr(  cmData_t* p, const cmChar_t* s );
252
-
253
-  // Set the type and value of an existing data object to an external array.
254
-  // These functions begin by releasing any resources help by *p.
255
-  // The array pointed to by 'vp' is not copied or duplicated.
256
-  // 'vp' is simply assigned as the data space for the object and therefore must remain
257
-  // valid for the life of the object.
258
-  cmData_t* cmDataSetVoidPtr(   cmData_t* p, void* vp,           unsigned cnt );
259
-  cmData_t* cmDataSetCharPtr(   cmData_t* p, char* vp,           unsigned cnt );
260
-  cmData_t* cmDataSetUCharPtr(  cmData_t* p, unsigned char* vp,  unsigned cnt );
261
-  cmData_t* cmDataSetShortPtr(  cmData_t* p, short* vp,          unsigned cnt );
262
-  cmData_t* cmDataSetUShortPtr( cmData_t* p, unsigned short* vp, unsigned cnt );
263
-  cmData_t* cmDataSetIntPtr(    cmData_t* p, int* vp,            unsigned cnt );
264
-  cmData_t* cmDataSetUIntPtr(   cmData_t* p, unsigned int* vp,   unsigned cnt );
265
-  cmData_t* cmDataSetLongPtr(   cmData_t* p, long* vp,           unsigned cnt );
266
-  cmData_t* cmDataSetULongPtr(  cmData_t* p, unsigned long* vp,  unsigned cnt );
267
-  cmData_t* cmDataSetFloatPtr(  cmData_t* p, float* vp,          unsigned cnt );
268
-  cmData_t* cmDataSetDoublePtr( cmData_t* p, double* vp,         unsigned cnt );
269
-
270
-  // Set the value of an existing array based data object. 
271
-  // These functions begin by releasing any resources help by *p
272
-  // and then dynamically allocate the internal array and copy 
273
-  // the array data into it.
274
-  cmData_t* cmDataSetStrAlloc(       cmData_t* p, const cmChar_t* s );
275
-  cmData_t* cmDataSetConstStrAlloc(  cmData_t* p, const cmChar_t* s );
276
-  cmData_t* cmDataSetVoidAllocPtr(   cmData_t* p, const void* vp,           unsigned cnt );
277
-  cmData_t* cmDataSetCharAllocPtr(   cmData_t* p, const char* vp,           unsigned cnt );
278
-  cmData_t* cmDataSetUCharAllocPtr(  cmData_t* p, const unsigned char* vp,  unsigned cnt );
279
-  cmData_t* cmDataSetShortAllocPtr(  cmData_t* p, const short* vp,          unsigned cnt );
280
-  cmData_t* cmDataSetUShortAllocPtr( cmData_t* p, const unsigned short* vp, unsigned cnt );
281
-  cmData_t* cmDataSetIntAllocPtr(    cmData_t* p, const int* vp,            unsigned cnt );
282
-  cmData_t* cmDataSetUIntAllocPtr(   cmData_t* p, const unsigned int* vp,   unsigned cnt );
283
-  cmData_t* cmDataSetLongAllocPtr(   cmData_t* p, const long* vp,           unsigned cnt );
284
-  cmData_t* cmDataSetULongAllocPtr(  cmData_t* p, const unsigned long* vp,  unsigned cnt );
285
-  cmData_t* cmDataSetFloatAllocPtr(  cmData_t* p, const float* vp,          unsigned cnt );
286
-  cmData_t* cmDataSetDoubleAllocPtr( cmData_t* p, const double* vp,         unsigned cnt );
334
+  // The 'flags' argument may include kConstValueDtFl, kConstObjDtFl,
335
+  // kNoCopyDtFl and the kFreeValueDtFl.
336
+
337
+  // Generic set array functions. 'vp' is assumed to point to an array 
338
+  // of the type defined by 'tid'.
339
+  cmDtRC_t cmDataSetArrayValue(  cmData_t* dt, cmDataTypeId_t tid, void* vp, unsigned eleCnt, unsigned flags );
340
+
341
+  // Type sepctific set array functions.
342
+  cmDtRC_t cmDataSetCharArray(   cmData_t* d, char* v,           unsigned eleCnt, unsigned flags );
343
+  cmDtRC_t cmDataSetUCharArray(  cmData_t* d, unsigned char* v,  unsigned eleCnt, unsigned flags );
344
+  cmDtRC_t cmDataSetShortArray(  cmData_t* d, short* v,          unsigned eleCnt, unsigned flags );
345
+  cmDtRC_t cmDataSetUShortArray( cmData_t* d, unsigned short* v, unsigned eleCnt, unsigned flags );
346
+  cmDtRC_t cmDataSetIntArray(    cmData_t* d, int* v,            unsigned eleCnt, unsigned flags );
347
+  cmDtRC_t cmDataSetUIntArray(   cmData_t* d, unsigned int* v,   unsigned eleCnt, unsigned flags );
348
+  cmDtRC_t cmDataSetLongArray(   cmData_t* d, long* v,           unsigned eleCnt, unsigned flags );
349
+  cmDtRC_t cmDataSetULongArray(  cmData_t* d, unsigned long* v,  unsigned eleCnt, unsigned flags );
350
+  cmDtRC_t cmDataSetFloatArray(  cmData_t* d, float* v,          unsigned eleCnt, unsigned flags );
351
+  cmDtRC_t cmDataSetDoubleArray( cmData_t* d, double* v,         unsigned eleCnt, unsigned flags );
352
+  cmDtRC_t cmDataSetStrArray(    cmData_t* d, cmChar_t** v,      unsigned eleCnt, unsigned flags );
353
+  cmDtRC_t cmDataSetConstStrArray(cmData_t* d,const cmChar_t** v,unsigned eleCnt, unsigned flags );
354
+
355
+  // Return the count of elements in a n array.
356
+  unsigned cmDataArrayEleCount( const cmData_t* d );
357
+
358
+  // Get a pointer to the base of an array. 
359
+  // The type must match exactly or an error is generated.
360
+  // Use cmDataEleCount() to determine the number of elements in the array.
361
+  cmDtRC_t cmDataCharArray(      const cmData_t* d, char** v );
362
+  cmDtRC_t cmDataUCharArray(     const cmData_t* d, unsigned char** v );
363
+  cmDtRC_t cmDataShortArray(     const cmData_t* d, short** v );
364
+  cmDtRC_t cmDataUShortArray(    const cmData_t* d, unsigned short** v );
365
+  cmDtRC_t cmDataIntArray(       const cmData_t* d, int** v );
366
+  cmDtRC_t cmDataUIntArray(      const cmData_t* d, unsigned int** v );
367
+  cmDtRC_t cmDataLongArray(      const cmData_t* d, long** v );
368
+  cmDtRC_t cmDataULongArray(     const cmData_t* d, unsigned long** v );
369
+  cmDtRC_t cmDataFloatArray(     const cmData_t* d, float** v );
370
+  cmDtRC_t cmDataDoubleArray(    const cmData_t* d, double** v );
371
+  cmDtRC_t cmDataStrArray(       const cmData_t* d, cmChar_t*** v );
372
+  cmDtRC_t cmDataConstStrArray(  const cmData_t* d, const cmChar_t*** v );
287 373
   
288
-
289
-  // Dynamically allocate a data object and set it's value.
290
-  cmData_t* cmDataAllocNull(   cmData_t* parent );
291
-  cmData_t* cmDataAllocChar(   cmData_t* parent, char v );
292
-  cmData_t* cmDataAllocUChar(  cmData_t* parent, unsigned char v );
293
-  cmData_t* cmDataAllocShort(  cmData_t* parent, short v );
294
-  cmData_t* cmDataAllocUShort( cmData_t* parent, unsigned short v );
295
-  cmData_t* cmDataAllocInt(    cmData_t* parent, int v );
296
-  cmData_t* cmDataAllocUInt(   cmData_t* parent, unsigned int v );
297
-  cmData_t* cmDataAllocLong(   cmData_t* parent, long v );
298
-  cmData_t* cmDataAllocULong(  cmData_t* parent, unsigned long v );
299
-  cmData_t* cmDataAllocFloat(  cmData_t* parent, float v );
300
-  cmData_t* cmDataAllocDouble( cmData_t* parent, double v );
301
-
302
-  // Dynamically allocate a data object and set its array value to an external
303
-  // array. v[cnt] is assigned as the internal data space for the object and 
304
-  // therefore must remain valid for the life of the object. 
305
-  // See the cmDataXXXAlocPtr() for equivalent functions which dynamically 
306
-  // allocate the intenal data space.
307
-  cmData_t* cmDataAllocStr(       cmData_t* parent, cmChar_t* str );
308
-  cmData_t* cmDataAllocConstStr(  cmData_t* parent, const cmChar_t* str );
309
-  cmData_t* cmDataAllocCharPtr(   cmData_t* parent, char* v,           unsigned cnt );
310
-  cmData_t* cmDataAllocUCharPtr(  cmData_t* parent, unsigned char* v,  unsigned cnt );
311
-  cmData_t* cmDataAllocShortPtr(  cmData_t* parent, short* v,          unsigned cnt );
312
-  cmData_t* cmDataAllocUShortPtr( cmData_t* parent, unsigned short* v, unsigned cnt );
313
-  cmData_t* cmDataAllocIntPtr(    cmData_t* parent, int* v,            unsigned cnt );
314
-  cmData_t* cmDataAllocUIntPtr(   cmData_t* parent, unsigned int* v,   unsigned cnt );
315
-  cmData_t* cmDataAllocLongPtr(   cmData_t* parent, long* v,           unsigned cnt );
316
-  cmData_t* cmDataAllocULongPtr(  cmData_t* parent, unsigned long* v,  unsigned cnt );
317
-  cmData_t* cmDataAllocFloatPtr(  cmData_t* parent, float* v,          unsigned cnt );
318
-  cmData_t* cmDataAllocDoublePtr( cmData_t* parent, double* v,         unsigned cnt );
319
-  cmData_t* cmDataAllocVoidPtr(   cmData_t* parent, void* v,           unsigned cnt );
320
-
321
-
322
-  // Dynamically allocate a data object and its array value.  
323
-  // These functions dynamically allocate the internal array data space
324
-  // and copy v[cnt] into it.
325
-  cmData_t* cmDataStrAlloc(       cmData_t* parent, cmChar_t* str );
326
-  cmData_t* cmDataConstStrAlloc(  cmData_t* parent, const cmChar_t* str );
327
-  cmData_t* cmDataCharAllocPtr(   cmData_t* parent, const char* v,           unsigned cnt );
328
-  cmData_t* cmDataUCharAllocPtr(  cmData_t* parent, const unsigned char* v,  unsigned cnt );
329
-  cmData_t* cmDataShortAllocPtr(  cmData_t* parent, const short* v,          unsigned cnt );
330
-  cmData_t* cmDataUShortAllocPtr( cmData_t* parent, const unsigned short* v, unsigned cnt );
331
-  cmData_t* cmDataIntAllocPtr(    cmData_t* parent, const int* v,            unsigned cnt );
332
-  cmData_t* cmDataUIntAllocPtr(   cmData_t* parent, const unsigned int* v,   unsigned cnt );
333
-  cmData_t* cmDataLongAllocPtr(   cmData_t* parent, const long* v,           unsigned cnt );
334
-  cmData_t* cmDataULongAllocPtr(  cmData_t* parent, const unsigned long* v,  unsigned cnt );
335
-  cmData_t* cmDataFloatAllocPtr(  cmData_t* parent, const float* v,          unsigned cnt );
336
-  cmData_t* cmDataDoubleAllocPtr( cmData_t* parent, const double* v,         unsigned cnt );
337
-  cmData_t* cmDataVoidAllocPtr(   cmData_t* parent, const void* v,           unsigned cnt );
338
-
339 374
   //----------------------------------------------------------------------------
340 375
   // Structure related functions
341 376
   //
@@ -428,6 +463,7 @@ extern "C" {
428 463
   cmData_t* cmDataAllocPairId(    cmData_t* parent, unsigned  keyId,       cmData_t* value );
429 464
 
430 465
   // Dynamically allocate the label but link (w/o realloc) the value.
466
+  cmData_t* cmDataAllocPairLabelN(cmData_t* parent, const cmChar_t* label, unsigned charCnt, cmData_t* value);
431 467
   cmData_t* cmDataAllocPairLabel( cmData_t* parent, const cmChar_t* label, cmData_t* value );
432 468
 
433 469
   //----------------------------------------------------------------------------
@@ -445,15 +481,15 @@ extern "C" {
445 481
 
446 482
 
447 483
   // Var-args fmt:
448
-  // <typeId> <value> {<cnt>}
484
+  // <contId> {<typeId>} <value> {<cnt>}
449 485
   // scalar types: <value> is literal,<cnt>   is not included
450 486
   //     null has no <value> or <cnt>
451
-  // ptr    types: <value> is pointer,<cnt>   is element count
452
-  // struct types: <value> is cmData_t, <cnt> is not included
487
+  // array  types: <value> is pointer,<cnt>   is element count
488
+  // struct types: <value> is cmData_t, <typeId> and <cnt> is not included
453 489
   // Indicate the end of argument list by setting  <typeId> to kInvalidDtId. 
454 490
   // The memory for array based data types is dynamically allocated.
455
-  cmData_t* cmDataListAllocV(cmData_t* parent, va_list vl );
456
-  cmData_t* cmDataListAllocA(cmData_t* parent,  ... );
491
+  cmRC_t cmDataListAllocV(cmData_t* parent, cmData_t** ref, va_list vl );
492
+  cmRC_t  cmDataListAllocA(cmData_t* parent,  cmData_t** ref, ... );
457 493
   
458 494
   // Returns a ptr to 'ele'.
459 495
   cmData_t* cmDataListAppendEle( cmData_t* p, cmData_t* ele );
@@ -464,9 +500,6 @@ extern "C" {
464 500
   cmData_t* cmDataListInsertEle( cmData_t* p, unsigned index, cmData_t* ele );
465 501
   cmData_t* cmDataListInsertEleN(cmData_t* p, unsigned index, cmData_t* ele[], unsigned n );
466 502
  
467
-  cmData_t* cmDataListUnlink( cmData_t* p, unsigned index );
468
-  cmData_t* cmDataListFree(   cmData_t* p, unsigned index );
469
-
470 503
   //----------------------------------------------------------------------------
471 504
   // Record related functions
472 505
   //
@@ -487,17 +520,17 @@ extern "C" {
487 520
   unsigned        cmDataRecdKeyId(    cmData_t* p, unsigned index );
488 521
   const cmChar_t* cmDataRecdKeyLabel( cmData_t* p, unsigned index );
489 522
   
490
-  cmData_t*       cmRecdMake( cmData_t* parent, cmData_t* p );
491
-  cmData_t*       cmRecdAlloc( cmData_t* parent );
523
+  cmData_t*       cmDataRecdMake( cmData_t* parent, cmData_t* p );
524
+  cmData_t*       cmDataRecdAlloc( cmData_t* parent );
492 525
   
493 526
   // Append a pair node by linking the pair node 'pair' to the record node 'p'.
494 527
   // 'pair' is simply linked to 'p' via cmDataAppendChild() no 
495 528
   // reallocation or duplicattion takes place.
496
-  cmData_t*       cmRecdAppendPair( cmData_t* p, cmData_t* pair );
529
+  cmData_t*       cmDataRecdAppendPair( cmData_t* p, cmData_t* pair );
497 530
 
498 531
 
499 532
   // Var-args format:
500
-  // <label|id> <typeId>  <value> {<cnt>}
533
+  // <label|id> {<cid>} <typeId>  <value> {<cnt>}
501 534
   // scalar types: <value> is literal,<cnt> is not included
502 535
   // null   type: has no <value> or <cnt>
503 536
   // ptr    types: <value> is pointer,  <cnt> is element count
@@ -529,13 +562,28 @@ extern "C" {
529 562
   unsigned cmDataSerializeByteCount( const cmData_t* p );
530 563
   cmDtRC_t cmDataSerialize(   const cmData_t* p, void* buf, unsigned bufByteCnt );
531 564
   cmDtRC_t cmDataDeserialize( const void* buf, unsigned bufByteCnt, cmData_t** pp );
565
+
566
+  //-----------------------------------------------------------------------------
567
+  typedef cmHandle_t cmDataParserH_t;
568
+  //static cmDataParserH_t cmDataParserNullHandle;
569
+
570
+  cmDtRC_t cmDataParserCreate( cmCtx_t* ctx, cmDataParserH_t* hp );
571
+  cmDtRC_t cmDataParserDestroy( cmDataParserH_t* hp );
572
+  bool     cmDataParserIsValid( cmDataParserH_t h );
573
+
574
+  // Parse a text representation into a 'record' type. 
575
+  // Note that the text is wrapped with implied curly braces 
576
+  // (e.g. "{ text }").  The contents of the text should therefore
577
+  // fit the record syntax (e.g. the first token should be a 
578
+  // 'pair' label.
579
+  cmDtRC_t cmDataParserExec(   cmDataParserH_t  h, const cmChar_t* text, cmData_t** pp );
580
+  //-----------------------------------------------------------------------------
532 581
   
533 582
   void     cmDataPrint( const cmData_t* p, cmRpt_t* rpt );
534 583
   
535 584
   void     cmDataTest( cmCtx_t* ctx );
536 585
 
537 586
 
538
-
539 587
 #ifdef __cplusplus
540 588
 }
541 589
 #endif

+ 4
- 0
cmGrPage.h Vedi File

@@ -60,7 +60,11 @@ extern "C" {
60 60
   // Draw the page.
61 61
   void      cmGrPageDraw( cmGrPgH_t h, cmGrDcH_t dcH );
62 62
 
63
+  // Label callback functions are used to translate numeric axis values to
64
+  // text strings.  Multiple label callback functions can be registered with
65
+  // a page and then assigned to a given view axis via cmGrViewSetLabelFunc().
63 66
   typedef void (*cmGrLabelFunc_t)( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value );
67
+
64 68
   // Returns id of the new page label function.
65 69
   unsigned         cmGrPageLabelFuncRegister( cmGrPgH_t h, cmGrLabelFunc_t func, void* arg, const cmChar_t* label );      
66 70
   unsigned         cmGrPageLabelFuncCount(    cmGrPgH_t h );

+ 84
- 89
cmLex.c Vedi File

@@ -7,6 +7,12 @@
7 7
 #include "cmMallocDebug.h"
8 8
 #include "cmFile.h"
9 9
 
10
+enum
11
+{
12
+  kRealFloatLexFl   = 0x01,
13
+  kIntUnsignedLexFl = 0x02
14
+};
15
+
10 16
 typedef struct
11 17
 {
12 18
   unsigned        code;
@@ -29,6 +35,7 @@ cmLexErrorRecd cmLexErrorArray[] =
29 35
   { kMemAllocErrLexRC,     "An attempted memory allocation failed"},
30 36
   { kEofRC,                "The end of the input text was encountered (this is a normal condition not an error)"},
31 37
   { kInvalidLexTIdLexRC,   "An invalid token id was encountered."},
38
+  { kSignErrorLexRC,       "A signed integer has a 'u' or 'U' suffix."},
32 39
   { kInvalidLexRC,         "Unknown lexer error code." }
33 40
 };
34 41
 
@@ -75,6 +82,7 @@ typedef struct cmLex_str
75 82
 
76 83
   cmChar_t*         textBuf;         // text buf used by cmLexSetFile()
77 84
 
85
+  unsigned          attrFlags;       // used to store the int and real suffix type flags
78 86
 } cmLex;
79 87
 
80 88
 
@@ -148,7 +156,7 @@ unsigned _cmLexRealMatcher(  cmLex* p, const cmChar_t* cp, unsigned cn, const cm
148 156
   unsigned i  = 0;
149 157
   unsigned n  = 0;     // decimal point counter
150 158
   unsigned d  = 0;     // digit counter
151
-  bool     fl = false; // true if this real includes an exponent
159
+  bool     fl = false; // expo flag  
152 160
 
153 161
   for(; i<cn && n<=1; ++i)
154 162
   {
@@ -170,10 +178,12 @@ unsigned _cmLexRealMatcher(  cmLex* p, const cmChar_t* cp, unsigned cn, const cm
170 178
   // if there was at least one digit and the next char is an 'e'
171 179
   if( d>0 && i<cn && (cp[i] == 'e' || cp[i] == 'E') )
172 180
   {
173
-    d=0;
181
+    unsigned e=0;
174 182
     ++i;
175 183
     unsigned j = i;
176 184
 
185
+    fl = false;
186
+
177 187
     for(; i<cn; ++i)
178 188
     {
179 189
       if( i==j && cp[i]=='-' ) // allow the char following the e to be '-'
@@ -181,6 +191,7 @@ unsigned _cmLexRealMatcher(  cmLex* p, const cmChar_t* cp, unsigned cn, const cm
181 191
 
182 192
       if( isdigit(cp[i]) )
183 193
       {
194
+        ++e;
184 195
         ++d;
185 196
         continue;
186 197
       }
@@ -190,17 +201,42 @@ unsigned _cmLexRealMatcher(  cmLex* p, const cmChar_t* cp, unsigned cn, const cm
190 201
     }
191 202
 
192 203
     // an exp exists if digits follwed the 'e'
193
-    fl = d > 0;
204
+    fl = e > 0;
194 205
      
195 206
   }
196 207
 
197
-  return i>1 && (n==1 || fl) ? i : 0;
208
+  // if at least one digit was found 
209
+  if( d>0 )
210
+  {
211
+    // Note that this path allows a string w/o a decimal pt to trigger a match.
212
+
213
+    if(i<cn)
214
+    {
215
+      // if the real has a suffix
216
+      switch(cp[i])
217
+      {
218
+        case 'F':
219
+        case 'f':
220
+          p->attrFlags = cmSetFlag(p->attrFlags,kRealFloatLexFl);
221
+          ++i;
222
+          break;
223
+      }
224
+
225
+    }
226
+    
227
+    // match w/o suffix return
228
+    if( d>0 && (fl || n==1 || cmIsFlag(p->attrFlags,kRealFloatLexFl)) )
229
+      return i;
230
+  }
231
+
232
+  return 0; // no-match return
198 233
 }
199 234
 
200 235
 unsigned _cmLexIntMatcher(   cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
201 236
 {
202 237
   unsigned i = 0;
203 238
   bool signFl = false;
239
+
204 240
   for(; i<cn; ++i)
205 241
   {
206 242
     if( i==0 && cp[i]=='-' )
@@ -222,9 +258,35 @@ unsigned _cmLexIntMatcher(   cmLex* p, const cmChar_t* cp, unsigned cn, const cm
222 258
   //
223 259
   // The current implementation recognizes all numeric strings 
224 260
   // containing a decimal point as reals. 
225
- 
226 261
 
227
-  return signFl && i==1 ? 0 : i;
262
+  // if no integer was found
263
+  if( (signFl && i==0) || i==0 )
264
+    return 0;
265
+
266
+
267
+  // check for suffix
268
+  if(i<cn )
269
+  {
270
+    
271
+    switch(cp[i])
272
+    {
273
+      case 'u':
274
+      case 'U':
275
+        if( signFl )
276
+          _cmLexError(p,kSignErrorLexRC,"A signed integer has a 'u' or 'U' suffix.");
277
+        else
278
+        {
279
+          p->attrFlags = cmSetFlag(p->attrFlags,kIntUnsignedLexFl);          
280
+          ++i;
281
+        }
282
+        break;
283
+
284
+      default:
285
+        break;
286
+    }
287
+  }
288
+
289
+  return  i;
228 290
 }
229 291
 
230 292
 unsigned _cmLexHexMatcher(   cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
@@ -387,23 +449,6 @@ cmLexH cmLexInit( const cmChar_t* cp, unsigned cn, unsigned flags, cmRpt_t* rpt
387 449
   
388 450
   _cmLexSetTextBuffer( p, cp, cn );
389 451
 
390
-  /*
391
-  p->cp              = (cn==0)    ? NULL : cp;
392
-  p->cn              = (cp==NULL) ? 0    : cn;
393
-
394
-  p->ci              = 0;
395
-
396
-
397
-  p->curTokenId      = kErrorLexTId;
398
-  p->curTokenCharIdx = cmInvalidIdx;
399
-  p->curTokenCharCnt = 0;
400
-
401
-  p->curLine         = 0;
402
-  p->curCol          = 0;
403
-  p->nextLine        = 0;
404
-  p->nextCol         = 0;
405
-  */
406
-
407 452
   int init_mfn       = 10;
408 453
   p->mfp             = cmMemAllocZ( cmLexMatcher, init_mfn );
409 454
   p->mfn             = init_mfn;
@@ -537,70 +582,6 @@ cmRC_t cmLexSetFile( cmLexH h, const cmChar_t* fn )
537 582
   return rc;
538 583
 }
539 584
 
540
-/*
541
-cmRC_t cmLexSetFile( cmLexH h, const cmChar_t* fn )
542
-{
543
-  cmRC_t   rc      = kOkLexRC;
544
-  FILE*    fp      = NULL;
545
-  cmLex*   p       = _cmLexHandleToPtr(h);
546
-  unsigned n       = 0;
547
-
548
-  assert( fn != NULL && p != NULL );
549
-  
550
-  // open the file
551
-  if((fp = fopen(fn,"rb")) == NULL )
552
-    return _cmLexError(p,kFileOpenErrLexRC,"Unable to open the file:'%s'.",fn);
553
-
554
-  // seek to the end
555
-  if( fseek(fp,0,SEEK_END) != 0 )
556
-  {
557
-    rc= _cmLexError(p,kFileSeekErrLexRC,"Unable to seek to the end of '%s'.",fn);
558
-    goto errLabel;
559
-  }
560
-
561
-  // get the length of the file
562
-  if( (n=ftell(fp)) == 0 )
563
-  {
564
-    rc = _cmLexError(p,kFileOpenErrLexRC,"The file '%s' appears to be empty.",fn);
565
-    goto errLabel;
566
-  }
567
-
568
-  // rewind the file
569
-  if( fseek(fp,0,SEEK_SET) != 0 )
570
-  {
571
-    rc = _cmLexError(p,kFileSeekErrLexRC,"Unable to seek to the beginning of '%s'.",fn);
572
-    goto errLabel;
573
-  }
574
-
575
-  // allocate the text buffer
576
-  if((p->textBuf = cmMemResizeZ( char, p->textBuf, n+1)) == NULL )
577
-  {
578
-    rc = _cmLexError(p,kMemAllocErrLexRC,"Unable to allocate the text file buffer for:'%s'.",fn);
579
-    goto errLabel;
580
-  }
581
-
582
-  // read the file into the text buffer
583
-  if( fread(p->textBuf,n,1,fp) != 1 )
584
-  {
585
-    rc = _cmLexError(p,kFileReadErrLexRC,"File read failed on:'%s'.",fn);
586
-    goto errLabel;
587
-  }  
588
-
589
-  if((rc = _cmLexSetTextBuffer( p, p->textBuf, n )) != kOkLexRC )
590
-    goto errLabel;
591
-
592
- errLabel:
593
-
594
-  // close the file
595
-  if( fclose(fp) != 0 )
596
-  {
597
-    rc =  _cmLexError(p,kFileCloseErrLexRC,"File close failed on:'%s'.",fn);
598
-    goto errLabel;
599
-  }
600
-
601
-  return rc;
602
-}
603
-*/
604 585
 
605 586
 cmLexMatcher* _cmLexFindUserToken( cmLex* p, unsigned id, const cmChar_t* tokenStr )
606 587
 {
@@ -689,9 +670,9 @@ unsigned           cmLexGetNextToken( cmLexH h )
689 670
     p->curTokenId      = kErrorLexTId;
690 671
     p->curTokenCharIdx = cmInvalidIdx;
691 672
     p->curTokenCharCnt = 0;
673
+    p->attrFlags       = 0;
692 674
 
693
-
694
-    // try each mater
675
+    // try each matcher
695 676
     for(; mi<p->mfi; ++mi)
696 677
       if( p->mfp[mi].enableFl )
697 678
       {
@@ -701,6 +682,7 @@ unsigned           cmLexGetNextToken( cmLexH h )
701 682
         else
702 683
           charCnt = p->mfp[mi].userPtr( p->cp + p->ci, p->cn - p->ci);
703 684
 
685
+        // notice if the matcher set the error code
704 686
         if( cmErrLastRC(&p->err) != kOkLexRC )
705 687
           return kErrorLexTId;
706 688
 
@@ -823,6 +805,19 @@ float              cmLexTokenFloat(        cmLexH h )
823 805
 double             cmLexTokenDouble(        cmLexH h )
824 806
 {  return strtod( cmLexTokenText(h),NULL ); }
825 807
 
808
+
809
+bool               cmLexTokenIsUnsigned( cmLexH h )
810
+{
811
+  cmLex* p = _cmLexHandleToPtr(h);
812
+  return p->curTokenId == kIntLexTId && cmIsFlag(p->attrFlags,kIntUnsignedLexFl);
813
+}
814
+
815
+bool               cmLexTokenIsSinglePrecision( cmLexH h )
816
+{
817
+  cmLex* p = _cmLexHandleToPtr(h);
818
+  return p->curTokenId == kRealLexTId && cmIsFlag(p->attrFlags,kRealFloatLexFl);
819
+}
820
+
826 821
 unsigned cmLexCurrentLineNumber( cmLexH h )
827 822
 { 
828 823
   cmLex* p = _cmLexHandleToPtr(h);

+ 12
- 3
cmLex.h Vedi File

@@ -50,7 +50,8 @@ enum
50 50
   kMemAllocErrLexRC,       //< 10  An attempted memory allocation failed
51 51
   kEofRC,                  //< 11 The end of the input text was encountered (this is a normal condition not an error)
52 52
   kInvalidLexTIdLexRC,     //< 12 An invalid lex token id was encountered.
53
-  kInvalidLexRC            //< 13 Sentinal value.
53
+  kSignErrorLexRC,         //< 13 An signed integer has a 'u' or 'U' suffix."
54
+  kInvalidLexRC            //< 1r Sentinal value.
54 55
 
55 56
 };
56 57
 
@@ -119,15 +120,23 @@ unsigned           cmLexTokenCharCount(  cmLexH h );
119 120
 // Return the value of the current token as an integer.
120 121
 int                cmLexTokenInt( cmLexH h );
121 122
 
122
-// Return the value of the current token as an integer.
123
+// Return the value of the current token as an unsigned integer.
123 124
 unsigned           cmLexTokenUInt( cmLexH h );
124 125
 
125
-// Return the value of the current token as an integer.
126
+// Return the value of the current token as a float.
126 127
 float              cmLexTokenFloat( cmLexH h );
127 128
 
128 129
 // Return the value of the current token as a double.
129 130
 double             cmLexTokenDouble( cmLexH h );
130 131
 
132
+// Return true if the current token is an int and it was suffixed
133
+// with 'u' to indicate that it is unsigned.
134
+bool               cmLexTokenIsUnsigned( cmLexH h );
135
+
136
+// Return true if the current token is a real and it was suffexed 
137
+// with 'f' to indicate that it is a single precision float.
138
+bool               cmLexTokenIsSinglePrecision( cmLexH h );
139
+
131 140
 // Return the line number associated with the current token 
132 141
 unsigned           cmLexCurrentLineNumber( cmLexH h );
133 142
 

+ 1
- 1
cmMidiFile.h Vedi File

@@ -64,7 +64,7 @@ extern "C" {
64 64
   {
65 65
     unsigned                   uid;     // uid's are unique among all msg's in the file
66 66
     unsigned                   dtick;   // delta ticks
67
-    unsigned                   atick;   
67
+    unsigned                   atick;   // accumulated ticks
68 68
     cmMidiByte_t               status;  // ch msg's have the channel value removed (it is stored in u.chMsgPtr->ch)
69 69
     cmMidiByte_t               metaId;  //
70 70
     unsigned short             trkIdx;  //  

+ 353
- 0
cmProc4.c Vedi File

@@ -4135,3 +4135,356 @@ cmRC_t  cmScModulatorDump(  cmScModulator* p )
4135 4135
   
4136 4136
   return rc;
4137 4137
 }
4138
+
4139
+//=======================================================================================================================
4140
+cmRecdPlay*    cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs  )
4141
+{
4142
+  cmRecdPlay* op = cmObjAlloc(cmRecdPlay,c,p);
4143
+
4144
+  if( cmRecdPlayInit(op,srate,fragCnt,chCnt,initFragSecs,maxLaSecs,curLaSecs) != cmOkRC )
4145
+    cmRecdPlayFree(&op);
4146
+
4147
+  return op;
4148
+}
4149
+
4150
+cmRC_t         cmRecdPlayFree(  cmRecdPlay** pp )
4151
+{
4152
+  cmRC_t rc = cmOkRC;
4153
+  if( pp==NULL || *pp==NULL )
4154
+    return rc;
4155
+
4156
+  cmRecdPlay* p = *pp;
4157
+  if((rc = cmRecdPlayFinal(p)) != cmOkRC )
4158
+    return rc;
4159
+
4160
+  cmObjFree(pp);
4161
+  return rc;
4162
+
4163
+}
4164
+
4165
+cmRC_t cmRecdPlayInit(  cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs  )
4166
+{
4167
+  cmRC_t rc;
4168
+  unsigned i;
4169
+
4170
+  if( curLaSecs > maxLaSecs )
4171
+    return  cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The initial look-ahead time %f is greater than the maximum look-ahead time %f.",curLaSecs,maxLaSecs);    
4172
+
4173
+  if((rc = cmRecdPlayFinal(p)) != cmOkRC )
4174
+    return rc;
4175
+
4176
+  if( chCnt == 0 )
4177
+    return cmOkRC;
4178
+
4179
+  p->frags        = cmMemAllocZ(cmRecdPlayFrag,fragCnt);
4180
+  p->fragCnt      = fragCnt;
4181
+  p->srate        = srate;
4182
+  p->chCnt        = chCnt;
4183
+  p->initFragSecs = initFragSecs;
4184
+  p->maxLaSmpCnt  = floor(maxLaSecs*srate);
4185
+  p->curLaSmpCnt  = floor(curLaSecs*srate); 
4186
+  p->laChs        = cmMemAllocZ(cmSample_t*,chCnt);
4187
+  p->laSmpIdx     = 0;
4188
+
4189
+  for(i=0; i<chCnt; ++i)
4190
+    p->laChs[i] = cmMemAllocZ(cmSample_t,p->maxLaSmpCnt);
4191
+  
4192
+  return rc;
4193
+}
4194
+
4195
+cmRC_t         cmRecdPlayFinal( cmRecdPlay* p )
4196
+{ 
4197
+  unsigned i,j;
4198
+  // free the fragments
4199
+  for(i=0; i<p->fragCnt; ++i)
4200
+  {
4201
+    for(j=0; j<p->chCnt; ++j)
4202
+      cmMemFree(p->frags[i].chArray[j]);
4203
+
4204
+    cmMemFree(p->frags[i].chArray);
4205
+  }
4206
+
4207
+  // free the look-ahead buffers
4208
+  for(i=0; i<p->chCnt; ++i)
4209
+    cmMemFree(p->laChs[i]);
4210
+
4211
+  cmMemPtrFree(&p->laChs);
4212
+  cmMemPtrFree(&p->frags);
4213
+  p->fragCnt = 0;
4214
+  p->chCnt   = 0;
4215
+  p->rlist   = NULL;
4216
+  p->plist   = NULL;
4217
+  return cmOkRC;
4218
+}
4219
+
4220
+cmRC_t         cmRecdPlayRegisterFrag( cmRecdPlay* p,  unsigned fragIdx, unsigned labelSymId )
4221
+{
4222
+  assert( fragIdx < p->fragCnt );
4223
+
4224
+  unsigned i;
4225
+
4226
+  p->frags[ fragIdx ].labelSymId = labelSymId;
4227
+
4228
+  p->frags[ fragIdx ].chArray = cmMemResizeZ(cmSample_t*,p->frags[fragIdx].chArray,p->chCnt);
4229
+
4230
+  for(i=0; i<p->chCnt; ++i)
4231
+  {
4232
+    
4233
+    p->frags[ fragIdx ].allocCnt = floor(p->initFragSecs * p->srate);
4234
+    p->frags[ fragIdx ].chArray[i] = cmMemResizeZ(cmSample_t,p->frags[ fragIdx ].chArray[i],p->frags[fragIdx].allocCnt);
4235
+  }
4236
+
4237
+  return cmOkRC;
4238
+}
4239
+
4240
+cmRC_t         cmRecdPlayRewind( cmRecdPlay* p )
4241
+{
4242
+  unsigned i;
4243
+
4244
+  p->laSmpIdx = 0;
4245
+
4246
+  while( p->plist != NULL )
4247
+    cmRecdPlayEndPlay(p,p->plist->labelSymId);
4248
+  
4249
+  while( p->rlist != NULL )
4250
+    cmRecdPlayEndRecord(p,p->plist->labelSymId);
4251
+
4252
+  for(i=0; i<p->fragCnt; ++i)
4253
+    p->frags[i].playIdx = 0;
4254
+
4255
+  return cmOkRC;
4256
+}
4257
+
4258
+
4259
+cmRC_t         cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId )
4260
+{
4261
+  unsigned i;
4262
+
4263
+  for(i=0; i<p->fragCnt; ++i)
4264
+    if( p->frags[i].labelSymId == labelSymId )
4265
+    {
4266
+      // if the frag is not already on the recd list
4267
+      if( p->frags[i].rlink == NULL )
4268
+      {
4269
+        p->frags[i].recdIdx = 0;
4270
+        p->frags[i].playIdx = 0;
4271
+        p->frags[i].rlink   = p->rlist;
4272
+        p->rlist            = p->frags + i;
4273
+
4274
+        // handle LA buf longer than frag buf.
4275
+        int cpyCnt  = cmMin(p->curLaSmpCnt,p->frags[i].allocCnt); 
4276
+
4277
+         // go backwards in LA buf from newest sample to find init src offset
4278
+        int srcOffs = p->laSmpIdx - cpyCnt;
4279
+
4280
+        // if the src is before the first sample in the LA buf then wrap to end of buf
4281
+        if( srcOffs < 0 )
4282
+          srcOffs += p->maxLaSmpCnt; 
4283
+
4284
+        assert( 0 <= srcOffs && srcOffs < p->maxLaSmpCnt );
4285
+
4286
+        // cnt of samples to copy from LA buf (limited by end of LA buf)
4287
+        int n0 = cmMin(cpyCnt,p->maxLaSmpCnt - srcOffs); 
4288
+
4289
+        // if necessary wrap to begin of LA buf for remaining samples
4290
+        int n1 = cpyCnt>n0 ? n1 = cpyCnt-n0 : 0;
4291
+        int j;
4292
+
4293
+        assert(n0+n1 == cpyCnt );
4294
+
4295
+        for(j=0; j<p->chCnt; ++j)
4296
+          cmVOS_Copy(p->frags[i].chArray[j],n0,p->laChs[j]+srcOffs);
4297
+
4298
+        if( n1 > 0 )
4299
+        {
4300
+          for(j=0; j<p->chCnt; ++j)
4301
+            cmVOS_Copy(p->frags[i].chArray[j]+n0,n1,p->laChs[j]);
4302
+        }
4303
+
4304
+        p->frags[i].recdIdx = cpyCnt;
4305
+
4306
+      }
4307
+      
4308
+      return cmOkRC;
4309
+    }
4310
+
4311
+  return  cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'begin record'.",labelSymId);    
4312
+}
4313
+
4314
+cmRC_t         cmRecdPlayEndRecord(   cmRecdPlay* p, unsigned labelSymId )
4315
+{
4316
+  cmRecdPlayFrag* fp = p->rlist;
4317
+  cmRecdPlayFrag* pp = NULL;
4318
+
4319
+  for(; fp != NULL; fp=fp->rlink )
4320
+  {
4321
+    if( fp->labelSymId == labelSymId )
4322
+    {
4323
+      if( pp == NULL )
4324
+        p->rlist = fp->rlink;
4325
+      else
4326
+        pp->rlink = fp->rlink;
4327
+
4328
+      fp->rlink = NULL;
4329
+
4330
+      return cmOkRC;
4331
+    }
4332
+
4333
+    pp = fp;
4334
+  }
4335
+
4336
+  return  cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'end record'.",labelSymId);      
4337
+}
4338
+
4339
+cmRC_t         cmRecdPlayBeginPlay(   cmRecdPlay* p, unsigned labelSymId )
4340
+{
4341
+  unsigned i;
4342
+
4343
+  for(i=0; i<p->fragCnt; ++i)
4344
+    if( p->frags[i].labelSymId == labelSymId )
4345
+    {
4346
+      // if the frag is not already on the play list
4347
+      if( p->frags[i].plink == NULL )
4348
+      {
4349
+        p->frags[i].playIdx      = 0;
4350
+        p->frags[i].fadeSmpIdx   = 0;
4351
+        p->frags[i].fadeDbPerSec = 0.0;
4352
+        p->frags[i].plink        = p->plist;
4353
+        p->plist                 = p->frags + i;
4354
+      }
4355
+
4356
+      return cmOkRC;
4357
+    }
4358
+
4359
+  return  cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'begin play'.",labelSymId);    
4360
+
4361
+}
4362
+
4363
+cmRC_t         cmRecdPlayEndPlay(     cmRecdPlay* p, unsigned labelSymId )
4364
+{
4365
+  cmRecdPlayFrag* fp = p->plist;
4366
+  cmRecdPlayFrag* pp = NULL;
4367
+
4368
+  for(; fp != NULL; fp=fp->plink )
4369
+  {
4370
+    if( fp->labelSymId == labelSymId )
4371
+    {
4372
+      if( pp == NULL )
4373
+        p->plist = fp->plink;
4374
+      else
4375
+        pp->plink = fp->plink;
4376
+
4377
+      fp->plink = NULL;
4378
+
4379
+      return cmOkRC;
4380
+    }
4381
+
4382
+    pp = fp;
4383
+  }
4384
+
4385
+  return  cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'end play'.",labelSymId);    
4386
+}
4387
+
4388
+cmRC_t cmRecdPlayBeginFade(   cmRecdPlay* p, unsigned labelSymId, double fadeDbPerSec )
4389
+{
4390
+  cmRecdPlayFrag* fp = p->plist;
4391
+
4392
+  for(; fp != NULL; fp=fp->plink )
4393
+    if( fp->labelSymId == labelSymId )
4394
+    {
4395
+      fp->fadeDbPerSec = -fabs(fadeDbPerSec);
4396
+      return cmOkRC;
4397
+    }
4398
+  
4399
+  return  cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'fade begin'.",labelSymId);      
4400
+}
4401
+
4402
+
4403
+cmRC_t         cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_t** oChs, unsigned chCnt, unsigned smpCnt )
4404
+{
4405
+  unsigned i;
4406
+
4407
+  chCnt = cmMin(chCnt, p->chCnt);
4408
+
4409
+  //-------------------------------------------------------------------
4410
+  // copy incoming audio into the look-head buffers
4411
+  //
4412
+
4413
+  // if the number of incoming samples is longer than the look-head buffer
4414
+  // then copy exactly maxLaSmpCnt samples from the end of the incoming sample
4415
+  // buffer to the look-ahead buffer.
4416
+  unsigned srcOffs   = 0;
4417
+  unsigned srcSmpCnt = smpCnt;
4418
+  if( srcSmpCnt > p->maxLaSmpCnt )
4419
+  {
4420
+    // advance incoming sample buffer so that there are maxLaSmpCnt samples remaining
4421
+    srcOffs   = smpCnt-p->maxLaSmpCnt; 
4422
+    srcSmpCnt = p->maxLaSmpCnt;        // decrease the total samples to copy  
4423
+  }
4424
+
4425
+  // count of samples from cur posn to end of the LA buffer.
4426
+  unsigned          n0  = cmMin(srcSmpCnt, p->maxLaSmpCnt - p->laSmpIdx );
4427
+
4428
+  // count of samples past the end of the LA buffer to be wrapped into begin of buffer
4429
+  unsigned          n1  = srcSmpCnt>n0 ? srcSmpCnt-n0 : 0;
4430
+
4431
+  assert(n0+n1 == srcSmpCnt);
4432
+
4433
+  // copy first block to end of LA buffer
4434
+  for(i=0; i<chCnt; ++i)
4435
+    cmVOS_Copy(p->laChs[i]+p->laSmpIdx,n0,iChs[i] + srcOffs);
4436
+
4437
+  p->laSmpIdx += n0;
4438
+
4439
+  if( n1!=0)
4440
+  {
4441
+    // copy second block to begin of LA buffer
4442
+    for(i=0; i<chCnt; ++i)
4443
+      cmVOS_Copy(p->laChs[i],n1,iChs[i] + srcOffs + n0);
4444
+
4445
+    p->laSmpIdx = n1; 
4446
+
4447
+  }
4448
+
4449
+  //-------------------------------------------------------------------
4450
+  // copy incoming audio into the active record buffers
4451
+  //
4452
+  cmRecdPlayFrag* fp = p->rlist;
4453
+
4454
+  for(; fp!=NULL; fp=fp->rlink)
4455
+  {
4456
+    assert( fp->recdIdx <= fp->allocCnt);
4457
+    unsigned n = cmMin(fp->allocCnt - fp->recdIdx,smpCnt);
4458
+    unsigned i;
4459
+    for(i=0; i<p->chCnt; ++i)
4460
+    {
4461
+      cmVOS_Copy(fp->chArray[i] + fp->recdIdx, n, iChs[i] );
4462
+      fp->recdIdx += n;
4463
+    }
4464
+  }  
4465
+
4466
+  //-------------------------------------------------------------------
4467
+  // copy outgoing audio out of the active play buffers
4468
+  //
4469
+  fp = p->plist;
4470
+  for(; fp!=NULL; fp=fp->rlink)
4471
+  {
4472
+    assert( fp->playIdx <= fp->recdIdx);
4473
+
4474
+    double   gain = pow(10.0,((fp->fadeSmpIdx / p->srate) * fp->fadeDbPerSec)/20.0);
4475
+    unsigned n    = cmMin(fp->recdIdx - fp->playIdx,smpCnt);
4476
+    unsigned i;
4477
+
4478
+    for(i=0; i<p->chCnt; ++i)
4479
+    {
4480
+      cmVOS_MultVVS(oChs[i],n,fp->chArray[i] + fp->playIdx,gain);
4481
+      fp->playIdx += n;
4482
+    }
4483
+
4484
+    // if a fade rate has been set then advance the fade phase
4485
+    if(fp->fadeDbPerSec!=0.0)
4486
+      fp->fadeSmpIdx += smpCnt;
4487
+  }  
4488
+
4489
+  return cmOkRC;
4490
+}

+ 49
- 0
cmProc4.h Vedi File

@@ -626,6 +626,55 @@ extern "C" {
626 626
   cmRC_t         cmScModulatorExec(  cmScModulator* p, unsigned scLocIdx );
627 627
   cmRC_t         cmScModulatorDump(  cmScModulator* p );
628 628
 
629
+  //=======================================================================================================================
630
+ 
631
+  typedef struct cmRecdPlayFrag_str
632
+  {
633
+    unsigned                   labelSymId; // this fragments label
634
+    cmSample_t**               chArray;    // record buffer chArray[cmRecdPlay.chCnt][allocCnt]
635
+    unsigned                   allocCnt;   // count of samples allocated to each channel
636
+    unsigned                   playIdx;    // index of next sample to play
637
+    unsigned                   recdIdx;    // index of next sample to receieve audio (count of full samples)
638
+    double                     fadeDbPerSec; // fade rate in dB per second
639
+    unsigned                   fadeSmpIdx; 
640
+    struct cmRecdPlayFrag_str* rlink;      // cmRecdPlay.rlist link
641
+    struct cmRecdPlayFrag_str* plink;      // cmRecdPlay.plist link
642
+  } cmRecdPlayFrag;
643
+
644
+  typedef struct
645
+  {
646
+    cmObj            obj;
647
+    cmRecdPlayFrag*  frags;         // frags[fragCnt] fragment array
648
+    unsigned         fragCnt;       // count of fragments 
649
+    double           srate;         // system sample rate
650
+    unsigned         chCnt;         // count of input and output audio channels
651
+    double           initFragSecs;  // size initial memory allocated to each frag in seconds
652
+    unsigned         maxLaSmpCnt;   // samples allocated to each channel of the look-ahead buffers.
653
+    unsigned         curLaSmpCnt;   // current look-ahead time in samples (curLaSmpCnt<=maxLaSmpCnt)
654
+    cmSample_t**     laChs;         // laChs[chCnt][maxLaSmpCnt] - look-ahead buffers
655
+    int              laSmpIdx;      // next look-ahead buffer index to receive a sample
656
+    cmRecdPlayFrag*  plist;         // currently playing frags
657
+    cmRecdPlayFrag*  rlist;         // currently recording frags
658
+  } cmRecdPlay;
659
+
660
+
661
+  cmRecdPlay*    cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs  );
662
+  cmRC_t         cmRecdPlayFree(  cmRecdPlay** pp );
663
+  cmRC_t         cmRecdPlayInit(  cmRecdPlay* p, double srate, unsigned flagCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs  );
664
+  cmRC_t         cmRecdPlayFinal( cmRecdPlay* p );
665
+
666
+  cmRC_t         cmRecdPlayRegisterFrag( cmRecdPlay* p, unsigned fragIdx, unsigned labelSymId );
667
+
668
+  cmRC_t         cmRecdPlayRewind(      cmRecdPlay* p );
669
+  cmRC_t         cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId );
670
+  cmRC_t         cmRecdPlayEndRecord(   cmRecdPlay* p, unsigned labelSymId );
671
+  cmRC_t         cmRecdPlayBeginPlay(   cmRecdPlay* p, unsigned labelSymId );
672
+  cmRC_t         cmRecdPlayEndPlay(     cmRecdPlay* p, unsigned labelSymId );
673
+
674
+  cmRC_t         cmRecdPlayBeginFade(   cmRecdPlay* p, unsigned labelSymId, double fadeDbPerSec );
675
+
676
+  cmRC_t         cmRecdPlayExec(        cmRecdPlay* p, const cmSample_t** iChs, cmSample_t** oChs, unsigned chCnt, unsigned smpCnt );
677
+
629 678
 #ifdef __cplusplus
630 679
 }
631 680
 #endif

+ 3
- 0
cmStack.h Vedi File

@@ -42,12 +42,15 @@ extern "C" {
42 42
   const void* cmStackTop(     cmStackH_t h );
43 43
 
44 44
   // Set the value of 'dataEleCnt' elements on the stack.
45
+  // The top element is at index cmStackCount() - 1.
45 46
   cmStRC_t    cmStackSet(     cmStackH_t h, unsigned index, const void* data, unsigned dataEleCnt );
46 47
 
47 48
   // Copy 'dataEleCnt' elements into the buffer pointed to by 'data'.
49
+  // The top element is at index cmStackCount() - 1.
48 50
   cmStRC_t    cmStackGetN(    cmStackH_t h, unsigned index, void* data, unsigned dataEleCnt );
49 51
 
50 52
   // Return a pointer to a single element on the stack.
53
+  // The top element is at index cmStackCount() - 1.
51 54
   const void* cmStackGet(     cmStackH_t h, unsigned index );
52 55
 
53 56
   // Convert the internal representation of the stack to a linear array and return

+ 1
- 0
dsp/cmDspBuiltIn.c Vedi File

@@ -5418,6 +5418,7 @@ cmDspClassConsFunc_t _cmDspClassBuiltInArray[] =
5418 5418
   cmActiveMeasClassCons,
5419 5419
   cmAmSyncClassCons,
5420 5420
   cmNanoMapClassCons,
5421
+  cmRecdPlayClassCons,
5421 5422
   NULL,
5422 5423
 };
5423 5424
 

+ 260
- 1
dsp/cmDspKr.c Vedi File

@@ -572,7 +572,7 @@ cmDspRC_t _cmDspScoreReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
572 572
   }
573 573
 
574 574
   if((tlFn =  cmDspStrcz(inst, kFnScId )) !=  NULL )
575
-    if( cmScoreInitialize(ctx->cmCtx, &p->scH, tlFn, cmDspSampleRate(ctx), dynRefArray, dynRefCnt, _cmDspScoreCb, p, cmSymTblNullHandle ) != kOkTlRC )
575
+    if( cmScoreInitialize(ctx->cmCtx, &p->scH, tlFn, cmDspSampleRate(ctx), dynRefArray, dynRefCnt, _cmDspScoreCb, p, ctx->stH ) != kOkTlRC )
576 576
       rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Score file open failed.");
577 577
 
578 578
  errLabel:
@@ -2264,3 +2264,262 @@ struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx )
2264 2264
 
2265 2265
   return &_cmNanoMapDC;
2266 2266
 }
2267
+
2268
+//==========================================================================================================================================
2269
+enum
2270
+{
2271
+  kChCntPrId,
2272
+  kFnPrId,
2273
+  kSecsPrId,
2274
+  kMaxLaSecsPrId,
2275
+  kCurLaSecsPrId,
2276
+  kFadeRatePrId,
2277
+  kScLocIdxPrId,
2278
+  kCmdPrId,
2279
+  kInAudioBasePrId
2280
+};
2281
+
2282
+cmDspClass_t _cmRecdPlayDC;
2283
+
2284
+typedef struct
2285
+{
2286
+  cmDspInst_t inst;
2287
+  cmRecdPlay* rcdply;
2288
+  cmScH_t     scH;
2289
+  unsigned    onSymId;
2290
+  unsigned    offSymId;
2291
+  unsigned    audioOutBaseId;
2292
+  unsigned    chCnt;
2293
+  unsigned    scLocIdx;
2294
+} cmDspRecdPlay_t;
2295
+
2296
+cmDspRC_t _cmDspRecdPlayOpenScore( cmDspCtx_t* ctx, cmDspInst_t* inst )
2297
+{
2298
+  cmDspRC_t rc =kOkDspRC;
2299
+  const cmChar_t* fn;
2300
+
2301
+  cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
2302
+
2303
+  p->scLocIdx = 0;
2304
+
2305
+
2306
+  if((fn = cmDspStrcz(inst,kFnPrId)) == NULL || strlen(fn)==0 )
2307
+    return cmErrMsg(&inst->classPtr->err, kInvalidArgDspRC, "No score file name supplied.");
2308
+
2309
+  if( cmScoreInitialize(ctx->cmCtx, &p->scH, fn, cmDspSampleRate(ctx), NULL, 0, NULL, NULL, ctx->stH ) != kOkScRC )
2310
+    return cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to open the score '%s'.",fn);
2311
+
2312
+  if( cmScoreIsValid(p->scH) )
2313
+  {
2314
+    unsigned i;
2315
+    unsigned markerCnt = cmScoreMarkerLabelCount(p->scH);
2316
+    double initFragSecs = cmDspDouble(inst,kSecsPrId);
2317
+    double maxLaSecs    = cmDspDouble(inst,kMaxLaSecsPrId);
2318
+    double curLaSecs    = cmDspDouble(inst,kCurLaSecsPrId);
2319
+
2320
+    if((p->rcdply = cmRecdPlayAlloc(ctx->cmProcCtx, NULL, cmDspSampleRate(ctx), markerCnt, p->chCnt, initFragSecs, maxLaSecs, curLaSecs)) == NULL)
2321
+      return cmErrMsg(&inst->classPtr->err,kSubSysFailDspRC,"Unable to create the internal recorder-player object.");    
2322
+
2323
+    for(i=0; i<markerCnt; ++i)
2324
+      cmRecdPlayRegisterFrag(p->rcdply,i, cmScoreMarkerLabelSymbolId(p->scH,i ));
2325
+
2326
+  }
2327
+
2328
+  return rc;
2329
+}
2330
+
2331
+
2332
+cmDspInst_t*  _cmDspRecdPlayAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
2333
+{
2334
+
2335
+  if( va_cnt < 1 )
2336
+  {
2337
+    cmDspClassErr(ctx,classPtr,kVarArgParseFailDspRC,"The 'RecdPlay' constructor must have a count of input ports.");
2338
+    return NULL;
2339
+  }
2340
+
2341
+  va_list vl1;
2342
+  va_copy(vl1,vl);
2343
+
2344
+  int      chCnt         = va_arg(vl,int);
2345
+  unsigned audioOutBase  = kInAudioBasePrId + chCnt;    
2346
+
2347
+  cmDspRecdPlay_t* p = cmDspInstAllocV(cmDspRecdPlay_t,ctx,classPtr,instSymId,id,storeSymId,va_cnt,vl1,
2348
+    1,         "chs",    kChCntPrId,      0,0, kUIntDsvFl | kReqArgDsvFl,              "channel count.",
2349
+    1,         "fn",     kFnPrId,         0,0, kInDsvFl   | kStrzDsvFl | kReqArgDsvFl, "Score file." ,
2350
+    1,         "secs",   kSecsPrId,       0,0, kInDsvFl   | kDoubleDsvFl | kReqArgDsvFl, "Initial fragment allocation in seconds.",
2351
+    1,         "maxla",  kMaxLaSecsPrId,  0,0, kInDsvFl   | kDoubleDsvFl,              "Maximum look-ahead buffer in seconds.",
2352
+    1,         "curla",  kCurLaSecsPrId,  0,0, kInDsvFl   | kDoubleDsvFl,              "Current look-head buffer in seconds.",
2353
+    1,         "frate",  kFadeRatePrId,   0,0, kInDsvFl   | kDoubleDsvFl,              "Fade rate in dB per second.",
2354
+    1,         "index",  kScLocIdxPrId,   0,0, kInDsvFl   | kUIntDsvFl,                "Score follower location index.",
2355
+    1,         "cmd",    kCmdPrId,        0,0, kInDsvFl   | kSymDsvFl,                 "on=reset off=stop.",
2356
+    chCnt,     "in",     kInAudioBasePrId,0,1, kInDsvFl   | kAudioBufDsvFl,            "Audio input",
2357
+    chCnt,     "out",    audioOutBase,    0,1, kOutDsvFl  | kAudioBufDsvFl,            "Audio output",
2358
+    0 );
2359
+
2360
+  va_end(vl1);
2361
+
2362
+  p->onSymId        = cmSymTblId(ctx->stH,"on");
2363
+  p->offSymId       = cmSymTblId(ctx->stH,"off");
2364
+  p->audioOutBaseId = audioOutBase;
2365
+  p->chCnt          = chCnt;
2366
+  p->scLocIdx       = 0;
2367
+
2368
+  cmDspSetDefaultDouble(ctx,&p->inst, kSecsPrId,     0, 10.0 );
2369
+  cmDspSetDefaultDouble(ctx,&p->inst, kMaxLaSecsPrId,0, 2.0);
2370
+  cmDspSetDefaultDouble(ctx,&p->inst, kCurLaSecsPrId,0, 0.5);
2371
+  cmDspSetDefaultDouble(ctx,&p->inst, kFadeRatePrId, 0, 1.0);
2372
+
2373
+  return &p->inst;
2374
+}
2375
+
2376
+cmDspRC_t _cmDspRecdPlayFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
2377
+{
2378
+  cmDspRC_t        rc = kOkDspRC;
2379
+  cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
2380
+
2381
+  cmRecdPlayFree(&p->rcdply);
2382
+
2383
+  cmScoreFinalize(&p->scH);
2384
+  return rc;
2385
+}
2386
+
2387
+cmDspRC_t _cmDspRecdPlayReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
2388
+{
2389
+  cmDspApplyAllDefaults(ctx,inst);
2390
+
2391
+  return _cmDspRecdPlayOpenScore(ctx,inst);
2392
+} 
2393
+
2394
+cmDspRC_t _cmDspRecdPlayExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
2395
+{
2396
+  cmDspRC_t      rc = kOkDspRC;
2397
+
2398
+  cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
2399
+
2400
+  const cmSample_t* x[ p->chCnt ];
2401
+  cmSample_t*       y[ p->chCnt ];
2402
+  unsigned n;
2403
+  unsigned i;
2404
+  unsigned actChCnt = 0;
2405
+
2406
+  for(i=0; i<p->chCnt; ++i)
2407
+  {
2408
+    if( i==0 )
2409
+      n  = cmDspAudioBufSmpCount(ctx,inst,kInAudioBasePrId+i,0);
2410
+    else
2411
+    { assert( n == cmDspAudioBufSmpCount(ctx,inst,kInAudioBasePrId+i,0)); }
2412
+
2413
+    x[i] = cmDspAudioBuf(ctx,inst,kInAudioBasePrId+i,0);
2414
+
2415
+    if( x[i] != NULL )
2416
+    {
2417
+      y[i] = cmDspAudioBuf(ctx,inst,p->audioOutBaseId+i,0);
2418
+
2419
+      if( y[i] != NULL )
2420
+      {
2421
+        assert( n == cmDspAudioBufSmpCount(ctx,inst,p->audioOutBaseId+i,0));
2422
+
2423
+        cmVOS_Zero(y[i],n);
2424
+
2425
+        actChCnt += 1;
2426
+      }
2427
+      
2428
+    }
2429
+  }
2430
+
2431
+  cmRecdPlayExec(p->rcdply,x,y,actChCnt,n);
2432
+
2433
+  return rc;
2434
+}
2435
+
2436
+cmDspRC_t _cmDspRecdPlayRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
2437
+{
2438
+  cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
2439
+
2440
+  cmDspSetEvent(ctx,inst,evt);
2441
+
2442
+  switch( evt->dstVarId )
2443
+  {
2444
+    case kCmdPrId:
2445
+      if( cmDspSymbol(inst,kCmdPrId) == p->onSymId )
2446
+      {
2447
+        printf("rewind\n");
2448
+        cmRecdPlayRewind(p->rcdply);
2449
+        p->scLocIdx = 0;
2450
+      }
2451
+      else
2452
+        if( cmDspSymbol(inst,kCmdPrId) == p->offSymId )
2453
+        {
2454
+        }
2455
+
2456
+      break;
2457
+
2458
+    case kCurLaSecsPrId:
2459
+      break;
2460
+
2461
+    case kScLocIdxPrId:
2462
+      {
2463
+        unsigned endScLocIdx = cmDspUInt(inst,kScLocIdxPrId) ;
2464
+
2465
+        for(; p->scLocIdx<=endScLocIdx; p->scLocIdx+=1)
2466
+        {
2467
+          cmScoreLoc_t*    loc = cmScoreLoc(p->scH, p->scLocIdx );
2468
+          cmScoreMarker_t* mp  = loc->markList;
2469
+
2470
+          for(; mp!=NULL; mp=mp->link)
2471
+            switch( mp->markTypeId )
2472
+            {
2473
+              case kRecdBegScMId:
2474
+                printf("recd-beg\n");
2475
+                cmRecdPlayBeginRecord(p->rcdply, mp->labelSymId );
2476
+                break;
2477
+                
2478
+              case kRecdEndScMId:
2479
+                printf("recd-end\n");
2480
+                cmRecdPlayEndRecord(p->rcdply, mp->labelSymId );
2481
+                break;
2482
+                
2483
+              case kPlayBegScMId:
2484
+                printf("play-beg\n");
2485
+                cmRecdPlayBeginPlay(p->rcdply, mp->labelSymId );
2486
+                break;
2487
+
2488
+              case kPlayEndScMId:
2489
+                printf("play-end\n");
2490
+                cmRecdPlayEndPlay(p->rcdply, mp->labelSymId );
2491
+                break;
2492
+
2493
+              case kFadeScMId:
2494
+                printf("fade-beg\n");
2495
+                cmRecdPlayBeginFade(p->rcdply, mp->labelSymId, cmDspDouble(inst,kFadeRatePrId) );
2496
+                break;
2497
+
2498
+              default:
2499
+                break;
2500
+            }
2501
+        }
2502
+
2503
+        p->scLocIdx = endScLocIdx+1;
2504
+      }
2505
+      break;
2506
+  }
2507
+
2508
+  return kOkDspRC;
2509
+}
2510
+
2511
+struct cmDspClass_str* cmRecdPlayClassCons( cmDspCtx_t* ctx )
2512
+{
2513
+  cmDspClassSetup(&_cmRecdPlayDC,ctx,"RecdPlay",
2514
+    NULL,
2515
+    _cmDspRecdPlayAlloc,
2516
+    _cmDspRecdPlayFree,
2517
+    _cmDspRecdPlayReset,
2518
+    _cmDspRecdPlayExec,
2519
+    _cmDspRecdPlayRecv,
2520
+    NULL,
2521
+    NULL,
2522
+    "Score controlled live recorder/player");
2523
+
2524
+  return &_cmRecdPlayDC;
2525
+}

+ 1
- 0
dsp/cmDspKr.h Vedi File

@@ -16,6 +16,7 @@ extern "C" {
16 16
   struct cmDspClass_str* cmActiveMeasClassCons( cmDspCtx_t* ctx );
17 17
   struct cmDspClass_str* cmAmSyncClassCons( cmDspCtx_t* ctx );
18 18
   struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx );
19
+  struct cmDspClass_str* cmRecdPlayClassCons( cmDspCtx_t* ctx );
19 20
 
20 21
 #ifdef __cplusplus
21 22
 }

+ 14
- 4
dsp/cmDspPgmKr.c Vedi File

@@ -97,7 +97,10 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
97 97
   double          cmpWndMaxMs  = 1000.0;
98 98
   double          cmpWndMs     = 200.0;
99 99
 
100
-
100
+  double          recdPlayInitAllocSecs    = 10.0;
101
+  double          recdPlayMaxLaSecs        = 2.0;
102
+  double          recdPlayCurLaSecs        = 0.1;
103
+  double          recdPlayFadeRateDbPerSec = 4.0;
101 104
 
102 105
   memset(&r,0,sizeof(r));
103 106
   cmErrSetup(&err,&cmCtx->rpt,"Kr Timeline");
@@ -122,6 +125,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
122 125
   cmDspInst_t* mop  = cmDspSysAllocInst(h,"MidiOut",     NULL,  2, r.midiDevice,r.midiOutPort);
123 126
   cmDspInst_t* sfp  = cmDspSysAllocInst(h,"ScFol",       NULL,  1, r.scFn );
124 127
   cmDspInst_t* amp  = cmDspSysAllocInst(h,"ActiveMeas",  NULL,  1, 100 );
128
+  cmDspInst_t* rpp  = cmDspSysAllocInst(h,"RecdPlay",    NULL,  4, 2, r.scFn, recdPlayInitAllocSecs, recdPlayMaxLaSecs, recdPlayCurLaSecs, recdPlayFadeRateDbPerSec );
125 129
   cmDspInst_t* modp = cmDspSysAllocInst(h,"ScMod",       NULL,  2, r.modFn, "m1" );
126 130
   cmDspInst_t* asp  = cmDspSysAllocInst(h,"AmSync",      NULL,  0 );
127 131
 
@@ -173,14 +177,14 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
173 177
   cmDspInst_t* kr00 = cmDspSysAllocInst(h, "Kr",         NULL,   2, krWndSmpCnt, krHopFact );
174 178
   cmDspInst_t* kr01 = cmDspSysAllocInst(h, "Kr",         NULL,   2, krWndSmpCnt, krHopFact );
175 179
   cmDspInst_t* fad0 = cmDspSysAllocInst(h, "Xfader",     NULL,   3, xfadeChCnt,  xfadeMs, xfadeInitFl ); 
176
-  cmDspInst_t* mix0 = cmDspSysAllocInst(h, "AMix",       NULL,   3, xfadeChCnt, mixGain, mixGain );
180
+  cmDspInst_t* mix0 = cmDspSysAllocInst(h, "AMix",       NULL,   4, xfadeChCnt+1, mixGain, mixGain, mixGain );
177 181
   cmDspInst_t* cmp0 =  cmDspSysAllocInst(h,"Compressor", NULL,   8, cmpBypassFl, cmpThreshDb, cmpRatio_num, cmpAtkMs, cmpRlsMs, cmpMakeup, cmpWndMs, cmpWndMaxMs ); 
178 182
   cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut",    NULL,   1, 0 );
179 183
   
180 184
   cmDspInst_t* kr10 = cmDspSysAllocInst(h, "Kr",         NULL,   2, krWndSmpCnt, krHopFact );
181 185
   cmDspInst_t* kr11 = cmDspSysAllocInst(h, "Kr",         NULL,   2, krWndSmpCnt, krHopFact );
182 186
   cmDspInst_t* fad1 = cmDspSysAllocInst(h, "Xfader",     NULL,   3, xfadeChCnt,  xfadeMs, xfadeInitFl ); 
183
-  cmDspInst_t* mix1 = cmDspSysAllocInst(h, "AMix",       NULL,   3, xfadeChCnt, mixGain, mixGain );
187
+  cmDspInst_t* mix1 = cmDspSysAllocInst(h, "AMix",       NULL,   4, xfadeChCnt+1, mixGain, mixGain, mixGain );
184 188
   cmDspInst_t* cmp1 =  cmDspSysAllocInst(h,"Compressor", NULL,   8, cmpBypassFl, cmpThreshDb, cmpRatio_num, cmpAtkMs, cmpRlsMs, cmpMakeup, cmpWndMs, cmpWndMaxMs ); 
185 189
   cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut",    NULL,   1, 1 );
186 190
 
@@ -378,12 +382,14 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
378 382
   cmDspSysConnectAudio(h, wtp,  "out",   au0Sw, "a-in-0" ); // wt  -> sw
379 383
   cmDspSysConnectAudio(h, ai0p, "out",   au0Sw, "a-in-1" ); // ain -> sw
380 384
   cmDspSysConnectAudio(h, ai0p, "out",   mi0p,  "in" );
385
+  cmDspSysConnectAudio(h, au0Sw,"a-out", rpp,   "in-0");    // sw  -> rcdply
381 386
   cmDspSysConnectAudio(h, au0Sw,"a-out", kr00, "in"  );     // sw  -> kr
382 387
   cmDspSysConnectAudio(h, kr00, "out",   fad0, "in-0");     // kr  -> fad
383 388
   cmDspSysConnectAudio(h, fad0, "out-0", mix0, "in-0");     // fad -> mix
384 389
   cmDspSysConnectAudio(h, au0Sw,"a-out", kr01, "in"  );     // sw  -> kr
385 390
   cmDspSysConnectAudio(h, kr01, "out",   fad0, "in-1");     // kr  -> fad
386 391
   cmDspSysConnectAudio(h, fad0, "out-1", mix0, "in-1");     // fad -> mix
392
+  cmDspSysConnectAudio(h, rpp,  "out-0", mix0, "in-2");
387 393
   cmDspSysConnectAudio(h, mix0, "out",   cmp0, "in");       // mix -> cmp
388 394
   cmDspSysConnectAudio(h, cmp0, "out",   ao0p, "in" );      // cmp -> aout
389 395
 
@@ -391,12 +397,14 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
391 397
   cmDspSysConnectAudio(h, wtp,  "out",   au1Sw, "a-in-0" );  // wt -> kr
392 398
   cmDspSysConnectAudio(h, ai1p, "out",   au1Sw, "a-in-1" );
393 399
   cmDspSysConnectAudio(h, ai1p, "out",   mi1p,  "in" );
400
+  cmDspSysConnectAudio(h, au1Sw,"a-out", rpp,   "in-1");    // sw  -> rcdply
394 401
   cmDspSysConnectAudio(h, au1Sw,"a-out", kr10, "in"  );  
395 402
   cmDspSysConnectAudio(h, kr10, "out",   fad1, "in-0");
396 403
   cmDspSysConnectAudio(h, fad1, "out-0", mix1, "in-0");
397 404
   cmDspSysConnectAudio(h, au1Sw,"a-out", kr11, "in"  );  // wt -> kr
398 405
   cmDspSysConnectAudio(h, kr11, "out",   fad1, "in-1");  
399 406
   cmDspSysConnectAudio(h, fad1, "out-1", mix1, "in-1");
407
+  cmDspSysConnectAudio(h, rpp,  "out-0", mix1, "in-2");
400 408
   cmDspSysConnectAudio(h, mix1, "out",   cmp1, "in");
401 409
   cmDspSysConnectAudio(h, cmp1, "out",   ao1p, "in" );   // comp -> aout
402 410
 
@@ -437,6 +445,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
437 445
   cmDspSysInstallCb(h, pts, "on",      wtRt,  "s-in",  NULL );
438 446
   cmDspSysInstallCb(h, wtRt,"s-out-0", wtp,   "cmd",   NULL );
439 447
   cmDspSysInstallCb(h, pts, "on",      modp,  "cmd",   NULL );
448
+  cmDspSysInstallCb(h, pts, "on",      rpp,   "cmd",   NULL );
440 449
   cmDspSysInstallCb(h, onb, "sym",     amCmd, "rewind",NULL );
441 450
   cmDspSysInstallCb(h, onb, "out",     achan0,"reset",  NULL );
442 451
   cmDspSysInstallCb(h, onb, "out",     achan1,"reset",  NULL );
@@ -493,7 +502,8 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
493 502
   cmDspSysInstallCb(h, mip, "d0",     sfp, "d0",     NULL );
494 503
   cmDspSysInstallCb(h, mip, "status", sfp, "status", NULL );
495 504
 
496
-  // score follower to modulator and printers
505
+  // score follower to recd_play,modulator and printers
506
+  cmDspSysInstallCb(h, sfp, "out",     rpp,     "index", NULL );
497 507
   cmDspSysInstallCb(h, sfp, "out",     modp,    "index", NULL );
498 508
   cmDspSysInstallCb(h, sfp, "recent",  prp,     "in",  NULL );  // report 'recent' but only act on 'max' loc index
499 509
 

Loading…
Annulla
Salva