Browse Source

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

spat lab mac.
master
kevin 11 years ago
parent
commit
c946234fde
17 changed files with 3772 additions and 1891 deletions
  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 View File

6
 #include "cmCtx.h"
6
 #include "cmCtx.h"
7
 #include "cmMem.h"
7
 #include "cmMem.h"
8
 #include "cmMallocDebug.h"
8
 #include "cmMallocDebug.h"
9
+#include "cmLinkedHeap.h"
9
 #include "cmMidi.h"
10
 #include "cmMidi.h"
10
 #include "cmLex.h"
11
 #include "cmLex.h"
11
 #include "cmCsv.h"
12
 #include "cmCsv.h"
13
 #include "cmMidiFile.h"
14
 #include "cmMidiFile.h"
14
 #include "cmAudioFile.h"
15
 #include "cmAudioFile.h"
15
 #include "cmTimeLine.h"
16
 #include "cmTimeLine.h"
17
+#include "cmText.h"
16
 #include "cmScore.h"
18
 #include "cmScore.h"
17
 #include "cmVectOpsTemplateMain.h"
19
 #include "cmVectOpsTemplateMain.h"
18
 
20
 
41
   kFracColScIdx      = 18,
43
   kFracColScIdx      = 18,
42
   kDynColScIdx       = 19,
44
   kDynColScIdx       = 19,
43
   kSectionColScIdx   = 20,
45
   kSectionColScIdx   = 20,
44
-  kRemarkColScIdx    = 21
46
+  kRecdPlayColScIdx  = 21,
47
+  kRemarkColScIdx    = 22
45
 };
48
 };
46
 
49
 
47
 
50
 
75
   struct cmScSet_str* link;   // 
78
   struct cmScSet_str* link;   // 
76
 } cmScSet_t;
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
 typedef struct
90
 typedef struct
79
 {
91
 {
80
   cmErr_t           err;
92
   cmErr_t           err;
94
   cmScoreSection_t* sect;
106
   cmScoreSection_t* sect;
95
   unsigned          sectCnt;
107
   unsigned          sectCnt;
96
 
108
 
109
+  unsigned*         markLabelArray;    // one symId per unique cmScoreMarker_t.labelSymId;
110
+  unsigned          markLabelCnt; 
111
+
97
   unsigned          sciPitchLexTId; // sci pitch and section id lexer token id's
112
   unsigned          sciPitchLexTId; // sci pitch and section id lexer token id's
98
   unsigned          sectionLexTId;
113
   unsigned          sectionLexTId;
99
 
114
 
100
   cmScSect_t*       sectList;       // lists used during parsing
115
   cmScSect_t*       sectList;       // lists used during parsing
101
   cmScSet_t*        setList;    
116
   cmScSet_t*        setList;    
117
+  cmScMark_t*       markList;
102
 
118
 
103
   cmScoreSet_t*     sets;
119
   cmScoreSet_t*     sets;
104
   unsigned          setCnt;
120
   unsigned          setCnt;
313
   return 0;
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
 void _cmScFreeSetList( cmScSet_t* setList )
343
 void _cmScFreeSetList( cmScSet_t* setList )
317
 {
344
 {
318
   cmScSet_t* tp = setList;
345
   cmScSet_t* tp = setList;
366
 
393
 
367
   _cmScFreeSetList(p->setList);
394
   _cmScFreeSetList(p->setList);
368
 
395
 
396
+  _cmScFreeMarkList(p->markList);
397
+
369
   if( p->loc != NULL )
398
   if( p->loc != NULL )
370
   {
399
   {
371
     for(i=0; i<p->locCnt; ++i)
400
     for(i=0; i<p->locCnt; ++i)
373
       cmMemFree(p->loc[i].evtArray);
402
       cmMemFree(p->loc[i].evtArray);
374
       if( p->loc[i].begSectPtr != NULL )
403
       if( p->loc[i].begSectPtr != NULL )
375
         cmMemFree(p->loc[i].begSectPtr->setArray);
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
     cmMemFree(p->loc);
416
     cmMemFree(p->loc);
378
   }
417
   }
379
 
418
 
419
+  
380
   cmMemPtrFree(&p->dynRefArray);
420
   cmMemPtrFree(&p->dynRefArray);
381
-
421
+  cmMemFree(p->markLabelArray);
382
   cmMemFree(p->sect);
422
   cmMemFree(p->sect);
383
   cmMemFree(p->fn);
423
   cmMemFree(p->fn);
384
   cmMemFree(p->array);
424
   cmMemFree(p->array);
557
   return kOkScRC;
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
 void _cmScPrintSets( const cmChar_t* label, cmScSet_t* setList )
673
 void _cmScPrintSets( const cmChar_t* label, cmScSet_t* setList )
561
 {
674
 {
562
   printf("%s\n",label);
675
   printf("%s\n",label);
598
     return cmErrMsg(&p->err,kSyntaxErrScRC,"Expected a scientific pitch value");
711
     return cmErrMsg(&p->err,kSyntaxErrScRC,"Expected a scientific pitch value");
599
           
712
           
600
   if((midiPitch = cmSciPitchToMidi(sciPitch)) == kInvalidMidiPitch)
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
   // it is possible that note delta-secs field is empty - so default to 0
716
   // it is possible that note delta-secs field is empty - so default to 0
604
   if((secs =  cmCsvCellDouble(p->cH, rowIdx, kSecsColScIdx )) == DBL_MAX) // Returns DBL_MAX on error.
717
   if((secs =  cmCsvCellDouble(p->cH, rowIdx, kSecsColScIdx )) == DBL_MAX) // Returns DBL_MAX on error.
658
     durSecs = 0.25;
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
   s->type       = kNonEvtScId;
782
   s->type       = kNonEvtScId;
662
   s->secs       = secs;
783
   s->secs       = secs;
663
   s->pitch      = midiPitch;
784
   s->pitch      = midiPitch;
870
 }
991
 }
871
 
992
 
872
 
993
 
994
+
995
+
873
 cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
996
 cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
874
 {
997
 {
875
   cmScRC_t rc = kOkScRC;
998
   cmScRC_t rc = kOkScRC;
935
   return rc;
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
 cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
1208
 cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
939
 {
1209
 {
940
   cmScRC_t    rc         = kOkScRC;
1210
   cmScRC_t    rc         = kOkScRC;
1036
         break;
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
   if((rc = _cmScProcSections(p,p->sectList)) != kOkScRC )
1437
   if((rc = _cmScProcSections(p,p->sectList)) != kOkScRC )
1165
     goto errLabel;
1438
     goto errLabel;
1166
 
1439
 
1440
+  if((rc = _cmScProcMarkers(p)) != kOkScRC )
1441
+    goto errLabel;
1442
+  
1167
   // load the dynamic reference array
1443
   // load the dynamic reference array
1168
   if( dynRefArray != NULL && dynRefCnt > 0)
1444
   if( dynRefArray != NULL && dynRefCnt > 0)
1169
   {
1445
   {
1409
   return p->setCnt;
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
 cmScRC_t      cmScoreSeqNotify( cmScH_t h )
1712
 cmScRC_t      cmScoreSeqNotify( cmScH_t h )
1413
 {
1713
 {
1414
   cmScRC_t  rc = kOkScRC;
1714
   cmScRC_t  rc = kOkScRC;
1502
         fl = true;
1802
         fl = true;
1503
       }
1803
       }
1504
     }
1804
     }
1505
-   --n;
1805
+    --n;
1506
   }
1806
   }
1507
 }
1807
 }
1508
 
1808
 
1568
   if(printFl)
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
       printf("%i %i ",i,v[i]);
1873
       printf("%i %i ",i,v[i]);
1574
       if( i > 0 )
1874
       if( i > 0 )
1575
-        printf("%i ", d[i-1]);
1875
+      printf("%i ", d[i-1]);
1576
       printf("\n");
1876
       printf("\n");
1577
-    }
1877
+      }
1578
     */
1878
     */
1579
     printf("%s EVENESS:%f\n",sortFl?"SORTED ":"",stp->value);
1879
     printf("%s EVENESS:%f\n",sortFl?"SORTED ":"",stp->value);
1580
   }
1880
   }
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
 void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
2466
 void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
1959
 {
2467
 {
1960
   cmScH_t h = cmScNullHandle;
2468
   cmScH_t h = cmScNullHandle;

+ 36
- 9
app/cmScore.h View File

12
     kSyntaxErrScRC,
12
     kSyntaxErrScRC,
13
     kInvalidIdxScRC,
13
     kInvalidIdxScRC,
14
     kTimeLineFailScRC,
14
     kTimeLineFailScRC,
15
-    kInvalidDynRefCntScRC
16
-  
15
+    kInvalidDynRefCntScRC,
16
+    kMidiFileFailScRC
17
   };
17
   };
18
 
18
 
19
   enum
19
   enum
36
   // Flags used by cmScoreEvt_t.flags
36
   // Flags used by cmScoreEvt_t.flags
37
   enum
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
     double                 value;
103
     double                 value;
104
     struct cmScoreSet_str* llink;      // cmScoreLoc_t setList link
104
     struct cmScoreSet_str* llink;      // cmScoreLoc_t setList link
105
   } cmScoreSet_t;
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
   // All events which are simultaneous are collected into a single
127
   // All events which are simultaneous are collected into a single
109
   // cmScoreLoc_t record.
128
   // cmScoreLoc_t record.
116
     unsigned          barNumb;       // Bar number this event is contained by.                            
135
     unsigned          barNumb;       // Bar number this event is contained by.                            
117
     cmScoreSet_t*     setList;       // Set's which end on this time location (linked through cmScoreSet_t.llink)
136
     cmScoreSet_t*     setList;       // Set's which end on this time location (linked through cmScoreSet_t.llink)
118
     cmScoreSection_t* begSectPtr;    // NULL if this location does not start a section
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
   } cmScoreLoc_t;
139
   } cmScoreLoc_t;
120
 
140
 
121
   typedef void (*cmScCb_t)( void* arg, const void* data, unsigned byteCnt );
141
   typedef void (*cmScCb_t)( void* arg, const void* data, unsigned byteCnt );
170
   // Return the count of sets.
190
   // Return the count of sets.
171
   unsigned      cmScoreSetCount( cmScH_t h );
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
   // Make callbacks for all events in the score. The callbacks
197
   // Make callbacks for all events in the score. The callbacks
174
   // contain cmScMsg_t records serialized as a byte stream.
198
   // contain cmScMsg_t records serialized as a byte stream.
175
   // Use cmScoreDecode() to convert the byte string to a
199
   // Use cmScoreDecode() to convert the byte string to a
235
 
259
 
236
   void          cmScorePrint( cmScH_t h, cmRpt_t* rpt );
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
   void          cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn );
265
   void          cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn );
239
 
266
 
240
 
267
 

+ 53
- 5
cmCsv.c View File

729
   return cmInvalidId;
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
 unsigned   cmCsvInsertSymFloat(  cmCsvH_t h, float v )
746
 unsigned   cmCsvInsertSymFloat(  cmCsvH_t h, float v )
733
 {
747
 {
734
   const char* fmt = "%f";
748
   const char* fmt = "%f";
812
   return kOkCsvRC;  
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
 cmCsvRC_t  cmCsvSetCellFloat(  cmCsvH_t h, unsigned row, unsigned col, float v )
847
 cmCsvRC_t  cmCsvSetCellFloat(  cmCsvH_t h, unsigned row, unsigned col, float v )
816
 {
848
 {
817
   cmCsvCell_t* cp;
849
   cmCsvCell_t* cp;
985
   cmCsvCell_t* ncp;
1017
   cmCsvCell_t* ncp;
986
 
1018
 
987
   if( cellPtrPtr != NULL )
1019
   if( cellPtrPtr != NULL )
988
-    cellPtrPtr = NULL;
1020
+    *cellPtrPtr = NULL;
989
 
1021
 
990
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1022
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
991
     if((rc = cmCsvSetCellText(h, ncp->row, ncp->col, text )) == kOkCsvRC )
1023
     if((rc = cmCsvSetCellText(h, ncp->row, ncp->col, text )) == kOkCsvRC )
1001
   cmCsvCell_t* ncp;
1033
   cmCsvCell_t* ncp;
1002
 
1034
 
1003
   if( cellPtrPtr != NULL )
1035
   if( cellPtrPtr != NULL )
1004
-    cellPtrPtr = NULL;
1036
+    *cellPtrPtr = NULL;
1005
 
1037
 
1006
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1038
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1007
     if((rc = cmCsvSetCellInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
1039
     if((rc = cmCsvSetCellInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
1017
   cmCsvCell_t* ncp;
1049
   cmCsvCell_t* ncp;
1018
 
1050
 
1019
   if( cellPtrPtr != NULL )
1051
   if( cellPtrPtr != NULL )
1020
-    cellPtrPtr = NULL;
1052
+    *cellPtrPtr = NULL;
1021
 
1053
 
1022
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1054
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1023
     if((rc = cmCsvSetCellUInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
1055
     if((rc = cmCsvSetCellUInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
1027
   return rc;
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
 cmCsvRC_t  cmCsvInsertFloatColAfter(  cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val, unsigned lexTId )
1078
 cmCsvRC_t  cmCsvInsertFloatColAfter(  cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val, unsigned lexTId )
1031
 {
1079
 {
1032
   cmCsvRC_t    rc;
1080
   cmCsvRC_t    rc;
1033
   cmCsvCell_t* ncp;
1081
   cmCsvCell_t* ncp;
1034
 
1082
 
1035
   if( cellPtrPtr != NULL )
1083
   if( cellPtrPtr != NULL )
1036
-    cellPtrPtr = NULL;
1084
+    *cellPtrPtr = NULL;
1037
 
1085
 
1038
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1086
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1039
     if((rc = cmCsvSetCellFloat(h, ncp->row, ncp->col, val )) == kOkCsvRC )
1087
     if((rc = cmCsvSetCellFloat(h, ncp->row, ncp->col, val )) == kOkCsvRC )
1049
   cmCsvCell_t* ncp;
1097
   cmCsvCell_t* ncp;
1050
 
1098
 
1051
   if( cellPtrPtr != NULL )
1099
   if( cellPtrPtr != NULL )
1052
-    cellPtrPtr = NULL;
1100
+    *cellPtrPtr = NULL;
1053
 
1101
 
1054
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1102
   if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
1055
     if((rc = cmCsvSetCellDouble(h, ncp->row, ncp->col, val )) == kOkCsvRC )
1103
     if((rc = cmCsvSetCellDouble(h, ncp->row, ncp->col, val )) == kOkCsvRC )

+ 4
- 0
cmCsv.h View File

109
   unsigned   cmCsvInsertSymText(   cmCsvH_t h, const char* text );
109
   unsigned   cmCsvInsertSymText(   cmCsvH_t h, const char* text );
110
   unsigned   cmCsvInsertSymInt(    cmCsvH_t h, int v );
110
   unsigned   cmCsvInsertSymInt(    cmCsvH_t h, int v );
111
   unsigned   cmCsvInsertSymUInt(   cmCsvH_t h, unsigned v );
111
   unsigned   cmCsvInsertSymUInt(   cmCsvH_t h, unsigned v );
112
+  unsigned   cmCsvInsertSymHex(    cmCsvH_t h, unsigned v );
112
   unsigned   cmCsvInsertSymFloat(  cmCsvH_t h, float v );
113
   unsigned   cmCsvInsertSymFloat(  cmCsvH_t h, float v );
113
   unsigned   cmCsvInsertSymDouble( cmCsvH_t h, double v );  
114
   unsigned   cmCsvInsertSymDouble( cmCsvH_t h, double v );  
114
 
115
 
116
+
115
   // Set the value associated with a cell.
117
   // Set the value associated with a cell.
116
   cmCsvRC_t  cmCsvSetCellText(   cmCsvH_t h, unsigned row, unsigned col, const char* text );
118
   cmCsvRC_t  cmCsvSetCellText(   cmCsvH_t h, unsigned row, unsigned col, const char* text );
117
   cmCsvRC_t  cmCsvSetCellInt(    cmCsvH_t h, unsigned row, unsigned col, int v );
119
   cmCsvRC_t  cmCsvSetCellInt(    cmCsvH_t h, unsigned row, unsigned col, int v );
118
   cmCsvRC_t  cmCsvSetCellUInt(   cmCsvH_t h, unsigned row, unsigned col, unsigned v );
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
   cmCsvRC_t  cmCsvSetCellFloat(  cmCsvH_t h, unsigned row, unsigned col, float v );
122
   cmCsvRC_t  cmCsvSetCellFloat(  cmCsvH_t h, unsigned row, unsigned col, float v );
120
   cmCsvRC_t  cmCsvSetCellDouble( cmCsvH_t h, unsigned row, unsigned col, double v );
123
   cmCsvRC_t  cmCsvSetCellDouble( cmCsvH_t h, unsigned row, unsigned col, double v );
121
 
124
 
134
   cmCsvRC_t  cmCsvInsertTextColAfter(   cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, const char* val, unsigned lexTId );
137
   cmCsvRC_t  cmCsvInsertTextColAfter(   cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, const char* val, unsigned lexTId );
135
   cmCsvRC_t  cmCsvInsertIntColAfter(    cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, int val,         unsigned lexTId );
138
   cmCsvRC_t  cmCsvInsertIntColAfter(    cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, int val,         unsigned lexTId );
136
   cmCsvRC_t  cmCsvInsertUIntColAfter(   cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val,    unsigned lexTId );
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
   cmCsvRC_t  cmCsvInsertFloatColAfter(  cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val,       unsigned lexTId );
141
   cmCsvRC_t  cmCsvInsertFloatColAfter(  cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val,       unsigned lexTId );
138
   cmCsvRC_t  cmCsvInsertDoubleColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, double val,      unsigned lexTId );
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 suppressed because it is too large
View File


+ 311
- 263
cmData.h View File

5
 extern "C" {
5
 extern "C" {
6
 #endif
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
   enum
50
   enum
9
   {
51
   {
10
     kOkDtRC = cmOkRC,
52
     kOkDtRC = cmOkRC,
53
+    kAssertErrDtRC,
54
+    kConstErrDtRC,
11
     kCvtErrDtRC,
55
     kCvtErrDtRC,
12
-    kVarArgErrDtRC,
13
-    kMissingFieldDtRC,
56
+    kInvalidContDtRC,
57
+    kInvalidTypeDtRC,
14
     kEolDtRC
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
   typedef enum
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
   enum
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
   typedef struct cmData_str
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
     union
132
     union
89
     {
133
     {
99
       double            d;
143
       double            d;
100
 
144
 
101
       cmChar_t*         z;
145
       cmChar_t*         z;
102
-      const cmChar_t*  cz;
103
 
146
 
104
       void*             vp;
147
       void*             vp;
105
 
148
 
149
+      /*
106
       char*             cp;
150
       char*             cp;
107
       unsigned char*   ucp;
151
       unsigned char*   ucp;
108
       short*            sp;
152
       short*            sp;
113
       unsigned long*   ulp;
157
       unsigned long*   ulp;
114
       float*            fp;
158
       float*            fp;
115
       double*           dp;
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
     } u;
163
     } u;
120
   
164
   
121
   } cmData_t;
165
   } cmData_t;
122
 
166
 
123
-  typedef unsigned cmDtRC_t;
124
-
125
   extern cmData_t cmDataNull;
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
   // Get the value of an object with conversion.
272
   // Get the value of an object with conversion.
209
   cmDtRC_t cmDataGetChar(      const cmData_t* p, char* v );
273
   cmDtRC_t cmDataGetChar(      const cmData_t* p, char* v );
217
   cmDtRC_t cmDataGetFloat(     const cmData_t* p, float* v );
281
   cmDtRC_t cmDataGetFloat(     const cmData_t* p, float* v );
218
   cmDtRC_t cmDataGetDouble(    const cmData_t* p, double* v );
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
   // These functions begin by releasing any resources held by *p
332
   // These functions begin by releasing any resources held by *p
238
   // prior to resetting the type and value of the object.
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
   // Structure related functions
375
   // Structure related functions
341
   //
376
   //
428
   cmData_t* cmDataAllocPairId(    cmData_t* parent, unsigned  keyId,       cmData_t* value );
463
   cmData_t* cmDataAllocPairId(    cmData_t* parent, unsigned  keyId,       cmData_t* value );
429
 
464
 
430
   // Dynamically allocate the label but link (w/o realloc) the value.
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
   cmData_t* cmDataAllocPairLabel( cmData_t* parent, const cmChar_t* label, cmData_t* value );
467
   cmData_t* cmDataAllocPairLabel( cmData_t* parent, const cmChar_t* label, cmData_t* value );
432
 
468
 
433
   //----------------------------------------------------------------------------
469
   //----------------------------------------------------------------------------
445
 
481
 
446
 
482
 
447
   // Var-args fmt:
483
   // Var-args fmt:
448
-  // <typeId> <value> {<cnt>}
484
+  // <contId> {<typeId>} <value> {<cnt>}
449
   // scalar types: <value> is literal,<cnt>   is not included
485
   // scalar types: <value> is literal,<cnt>   is not included
450
   //     null has no <value> or <cnt>
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
   // Indicate the end of argument list by setting  <typeId> to kInvalidDtId. 
489
   // Indicate the end of argument list by setting  <typeId> to kInvalidDtId. 
454
   // The memory for array based data types is dynamically allocated.
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
   // Returns a ptr to 'ele'.
494
   // Returns a ptr to 'ele'.
459
   cmData_t* cmDataListAppendEle( cmData_t* p, cmData_t* ele );
495
   cmData_t* cmDataListAppendEle( cmData_t* p, cmData_t* ele );
464
   cmData_t* cmDataListInsertEle( cmData_t* p, unsigned index, cmData_t* ele );
500
   cmData_t* cmDataListInsertEle( cmData_t* p, unsigned index, cmData_t* ele );
465
   cmData_t* cmDataListInsertEleN(cmData_t* p, unsigned index, cmData_t* ele[], unsigned n );
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
   // Record related functions
504
   // Record related functions
472
   //
505
   //
487
   unsigned        cmDataRecdKeyId(    cmData_t* p, unsigned index );
520
   unsigned        cmDataRecdKeyId(    cmData_t* p, unsigned index );
488
   const cmChar_t* cmDataRecdKeyLabel( cmData_t* p, unsigned index );
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
   // Append a pair node by linking the pair node 'pair' to the record node 'p'.
526
   // Append a pair node by linking the pair node 'pair' to the record node 'p'.
494
   // 'pair' is simply linked to 'p' via cmDataAppendChild() no 
527
   // 'pair' is simply linked to 'p' via cmDataAppendChild() no 
495
   // reallocation or duplicattion takes place.
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
   // Var-args format:
532
   // Var-args format:
500
-  // <label|id> <typeId>  <value> {<cnt>}
533
+  // <label|id> {<cid>} <typeId>  <value> {<cnt>}
501
   // scalar types: <value> is literal,<cnt> is not included
534
   // scalar types: <value> is literal,<cnt> is not included
502
   // null   type: has no <value> or <cnt>
535
   // null   type: has no <value> or <cnt>
503
   // ptr    types: <value> is pointer,  <cnt> is element count
536
   // ptr    types: <value> is pointer,  <cnt> is element count
529
   unsigned cmDataSerializeByteCount( const cmData_t* p );
562
   unsigned cmDataSerializeByteCount( const cmData_t* p );
530
   cmDtRC_t cmDataSerialize(   const cmData_t* p, void* buf, unsigned bufByteCnt );
563
   cmDtRC_t cmDataSerialize(   const cmData_t* p, void* buf, unsigned bufByteCnt );
531
   cmDtRC_t cmDataDeserialize( const void* buf, unsigned bufByteCnt, cmData_t** pp );
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
   void     cmDataPrint( const cmData_t* p, cmRpt_t* rpt );
582
   void     cmDataPrint( const cmData_t* p, cmRpt_t* rpt );
534
   
583
   
535
   void     cmDataTest( cmCtx_t* ctx );
584
   void     cmDataTest( cmCtx_t* ctx );
536
 
585
 
537
 
586
 
538
-
539
 #ifdef __cplusplus
587
 #ifdef __cplusplus
540
 }
588
 }
541
 #endif
589
 #endif

+ 4
- 0
cmGrPage.h View File

60
   // Draw the page.
60
   // Draw the page.
61
   void      cmGrPageDraw( cmGrPgH_t h, cmGrDcH_t dcH );
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
   typedef void (*cmGrLabelFunc_t)( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value );
66
   typedef void (*cmGrLabelFunc_t)( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value );
67
+
64
   // Returns id of the new page label function.
68
   // Returns id of the new page label function.
65
   unsigned         cmGrPageLabelFuncRegister( cmGrPgH_t h, cmGrLabelFunc_t func, void* arg, const cmChar_t* label );      
69
   unsigned         cmGrPageLabelFuncRegister( cmGrPgH_t h, cmGrLabelFunc_t func, void* arg, const cmChar_t* label );      
66
   unsigned         cmGrPageLabelFuncCount(    cmGrPgH_t h );
70
   unsigned         cmGrPageLabelFuncCount(    cmGrPgH_t h );

+ 84
- 89
cmLex.c View File

7
 #include "cmMallocDebug.h"
7
 #include "cmMallocDebug.h"
8
 #include "cmFile.h"
8
 #include "cmFile.h"
9
 
9
 
10
+enum
11
+{
12
+  kRealFloatLexFl   = 0x01,
13
+  kIntUnsignedLexFl = 0x02
14
+};
15
+
10
 typedef struct
16
 typedef struct
11
 {
17
 {
12
   unsigned        code;
18
   unsigned        code;
29
   { kMemAllocErrLexRC,     "An attempted memory allocation failed"},
35
   { kMemAllocErrLexRC,     "An attempted memory allocation failed"},
30
   { kEofRC,                "The end of the input text was encountered (this is a normal condition not an error)"},
36
   { kEofRC,                "The end of the input text was encountered (this is a normal condition not an error)"},
31
   { kInvalidLexTIdLexRC,   "An invalid token id was encountered."},
37
   { kInvalidLexTIdLexRC,   "An invalid token id was encountered."},
38
+  { kSignErrorLexRC,       "A signed integer has a 'u' or 'U' suffix."},
32
   { kInvalidLexRC,         "Unknown lexer error code." }
39
   { kInvalidLexRC,         "Unknown lexer error code." }
33
 };
40
 };
34
 
41
 
75
 
82
 
76
   cmChar_t*         textBuf;         // text buf used by cmLexSetFile()
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
 } cmLex;
86
 } cmLex;
79
 
87
 
80
 
88
 
148
   unsigned i  = 0;
156
   unsigned i  = 0;
149
   unsigned n  = 0;     // decimal point counter
157
   unsigned n  = 0;     // decimal point counter
150
   unsigned d  = 0;     // digit counter
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
   for(; i<cn && n<=1; ++i)
161
   for(; i<cn && n<=1; ++i)
154
   {
162
   {
170
   // if there was at least one digit and the next char is an 'e'
178
   // if there was at least one digit and the next char is an 'e'
171
   if( d>0 && i<cn && (cp[i] == 'e' || cp[i] == 'E') )
179
   if( d>0 && i<cn && (cp[i] == 'e' || cp[i] == 'E') )
172
   {
180
   {
173
-    d=0;
181
+    unsigned e=0;
174
     ++i;
182
     ++i;
175
     unsigned j = i;
183
     unsigned j = i;
176
 
184
 
185
+    fl = false;
186
+
177
     for(; i<cn; ++i)
187
     for(; i<cn; ++i)
178
     {
188
     {
179
       if( i==j && cp[i]=='-' ) // allow the char following the e to be '-'
189
       if( i==j && cp[i]=='-' ) // allow the char following the e to be '-'
181
 
191
 
182
       if( isdigit(cp[i]) )
192
       if( isdigit(cp[i]) )
183
       {
193
       {
194
+        ++e;
184
         ++d;
195
         ++d;
185
         continue;
196
         continue;
186
       }
197
       }
190
     }
201
     }
191
 
202
 
192
     // an exp exists if digits follwed the 'e'
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
 unsigned _cmLexIntMatcher(   cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
235
 unsigned _cmLexIntMatcher(   cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
201
 {
236
 {
202
   unsigned i = 0;
237
   unsigned i = 0;
203
   bool signFl = false;
238
   bool signFl = false;
239
+
204
   for(; i<cn; ++i)
240
   for(; i<cn; ++i)
205
   {
241
   {
206
     if( i==0 && cp[i]=='-' )
242
     if( i==0 && cp[i]=='-' )
222
   //
258
   //
223
   // The current implementation recognizes all numeric strings 
259
   // The current implementation recognizes all numeric strings 
224
   // containing a decimal point as reals. 
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
 unsigned _cmLexHexMatcher(   cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
292
 unsigned _cmLexHexMatcher(   cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
387
   
449
   
388
   _cmLexSetTextBuffer( p, cp, cn );
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
   int init_mfn       = 10;
452
   int init_mfn       = 10;
408
   p->mfp             = cmMemAllocZ( cmLexMatcher, init_mfn );
453
   p->mfp             = cmMemAllocZ( cmLexMatcher, init_mfn );
409
   p->mfn             = init_mfn;
454
   p->mfn             = init_mfn;
537
   return rc;
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
 cmLexMatcher* _cmLexFindUserToken( cmLex* p, unsigned id, const cmChar_t* tokenStr )
586
 cmLexMatcher* _cmLexFindUserToken( cmLex* p, unsigned id, const cmChar_t* tokenStr )
606
 {
587
 {
689
     p->curTokenId      = kErrorLexTId;
670
     p->curTokenId      = kErrorLexTId;
690
     p->curTokenCharIdx = cmInvalidIdx;
671
     p->curTokenCharIdx = cmInvalidIdx;
691
     p->curTokenCharCnt = 0;
672
     p->curTokenCharCnt = 0;
673
+    p->attrFlags       = 0;
692
 
674
 
693
-
694
-    // try each mater
675
+    // try each matcher
695
     for(; mi<p->mfi; ++mi)
676
     for(; mi<p->mfi; ++mi)
696
       if( p->mfp[mi].enableFl )
677
       if( p->mfp[mi].enableFl )
697
       {
678
       {
701
         else
682
         else
702
           charCnt = p->mfp[mi].userPtr( p->cp + p->ci, p->cn - p->ci);
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
         if( cmErrLastRC(&p->err) != kOkLexRC )
686
         if( cmErrLastRC(&p->err) != kOkLexRC )
705
           return kErrorLexTId;
687
           return kErrorLexTId;
706
 
688
 
823
 double             cmLexTokenDouble(        cmLexH h )
805
 double             cmLexTokenDouble(        cmLexH h )
824
 {  return strtod( cmLexTokenText(h),NULL ); }
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
 unsigned cmLexCurrentLineNumber( cmLexH h )
821
 unsigned cmLexCurrentLineNumber( cmLexH h )
827
 { 
822
 { 
828
   cmLex* p = _cmLexHandleToPtr(h);
823
   cmLex* p = _cmLexHandleToPtr(h);

+ 12
- 3
cmLex.h View File

50
   kMemAllocErrLexRC,       //< 10  An attempted memory allocation failed
50
   kMemAllocErrLexRC,       //< 10  An attempted memory allocation failed
51
   kEofRC,                  //< 11 The end of the input text was encountered (this is a normal condition not an error)
51
   kEofRC,                  //< 11 The end of the input text was encountered (this is a normal condition not an error)
52
   kInvalidLexTIdLexRC,     //< 12 An invalid lex token id was encountered.
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
 // Return the value of the current token as an integer.
120
 // Return the value of the current token as an integer.
120
 int                cmLexTokenInt( cmLexH h );
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
 unsigned           cmLexTokenUInt( cmLexH h );
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
 float              cmLexTokenFloat( cmLexH h );
127
 float              cmLexTokenFloat( cmLexH h );
127
 
128
 
128
 // Return the value of the current token as a double.
129
 // Return the value of the current token as a double.
129
 double             cmLexTokenDouble( cmLexH h );
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
 // Return the line number associated with the current token 
140
 // Return the line number associated with the current token 
132
 unsigned           cmLexCurrentLineNumber( cmLexH h );
141
 unsigned           cmLexCurrentLineNumber( cmLexH h );
133
 
142
 

+ 1
- 1
cmMidiFile.h View File

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

+ 353
- 0
cmProc4.c View File

4135
   
4135
   
4136
   return rc;
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 View File

626
   cmRC_t         cmScModulatorExec(  cmScModulator* p, unsigned scLocIdx );
626
   cmRC_t         cmScModulatorExec(  cmScModulator* p, unsigned scLocIdx );
627
   cmRC_t         cmScModulatorDump(  cmScModulator* p );
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
 #ifdef __cplusplus
678
 #ifdef __cplusplus
630
 }
679
 }
631
 #endif
680
 #endif

+ 3
- 0
cmStack.h View File

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

+ 1
- 0
dsp/cmDspBuiltIn.c View File

5418
   cmActiveMeasClassCons,
5418
   cmActiveMeasClassCons,
5419
   cmAmSyncClassCons,
5419
   cmAmSyncClassCons,
5420
   cmNanoMapClassCons,
5420
   cmNanoMapClassCons,
5421
+  cmRecdPlayClassCons,
5421
   NULL,
5422
   NULL,
5422
 };
5423
 };
5423
 
5424
 

+ 260
- 1
dsp/cmDspKr.c View File

572
   }
572
   }
573
 
573
 
574
   if((tlFn =  cmDspStrcz(inst, kFnScId )) !=  NULL )
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
       rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Score file open failed.");
576
       rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Score file open failed.");
577
 
577
 
578
  errLabel:
578
  errLabel:
2264
 
2264
 
2265
   return &_cmNanoMapDC;
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 View File

16
   struct cmDspClass_str* cmActiveMeasClassCons( cmDspCtx_t* ctx );
16
   struct cmDspClass_str* cmActiveMeasClassCons( cmDspCtx_t* ctx );
17
   struct cmDspClass_str* cmAmSyncClassCons( cmDspCtx_t* ctx );
17
   struct cmDspClass_str* cmAmSyncClassCons( cmDspCtx_t* ctx );
18
   struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx );
18
   struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx );
19
+  struct cmDspClass_str* cmRecdPlayClassCons( cmDspCtx_t* ctx );
19
 
20
 
20
 #ifdef __cplusplus
21
 #ifdef __cplusplus
21
 }
22
 }

+ 14
- 4
dsp/cmDspPgmKr.c View File

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

Loading…
Cancel
Save