Browse Source

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

master
kevin 6 years ago
parent
commit
e0a683e8b1
9 changed files with 417 additions and 98 deletions
  1. 2
    2
      Makefile.am
  2. 1
    1
      app/cmMidiScoreFollow.c
  3. 217
    91
      app/cmXScore.c
  4. 5
    2
      app/cmXScore.h
  5. 1
    2
      cmFile.c
  6. 30
    0
      cmMidiFile.c
  7. 3
    0
      cmMidiFile.h
  8. 128
    0
      cmRptFile.c
  9. 30
    0
      cmRptFile.h

+ 2
- 2
Makefile.am View File

3
 cmHDR = 
3
 cmHDR = 
4
 cmSRC = 
4
 cmSRC = 
5
 
5
 
6
-cmHDR += src/libcm/cmErr.h src/libcm/cmCtx.h src/libcm/cmRpt.h src/libcm/cmGlobal.h src/libcm/cmComplexTypes.h src/libcm/cmFloatTypes.h src/libcm/cmPrefix.h
7
-cmSRC += src/libcm/cmErr.c src/libcm/cmCtx.c src/libcm/cmRpt.c src/libcm/cmGlobal.c src/libcm/cmComplexTypes.c
6
+cmHDR += src/libcm/cmErr.h src/libcm/cmCtx.h src/libcm/cmRpt.h src/libcm/cmRptFile.h src/libcm/cmGlobal.h src/libcm/cmComplexTypes.h src/libcm/cmFloatTypes.h src/libcm/cmPrefix.h
7
+cmSRC += src/libcm/cmErr.c src/libcm/cmCtx.c src/libcm/cmRpt.c src/libcm/cmRptFile.c src/libcm/cmGlobal.c src/libcm/cmComplexTypes.c
8
 
8
 
9
 cmHDR += src/libcm/cmSerialize.h src/libcm/cmSymTbl.h src/libcm/cmHashTbl.h src/libcm/cmFileSys.h src/libcm/cmFile.h 
9
 cmHDR += src/libcm/cmSerialize.h src/libcm/cmSymTbl.h src/libcm/cmHashTbl.h src/libcm/cmFileSys.h src/libcm/cmFile.h 
10
 cmSRC += src/libcm/cmSerialize.c src/libcm/cmSymTbl.c src/libcm/cmHashTbl.c src/libcm/cmFileSys.c src/libcm/cmFile.c 
10
 cmSRC += src/libcm/cmSerialize.c src/libcm/cmSymTbl.c src/libcm/cmHashTbl.c src/libcm/cmFileSys.c src/libcm/cmFile.c 

+ 1
- 1
app/cmMidiScoreFollow.c View File

269
 
269
 
270
   }
270
   }
271
 
271
 
272
-  //_cmMsf_ReportScoreErrors(&sfr, scH );
272
+  _cmMsf_ReportScoreErrors(&sfr, scH );
273
 
273
 
274
   //_cmMsf_ReportMidiErrors(&sfr, scH, m, mN);
274
   //_cmMsf_ReportMidiErrors(&sfr, scH, m, mN);
275
 
275
 

+ 217
- 91
app/cmXScore.c View File

69
   kNFirstGraceXsFl = 0x08000000,  // (n) grace notes start as soon as possible after first note and add time
69
   kNFirstGraceXsFl = 0x08000000,  // (n) grace notes start as soon as possible after first note and add time
70
   kDeleteXsFl      = 0x10000000,
70
   kDeleteXsFl      = 0x10000000,
71
   kDynBegForkXsFl  = 0x20000000,
71
   kDynBegForkXsFl  = 0x20000000,
72
-  kDynEndForkXsFl  = 0x40000000
72
+  kDynEndForkXsFl  = 0x40000000,
73
+
74
+  kDynEndXsFl   = 0x100000000,
75
+  kEvenEndXsFl  = 0x200000000,
76
+  kTempoEndXsFl = 0x400000000
73
   
77
   
74
 };
78
 };
75
 
79
 
90
 typedef struct cmXsNote_str
94
 typedef struct cmXsNote_str
91
 {
95
 {
92
   unsigned                    uid;      // unique id of this note record
96
   unsigned                    uid;      // unique id of this note record
93
-  unsigned                    flags;    // See k???XsFl
97
+  unsigned long long          flags;    // See k???XsFl
94
   unsigned                    pitch;    // midi pitch
98
   unsigned                    pitch;    // midi pitch
95
   unsigned                    dynamics; // dynamic level 1=pppp 9=fff
99
   unsigned                    dynamics; // dynamic level 1=pppp 9=fff
96
   unsigned                    vel;      // score specified MIDI velocity 
100
   unsigned                    vel;      // score specified MIDI velocity 
270
 }
274
 }
271
 
275
 
272
 
276
 
273
-void _cmXScoreRemoveNote( cmXsNote_t* note )
277
+cmXsRC_t  _cmXScoreRemoveNote( cmXsNote_t* note )
274
 {
278
 {
275
   cmXsNote_t* n0 = NULL;
279
   cmXsNote_t* n0 = NULL;
276
   cmXsNote_t* n1 = note->voice->noteL;
280
   cmXsNote_t* n1 = note->voice->noteL;
277
-  
281
+  unsigned    cnt = 0;
278
   for(; n1!=NULL; n1=n1->mlink)
282
   for(; n1!=NULL; n1=n1->mlink)
283
+  {
279
     if( n1->uid == note->uid )
284
     if( n1->uid == note->uid )
280
     {
285
     {
281
       if( n0 == NULL )
286
       if( n0 == NULL )
283
       else
288
       else
284
         n0->mlink = n1->mlink;
289
         n0->mlink = n1->mlink;
285
 
290
 
291
+      cnt = 1;
286
       break;
292
       break;
287
     }
293
     }
288
 
294
 
295
+    n0 = n1;
296
+  }
297
+  
289
   n0 = NULL;
298
   n0 = NULL;
290
   n1 = note->meas->noteL;
299
   n1 = note->meas->noteL;
291
   for(; n1!=NULL; n1=n1->slink)
300
   for(; n1!=NULL; n1=n1->slink)
301
+  {
292
     if( n1->uid == note->uid )
302
     if( n1->uid == note->uid )
293
     {
303
     {
294
       if( n0 == NULL )
304
       if( n0 == NULL )
296
       else
306
       else
297
         n0->slink = n1->slink;
307
         n0->slink = n1->slink;
298
 
308
 
309
+      cnt = 2;
299
       break;
310
       break;
300
     }
311
     }
312
+    
313
+    n0 = n1;
314
+  }
315
+  return cnt == 2 ? kOkXsRC : kSyntaxErrorXsRC;
301
  
316
  
302
 }
317
 }
303
 
318
 
304
 void _cmXScoreInsertNoteBefore( cmXsNote_t* note, cmXsNote_t* nn )
319
 void _cmXScoreInsertNoteBefore( cmXsNote_t* note, cmXsNote_t* nn )
305
 {
320
 {
321
+  assert( note != NULL );
322
+  
306
   // insert the new note into the voice list before 'note'
323
   // insert the new note into the voice list before 'note'
307
   cmXsNote_t* n0 = NULL;
324
   cmXsNote_t* n0 = NULL;
308
   cmXsNote_t* n1 = note->voice->noteL;
325
   cmXsNote_t* n1 = note->voice->noteL;
515
 
532
 
516
    typedef struct map_str
533
    typedef struct map_str
517
   {
534
   {
518
-    unsigned        value;
535
+    unsigned long long        value;
519
     const cmChar_t* label;
536
     const cmChar_t* label;
520
   } map_t;
537
   } map_t;
521
 
538
 
522
   map_t mapV[] =
539
   map_t mapV[] =
523
   {
540
   {
524
-    { kEvenXsFl,                         "#0000FF" },  // blue (even)
525
-    { kTempoXsFl,                        "#00FF00" },  // green (tempo)
526
-    { kDynXsFl,                          "#FF0000" },  // red   (dynamics)
527
-    { kTempoXsFl | kEvenXsFl,            "#00FFFF" },  // green + blue (turquoise)
528
-    { kDynXsFl   | kEvenXsFl,            "#FF00FF" },  // red   + blue
529
-    { kDynXsFl   | kEvenXsFl,            "#FF0CF7" },  // magenta (even+dyn)
530
-    { kDynXsFl   | kTempoXsFl,           "#FF7F00" },  // red   + green (brown)
531
-    { kTempoXsFl | kEvenXsFl | kDynXsFl, "#996633" },  // (purple)
532
-    { kDynXsFl,                          "#FF6A03" },  //   176 orange  (dynamics)
533
-    { kEvenXsFl,                         "#2F00E8" },  //  1001 blue (even)
534
-    { kTempoXsFl,                        "#01CD1F" },  //  1196 green   (tempo)
535
-    { kEvenXsFl,                         "#3600E8" },  //  1627 blue (even)
536
-    { kDynXsFl | kTempoXsFl,             "#9E8F15" },  //  8827 brown (dyn + tempo)
537
-    { kEvenXsFl,                         "#2E00E6" },  //  5393 blue (even)
538
-    { kEvenXsFl,                         "#2C00DD" },  //  5895 blue (even)
539
-    { kDynXsFl,                          "#FF5B03" },  //  6498 orange (dyn)
540
-    { kDynXsFl,                          "#FF6104" },  //  6896 orange
541
-    { kEvenXsFl,                         "#2A00E6" },  //  7781 blue
542
-    { kEvenXsFl,                         "#2300DD" },  //  8300 blue (even)
543
-    { kTempoXsFl,                        "#03CD22" },  // 10820 green (tempo)
544
-    { kEvenXsFl,                         "#3400DB" },  // 11627 blue (dyn)
541
+    { kEvenXsFl,                                       "#0000FF" },  // blue (even)
542
+    { kEvenXsFl  | kEvenEndXsFl,                       "#0000FE" },  // blue (even end)
543
+    { kEvenXsFl  | kEvenEndXsFl,                       "#0000FD" },  // blue (even end)
544
+    { kTempoXsFl,                                      "#00FF00" },  // green (tempo)
545
+    { kTempoXsFl | kTempoEndXsFl,                      "#00FE00" },  // green (tempo end)
546
+    { kDynXsFl,                                        "#FF0000" },  // red   (dynamics)
547
+    { kDynXsFl   | kDynEndXsFl,                        "#FE0000" },  // red   (dynamics end)
548
+    { kDynXsFl   | kDynEndXsFl,                        "#FD0000" },  // red   (dynamics end)
549
+    { kTempoXsFl | kEvenXsFl,                          "#00FFFF" },  // green + blue (turquoise)
550
+    { kTempoXsFl | kEvenXsFl | kEvenEndXsFl,           "#00FFFE" },  // green + blue (turquoise) (end)    
551
+    { kDynXsFl   | kEvenXsFl,                          "#FF00FF" },  // red   + blue
552
+    { kDynXsFl   | kEvenXsFl | kEvenEndXsFl,           "#FF00FE" },  // red   + blue (end)
553
+    { kDynXsFl   | kEvenXsFl | kEvenEndXsFl,           "#FF00FD" },  // red   + blue (end)    
554
+    { kDynXsFl   | kEvenXsFl,                          "#FF0CF7" },  // magenta (even+dyn)
555
+    { kDynXsFl   | kTempoXsFl,                         "#FF7F00" },  // red   + green (brown)
556
+    { kDynXsFl   | kTempoXsFl,                         "#FE7F00" },  // red   + green (brown)    (end)
557
+    { kDynXsFl   | kTempoXsFl,                         "#FD7F00" },  // red   + green (brown)    (end)
558
+    { kTempoXsFl | kEvenXsFl | kDynXsFl,               "#996633" },  // (purple)
559
+    { kTempoXsFl | kEvenXsFl | kDynXsFl | kDynEndXsFl, "#996632" },  // (purple)
560
+    { kDynXsFl,                                        "#FF6A03" },  //   176 orange  (dynamics)
561
+    { kEvenXsFl,                                       "#2F00E8" },  //  1001 blue (even)
562
+    { kTempoXsFl,                                      "#01CD1F" },  //  1196 green   (tempo)
563
+    { kEvenXsFl,                                       "#3600E8" },  //  1627 blue (even)
564
+    { kDynXsFl | kTempoXsFl,                           "#9E8F15" },  //  8827 brown (dyn + tempo)
565
+    { kEvenXsFl,                                       "#2E00E6" },  //  5393 blue (even)
566
+    { kEvenXsFl,                                       "#2C00DD" },  //  5895 blue (even)
567
+    { kDynXsFl,                                        "#FF5B03" },  //  6498 orange (dyn)
568
+    { kDynXsFl,                                        "#FF6104" },  //  6896 orange
569
+    { kEvenXsFl,                                       "#2A00E6" },  //  7781 blue
570
+    { kEvenXsFl,                                       "#2300DD" },  //  8300 blue (even)
571
+    { kTempoXsFl,                                      "#03CD22" },  // 10820 green (tempo)
572
+    { kEvenXsFl,                                       "#3400DB" },  // 11627 blue (dyn)
545
     { -1, "" }
573
     { -1, "" }
546
   };
574
   };
547
 
575
 
1785
     // grace note groups must have at least 3 members
1813
     // grace note groups must have at least 3 members
1786
     if( gN < 3 )
1814
     if( gN < 3 )
1787
     {
1815
     {
1788
-      rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"The grace not group (groupid=%i) ending in meas %i has fewer than 3 (%i) members.", gn1p->graceGroupId, gn1p->meas->number, gN );
1816
+      rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"The grace note group (groupid=%i) ending in meas %i has fewer than 3 (%i) members.", gn1p->graceGroupId, gn1p->meas->number, gN );
1789
       break;
1817
       break;
1790
     }
1818
     }
1791
     
1819
     
2130
   // remove deleted notes
2158
   // remove deleted notes
2131
   for(i=0; i<rN; ++i)
2159
   for(i=0; i<rN; ++i)
2132
     if( cmIsFlag(rV[i].newFlags,kDeleteXsFl) )
2160
     if( cmIsFlag(rV[i].newFlags,kDeleteXsFl) )
2133
-      _cmXScoreRemoveNote( rV[i].note );
2161
+      if( _cmXScoreRemoveNote( rV[i].note ) != kOkXsRC )
2162
+        return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Event marked to skip was not found in measure: %i",measNumb);
2134
       
2163
       
2135
   cmXsMeas_t* mp  = rV[0].note->meas;
2164
   cmXsMeas_t* mp  = rV[0].note->meas;
2136
   cmXsNote_t* n0p = NULL;
2165
   cmXsNote_t* n0p = NULL;
2214
 
2243
 
2215
 }
2244
 }
2216
 
2245
 
2217
-cmXsRC_t _cmXScoreReorderParseDyn(cmXScore_t* p, const cmChar_t* b, unsigned lineNumb, unsigned* dynIdxRef, unsigned* flagsRef )
2246
+cmXsRC_t _cmXScoreReorderParseDyn(cmXScore_t* p, const cmChar_t* b, unsigned lineNumb, unsigned* dynIdxRef, unsigned* flagsRef, int measNumb )
2218
 {
2247
 {
2219
   cmXsRC_t        rc        = kOkXsRC;
2248
   cmXsRC_t        rc        = kOkXsRC;
2220
   const cmChar_t* s         = NULL;
2249
   const cmChar_t* s         = NULL;
2239
 
2268
 
2240
   if( *s == '!')
2269
   if( *s == '!')
2241
   {
2270
   {
2271
+    //printf("E %3i %5i %s\n",measNumb,lineNumb,b);
2242
     endForkFl = true;
2272
     endForkFl = true;
2243
     ++s;      
2273
     ++s;      
2244
   }   
2274
   }   
2251
   if( isupper(*s) )
2281
   if( isupper(*s) )
2252
   {
2282
   {
2253
     if( !endForkFl)
2283
     if( !endForkFl)
2284
+    {
2254
       begForkFl=true;
2285
       begForkFl=true;
2286
+      //printf("B %3i %5i %s\n",measNumb,lineNumb,b);
2287
+      
2288
+    }
2255
   }
2289
   }
2256
   else
2290
   else
2257
   {
2291
   {
2431
         continue;
2465
         continue;
2432
         
2466
         
2433
       default:
2467
       default:
2434
-        { assert(0); }
2468
+        {
2469
+          return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Unexpected grace note reorder character code %c on line %i.",*s,line);
2470
+
2471
+          assert(0);
2472
+        }
2435
     }
2473
     }
2436
     
2474
     
2437
     break;
2475
     break;
2457
   ++s;
2495
   ++s;
2458
 
2496
 
2459
   j=2;
2497
   j=2;
2460
-  for(i=0; i<j && s[i]; ++i,++s)
2498
+  for(i=0; i<j && *s; ++i,++s)
2461
   {
2499
   {
2462
     buf[i] = *s;
2500
     buf[i] = *s;
2463
     
2501
     
2479
   if( pitch<kInvalidMidiByte)
2517
   if( pitch<kInvalidMidiByte)
2480
     *pitchRef = pitch;
2518
     *pitchRef = pitch;
2481
   else
2519
   else
2520
+  {
2482
     rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"Pitch conversion from '%s' failed on line %i.",buf,line); 
2521
     rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"Pitch conversion from '%s' failed on line %i.",buf,line); 
2483
-
2522
+  }
2484
   return rc;  
2523
   return rc;  
2485
 }
2524
 }
2486
 
2525
 
2563
               goto errLabel;
2602
               goto errLabel;
2564
 
2603
 
2565
             // parse the dynamic marking following a '!'
2604
             // parse the dynamic marking following a '!'
2566
-            if((rc = _cmXScoreReorderParseDyn(p,b,ln+1,&r.dynIdx, &r.newFlags)) != kOkXsRC )
2605
+            if((rc = _cmXScoreReorderParseDyn(p,b,ln+1,&r.dynIdx, &r.newFlags, measNumb)) != kOkXsRC )
2567
               goto errLabel;
2606
               goto errLabel;
2568
                         
2607
                         
2569
             // parse the @newtick marker
2608
             // parse the @newtick marker
3062
   return rc;
3101
   return rc;
3063
 }
3102
 }
3064
 
3103
 
3065
-cmXsRC_t cmXScoreWriteCsv( cmXsH_t h, const cmChar_t* csvFn )
3104
+cmXsRC_t cmXScoreWriteCsv( cmXsH_t h, int begMeasNumb, const cmChar_t* csvFn )
3066
 {
3105
 {
3067
   cmXsRC_t        rc           = kOkXsRC;
3106
   cmXsRC_t        rc           = kOkXsRC;
3068
   cmXScore_t*     p            = _cmXScoreHandleToPtr(h);
3107
   cmXScore_t*     p            = _cmXScoreHandleToPtr(h);
3069
   unsigned        rowIdx       = 1;
3108
   unsigned        rowIdx       = 1;
3070
   const cmChar_t* sectionIdStr = NULL;
3109
   const cmChar_t* sectionIdStr = NULL;
3110
+  double          baseSecs     = -1;
3071
 
3111
 
3072
   if( !cmCsvIsValid(p->csvH) )
3112
   if( !cmCsvIsValid(p->csvH) )
3073
     return cmErrMsg(&p->err,kCsvFailXsRC,"The CSV output object is not initialized.");
3113
     return cmErrMsg(&p->err,kCsvFailXsRC,"The CSV output object is not initialized.");
3079
   for(; pp!=NULL; pp=pp->link)
3119
   for(; pp!=NULL; pp=pp->link)
3080
   {
3120
   {
3081
     cmXsMeas_t* mp = pp->measL;
3121
     cmXsMeas_t* mp = pp->measL;
3122
+            
3082
     for(; mp!=NULL; mp=mp->link)
3123
     for(; mp!=NULL; mp=mp->link)
3083
     {
3124
     {
3125
+
3126
+      if( mp->number < begMeasNumb)
3127
+        continue;
3128
+      
3084
       cmXsNote_t* np = mp->noteL;
3129
       cmXsNote_t* np = mp->noteL;
3130
+
3131
+      if( baseSecs == -1 )
3132
+        baseSecs = np->secs;
3133
+      
3085
       for(; np!=NULL; np=np->slink)
3134
       for(; np!=NULL; np=np->slink)
3086
       {
3135
       {
3087
-
3136
+        double thisSecs = np->secs - baseSecs;
3137
+        
3088
         // if this is a section event
3138
         // if this is a section event
3089
         if( cmIsFlag(np->flags,kSectionXsFl) )
3139
         if( cmIsFlag(np->flags,kSectionXsFl) )
3090
           sectionIdStr = np->tvalue;
3140
           sectionIdStr = np->tvalue;
3092
         // if this is a bar event
3142
         // if this is a bar event
3093
         if( cmIsFlag(np->flags,kBarXsFl)  )
3143
         if( cmIsFlag(np->flags,kBarXsFl)  )
3094
         {
3144
         {
3095
-          _cmXScoreWriteCsvRow(p,rowIdx,-1,mp->number,sectionIdStr,"bar",np->dsecs,np->secs,0,0,-1,0,"",np->flags,"","");
3145
+          _cmXScoreWriteCsvRow(p,rowIdx,-1,mp->number,sectionIdStr,"bar",np->dsecs,thisSecs,0,0,-1,0,"",np->flags,"","");
3096
           sectionIdStr = NULL;
3146
           sectionIdStr = NULL;
3097
         }
3147
         }
3098
         else
3148
         else
3102
           {
3152
           {
3103
             unsigned d0 = cmIsFlag(np->flags,kSostDnXsFl |kSostUpXsFl) ? 66 : 64; // pedal MIDI ctl id
3153
             unsigned d0 = cmIsFlag(np->flags,kSostDnXsFl |kSostUpXsFl) ? 66 : 64; // pedal MIDI ctl id
3104
             unsigned d1 = cmIsFlag(np->flags,kDampDnXsFl|kSostDnXsFl) ? 64 : 0;  // pedal-dn: d1>=64 pedal-up:<64
3154
             unsigned d1 = cmIsFlag(np->flags,kDampDnXsFl|kSostDnXsFl) ? 64 : 0;  // pedal-dn: d1>=64 pedal-up:<64
3105
-            _cmXScoreWriteCsvRow(p,rowIdx,-1,mp->number,sectionIdStr,"ctl",np->dsecs,np->secs,d0,d1,-1,0,"",np->flags,"","");
3155
+            _cmXScoreWriteCsvRow(p,rowIdx,-1,mp->number,sectionIdStr,"ctl",np->dsecs,thisSecs,d0,d1,-1,0,"",np->flags,"","");
3106
             sectionIdStr = NULL;
3156
             sectionIdStr = NULL;
3107
             
3157
             
3108
             if( cmIsFlag(np->flags,kDampUpDnXsFl) )
3158
             if( cmIsFlag(np->flags,kDampUpDnXsFl) )
3109
             {
3159
             {
3110
               rowIdx += 1;
3160
               rowIdx += 1;
3111
               double millisecond = 0.0;
3161
               double millisecond = 0.0;
3112
-              _cmXScoreWriteCsvRow(p,rowIdx,-1,mp->number,sectionIdStr,"ctl",millisecond,np->secs+millisecond,d0,64,-1,0,"",np->flags,"","");
3162
+              _cmXScoreWriteCsvRow(p,rowIdx,-1,mp->number,sectionIdStr,"ctl",millisecond,thisSecs+millisecond,d0,64,-1,0,"",np->flags,"","");
3113
             }
3163
             }
3114
 
3164
 
3115
           }
3165
           }
3123
               cmChar_t ebuf[ bufN+1]; ebuf[bufN] = 0;
3173
               cmChar_t ebuf[ bufN+1]; ebuf[bufN] = 0;
3124
               cmChar_t dbuf[ bufN+1]; dbuf[bufN] = 0;
3174
               cmChar_t dbuf[ bufN+1]; dbuf[bufN] = 0;
3125
               cmChar_t tbuf[ bufN+1]; tbuf[bufN] = 0;
3175
               cmChar_t tbuf[ bufN+1]; tbuf[bufN] = 0;
3126
-              
3127
-              
3176
+                            
3128
               double          frac  = np->rvalue + (cmIsFlag(np->flags,kDotXsFl) ? (np->rvalue/2) : 0);
3177
               double          frac  = np->rvalue + (cmIsFlag(np->flags,kDotXsFl) ? (np->rvalue/2) : 0);
3129
               const cmChar_t* dyn   = _cmXScoreTranslateDynamics( p,  np, dbuf, bufN );
3178
               const cmChar_t* dyn   = _cmXScoreTranslateDynamics( p,  np, dbuf, bufN );
3130
               unsigned        vel   = np->vel==0 ? 60 : np->vel;
3179
               unsigned        vel   = np->vel==0 ? 60 : np->vel;
3131
 
3180
 
3132
-              //
3133
-              _cmXScoreWriteCsvRow(p,rowIdx,np->uid,mp->number,sectionIdStr,"non",np->dsecs,np->secs,np->pitch,vel,np->pitch,frac,dyn,np->flags,
3181
+              // 
3182
+              _cmXScoreWriteCsvRow(p,rowIdx,np->uid,mp->number,sectionIdStr,"non",np->dsecs,thisSecs,np->pitch,vel,np->pitch,frac,dyn,np->flags,
3134
                 cmXsFormatMeasurementCsvField(np->flags, kEvenXsFl, 'e', np->evenGroupId,  ebuf, bufN ),
3183
                 cmXsFormatMeasurementCsvField(np->flags, kEvenXsFl, 'e', np->evenGroupId,  ebuf, bufN ),
3135
                 cmXsFormatMeasurementCsvField(np->flags, kTempoXsFl,'t', np->tempoGroupId, tbuf, bufN ));
3184
                 cmXsFormatMeasurementCsvField(np->flags, kTempoXsFl,'t', np->tempoGroupId, tbuf, bufN ));
3136
               
3185
               
3157
   return rc;
3206
   return rc;
3158
 }
3207
 }
3159
 
3208
 
3209
+bool  _cmXsIsCsvValid(cmCtx_t* ctx, cmXsH_t h, const cmChar_t* outFn)
3210
+{
3211
+  bool        retFl = true;
3212
+  cmScH_t     scH   = cmScNullHandle;
3213
+  double      srate = 44100.0;
3214
+  cmSymTblH_t stH   = cmSymTblCreate(cmSymTblNullHandle, 0, ctx );
3215
+    
3216
+  if( cmScoreInitialize( ctx, &scH, outFn, srate, NULL, 0, NULL, NULL, stH) != kOkScRC )
3217
+  {
3218
+    cmErrMsg(&ctx->err,kFileFailXsRC,"The generated CSV file (%s) could not be parsed.",cmStringNullGuard(outFn));
3219
+    retFl = false;
3220
+  }
3221
+  else
3222
+  {
3223
+    //cmScorePrintSets(scH,&ctx->rpt);
3224
+    //cmScorePrint(scH,&ctx->rpt);
3225
+      
3226
+    cmScoreFinalize(&scH);
3227
+  }
3228
+
3229
+  cmSymTblDestroy(&stH);
3230
+
3231
+  return retFl;
3232
+}
3160
 
3233
 
3161
 void _cmXScoreReportTitle( cmRpt_t* rpt )
3234
 void _cmXScoreReportTitle( cmRpt_t* rpt )
3162
 {
3235
 {
3171
   const cmChar_t* G  = cmIsFlag(note->flags,kGraceXsFl)     ? "G" : "-";
3244
   const cmChar_t* G  = cmIsFlag(note->flags,kGraceXsFl)     ? "G" : "-";
3172
   const cmChar_t* D  = cmIsFlag(note->flags,kDotXsFl)       ? "." : "-";
3245
   const cmChar_t* D  = cmIsFlag(note->flags,kDotXsFl)       ? "." : "-";
3173
   const cmChar_t* C  = cmIsFlag(note->flags,kChordXsFl)     ? "C" : "-";
3246
   const cmChar_t* C  = cmIsFlag(note->flags,kChordXsFl)     ? "C" : "-";
3174
-  const cmChar_t* e  = cmIsFlag(note->flags,kEvenXsFl)      ? "e" : "-";
3175
-  const cmChar_t* d  = cmIsFlag(note->flags,kDynXsFl)       ? "d" : "-";
3176
-  const cmChar_t* t  = cmIsFlag(note->flags,kTempoXsFl)     ? "t" : "-";
3177
   const cmChar_t* P  = cmIsFlag(note->flags,kDampDnXsFl)    ? "V" : "-";
3247
   const cmChar_t* P  = cmIsFlag(note->flags,kDampDnXsFl)    ? "V" : "-";
3178
   const cmChar_t* s  = cmIsFlag(note->flags,kSostDnXsFl)    ? "{" : "-";
3248
   const cmChar_t* s  = cmIsFlag(note->flags,kSostDnXsFl)    ? "{" : "-";
3179
   const cmChar_t* S  = cmIsFlag(note->flags,kSectionXsFl)   ? "S" : "-";
3249
   const cmChar_t* S  = cmIsFlag(note->flags,kSectionXsFl)   ? "S" : "-";
3181
   const cmChar_t* T0 = cmIsFlag(note->flags,kTieBegXsFl)    ? "T" : "-";
3251
   const cmChar_t* T0 = cmIsFlag(note->flags,kTieBegXsFl)    ? "T" : "-";
3182
   const cmChar_t* T1 = cmIsFlag(note->flags,kTieEndXsFl)    ? "_" : "-";
3252
   const cmChar_t* T1 = cmIsFlag(note->flags,kTieEndXsFl)    ? "_" : "-";
3183
   const cmChar_t* O  = cmIsFlag(note->flags,kOnsetXsFl)     ? "*" : "-";
3253
   const cmChar_t* O  = cmIsFlag(note->flags,kOnsetXsFl)     ? "*" : "-";
3254
+
3255
+  const cmChar_t* e  = cmIsFlag(note->flags,kEvenXsFl)      ? "e" : "-";
3256
+  const cmChar_t* d  = cmIsFlag(note->flags,kDynXsFl)       ? "d" : "-";
3257
+  const cmChar_t* t  = cmIsFlag(note->flags,kTempoXsFl)     ? "t" : "-";
3258
+
3259
+  if( cmIsFlag(note->flags,kEvenEndXsFl) )  e="E";
3260
+  if( cmIsFlag(note->flags,kDynEndXsFl) )   d="D";
3261
+  if( cmIsFlag(note->flags,kTempoEndXsFl) ) t="T";
3262
+  
3184
   P = cmIsFlag(note->flags,kDampUpXsFl)   ? "^" : P;
3263
   P = cmIsFlag(note->flags,kDampUpXsFl)   ? "^" : P;
3185
   P = cmIsFlag(note->flags,kDampUpDnXsFl) ? "X" : P;
3264
   P = cmIsFlag(note->flags,kDampUpDnXsFl) ? "X" : P;
3186
   s = cmIsFlag(note->flags,kSostUpXsFl)    ? "}" : s;
3265
   s = cmIsFlag(note->flags,kSostUpXsFl)    ? "}" : s;
3226
 
3305
 
3227
   if( cmIsFlag(note->flags,kEndGraceXsFl) )
3306
   if( cmIsFlag(note->flags,kEndGraceXsFl) )
3228
     cmRptPrintf(rpt," E");
3307
     cmRptPrintf(rpt," E");
3229
-
3230
-
3308
+    
3231
   if( cmIsFlag(note->flags,kDynBegForkXsFl) )
3309
   if( cmIsFlag(note->flags,kDynBegForkXsFl) )
3232
     cmRptPrintf(rpt," B");
3310
     cmRptPrintf(rpt," B");
3233
 
3311
 
3234
   if( cmIsFlag(note->flags,kDynEndForkXsFl) )
3312
   if( cmIsFlag(note->flags,kDynEndForkXsFl) )
3235
     cmRptPrintf(rpt," E");
3313
     cmRptPrintf(rpt," E");
3236
-  */  
3314
+  */
3315
+    
3237
 }
3316
 }
3238
 
3317
 
3239
 
3318
 
3547
   return rc;
3626
   return rc;
3548
 }
3627
 }
3549
 
3628
 
3550
-cmXsRC_t _cmXsWriteMidiFile( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const cmChar_t* fn )
3629
+cmXsRC_t _cmXsWriteMidiFile( cmCtx_t* ctx, cmXsH_t h, int beginMeasNumb, int beginBPM, const cmChar_t* dir, const cmChar_t* fn )
3551
 {
3630
 {
3552
   cmXsRC_t rc = kOkXsRC;
3631
   cmXsRC_t rc = kOkXsRC;
3553
   cmXScore_t* p = _cmXScoreHandleToPtr(h);
3632
   cmXScore_t* p = _cmXScoreHandleToPtr(h);
3559
   unsigned        trkN       = 2;
3638
   unsigned        trkN       = 2;
3560
   unsigned        ticksPerQN = p->partL->measL->divisions;
3639
   unsigned        ticksPerQN = p->partL->measL->divisions;
3561
   const cmChar_t* outFn      = cmFsMakeFn(dir,fn,"mid",NULL);
3640
   const cmChar_t* outFn      = cmFsMakeFn(dir,fn,"mid",NULL);
3641
+  unsigned        baseTick   = -1;
3642
+  unsigned        bpm        = beginBPM==0 ? 60 : beginBPM;
3562
 
3643
 
3563
-  if( cmMidiFileCreate( ctx, &mfH, trkN, ticksPerQN ) != kOkMfRC )
3564
-    return cmErrMsg(&p->err,kMidiFailXsRC,"Unable to create the MIDI file object.");
3644
+  //if( cmMidiFileCreate( ctx, &mfH, trkN, ticksPerQN ) != kOkMfRC )
3645
+  //  return cmErrMsg(&p->err,kMidiFailXsRC,"Unable to create the MIDI file object.");
3565
   
3646
   
3566
   cmXsPart_t* pp = p->partL;
3647
   cmXsPart_t* pp = p->partL;
3567
 
3648
 
3573
     // for each measure
3654
     // for each measure
3574
     for(; mp!=NULL; mp=mp->link)
3655
     for(; mp!=NULL; mp=mp->link)
3575
     {
3656
     {
3657
+
3658
+      // skip all measures until we reach the first measure to output
3659
+      if(mp->number < beginMeasNumb)
3660
+        continue;
3661
+
3662
+      // if the MIDI file has not yet been created 
3663
+      if( !cmMidiFileIsValid(mfH) )
3664
+      {
3665
+        ticksPerQN = mp->divisions;
3666
+
3667
+        // create the MIDI file
3668
+        if( cmMidiFileCreate( ctx, &mfH, trkN, ticksPerQN ) != kOkMfRC )
3669
+        {
3670
+          rc = cmErrMsg(&p->err,kMidiFailXsRC,"Unable to create the MIDI file object.");
3671
+          goto errLabel;
3672
+        }
3673
+
3674
+        // set the starting tempo
3675
+        cmMidFileInsertTrackTempoMsg(mfH, 0, 0, bpm );
3676
+        
3677
+      }
3678
+      
3576
       cmXsNote_t* np = mp->noteL;
3679
       cmXsNote_t* np = mp->noteL;
3577
 
3680
 
3681
+      if( baseTick == -1 )
3682
+        baseTick = np->tick;
3683
+
3578
       if( mp->divisions != ticksPerQN )
3684
       if( mp->divisions != ticksPerQN )
3579
         cmErrWarnMsg(&p->err,kMidiFailXsRC,"The 'tick per quarter note' (divisions) field in measure %i does not match the value in the first measure (%i).",mp->divisions,ticksPerQN);
3685
         cmErrWarnMsg(&p->err,kMidiFailXsRC,"The 'tick per quarter note' (divisions) field in measure %i does not match the value in the first measure (%i).",mp->divisions,ticksPerQN);
3580
 
3686
 
3582
       // for each note in this measure
3688
       // for each note in this measure
3583
       for(; np!=NULL; np=np->slink,++ni)
3689
       for(; np!=NULL; np=np->slink,++ni)
3584
       {
3690
       {
3691
+        unsigned thisTick = np->tick - baseTick;
3692
+        
3585
         switch( np->flags & (kOnsetXsFl|kMetronomeXsFl|kDampDnXsFl|kDampUpDnXsFl|kSostDnXsFl) )
3693
         switch( np->flags & (kOnsetXsFl|kMetronomeXsFl|kDampDnXsFl|kDampUpDnXsFl|kSostDnXsFl) )
3586
         {
3694
         {
3587
           case kOnsetXsFl:
3695
           case kOnsetXsFl:
3696
+            if( cmMidiFileIsValid(mfH) )
3588
             {
3697
             {
3589
               if( np->tied_dur <= 0 )
3698
               if( np->tied_dur <= 0 )
3590
-                cmErrWarnMsg(&p->err,kOkXsRC,"A zero length note was encountered bar:%i tick:%i %s",np->meas->number,np->tick,cmMidiToSciPitch(np->pitch,NULL,0));
3699
+                cmErrWarnMsg(&p->err,kOkXsRC,"A zero length note was encountered bar:%i tick:%i (%i) %s",np->meas->number,np->tick,thisTick,cmMidiToSciPitch(np->pitch,NULL,0));
3591
 
3700
 
3592
               /*
3701
               /*
3593
               if( mp->number == 20 )
3702
               if( mp->number == 20 )
3596
                 cmRptPrintf(ctx->err.rpt,"\n");
3705
                 cmRptPrintf(ctx->err.rpt,"\n");
3597
               }
3706
               }
3598
               */
3707
               */
3599
-              
3600
-              if( cmMidiFileInsertTrackChMsg(mfH, 1, np->tick,                kNoteOnMdId,  np->pitch, np->vel ) != kOkMfRC
3601
-                ||cmMidiFileInsertTrackChMsg(mfH, 1, np->tick + np->tied_dur, kNoteOffMdId, np->pitch, 0 )       != kOkMfRC )
3708
+
3709
+              if( np->vel == 0 )
3710
+                cmErrWarnMsg(&p->err,kOkXsRC,"A sounding note with zero velocity was encountered at bar:%i tick:%i pitch:%s.",np->meas->number,np->tick,cmMidiToSciPitch(np->pitch,NULL,0));
3711
+                            
3712
+              if( cmMidiFileInsertTrackChMsg(mfH, 1, thisTick,                kNoteOnMdId,  np->pitch, np->vel ) != kOkMfRC
3713
+                ||cmMidiFileInsertTrackChMsg(mfH, 1, thisTick + np->tied_dur, kNoteOffMdId, np->pitch, 0 )       != kOkMfRC )
3602
               {
3714
               {
3603
                 rc = kMidiFailXsRC;
3715
                 rc = kMidiFailXsRC;
3604
               }
3716
               }
3608
           case kDampDnXsFl:
3720
           case kDampDnXsFl:
3609
           case kDampUpDnXsFl:
3721
           case kDampUpDnXsFl:
3610
           case kSostDnXsFl:
3722
           case kSostDnXsFl:
3723
+            if( cmMidiFileIsValid(mfH) )
3611
             {
3724
             {
3612
               if( np->duration <= 0 )
3725
               if( np->duration <= 0 )
3613
-                cmErrWarnMsg(&p->err,kOkXsRC,"A zero length pedal event was encountered bar:%i tick:%i",np->meas->number,np->tick);
3726
+                cmErrWarnMsg(&p->err,kOkXsRC,"A zero length pedal event was encountered bar:%i tick:%i (%i)",np->meas->number,np->tick,thisTick);
3614
               
3727
               
3615
               cmMidiByte_t d0     = cmIsFlag(np->flags,kSostDnXsFl) ? kSostenutoCtlMdId : kSustainCtlMdId;              
3728
               cmMidiByte_t d0     = cmIsFlag(np->flags,kSostDnXsFl) ? kSostenutoCtlMdId : kSustainCtlMdId;              
3616
-              if( (cmMidiFileInsertTrackChMsg(mfH, 1, np->tick,                kCtlMdId, d0, 127 ) != kOkMfRC )
3617
-                ||(cmMidiFileInsertTrackChMsg(mfH, 1, np->tick + np->duration, kCtlMdId, d0,   0 ) != kOkMfRC ) )
3729
+              if( (cmMidiFileInsertTrackChMsg(mfH, 1, thisTick,                kCtlMdId, d0, 127 ) != kOkMfRC )
3730
+                ||(cmMidiFileInsertTrackChMsg(mfH, 1, thisTick + np->duration, kCtlMdId, d0,   0 ) != kOkMfRC ) )
3618
               {
3731
               {
3619
                 rc = kMidiFailXsRC;
3732
                 rc = kMidiFailXsRC;
3620
               }
3733
               }
3622
             break;
3735
             break;
3623
 
3736
 
3624
           case kMetronomeXsFl:
3737
           case kMetronomeXsFl:
3625
-            if( cmMidFileInsertTrackTempoMsg(mfH, 0, np->tick, np->duration ) != kOkMfRC )
3626
-              rc = kMidiFailXsRC;            
3738
+            bpm = np->duration;
3739
+            if( cmMidiFileIsValid(mfH) )
3740
+              if( cmMidFileInsertTrackTempoMsg(mfH, 0, thisTick, bpm ) != kOkMfRC )
3741
+                rc = kMidiFailXsRC;            
3627
             break;
3742
             break;
3628
             
3743
             
3629
           case 0:
3744
           case 0:
3641
       }
3756
       }
3642
     }
3757
     }
3643
   }
3758
   }
3644
-  
3645
-  if( cmMidiFileWrite(mfH,outFn) != kOkMfRC )
3646
-  {
3647
-    rc = cmErrMsg(&p->err,kMidiFailXsRC,"MIDI file write failed on '%s'.",cmStringNullGuard(outFn));
3648
-    goto errLabel;
3649
-  }
3759
+
3760
+  if( cmMidiFileIsValid(mfH) )
3761
+    if( cmMidiFileWrite(mfH,outFn) != kOkMfRC )
3762
+    {
3763
+      rc = cmErrMsg(&p->err,kMidiFailXsRC,"MIDI file write failed on '%s'.",cmStringNullGuard(outFn));
3764
+      goto errLabel;
3765
+    }
3650
   
3766
   
3651
  errLabel:
3767
  errLabel:
3652
   cmFsFreeFn(outFn);
3768
   cmFsFreeFn(outFn);
3659
   return rc;
3775
   return rc;
3660
 }
3776
 }
3661
 
3777
 
3778
+bool _cmXsIsMidiFileValid( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const cmChar_t* fn )
3779
+{
3780
+  const cmChar_t* midiFn = cmFsMakeFn(dir,fn,"mid",NULL);
3781
+  cmMidiFileH_t mfH = cmMidiFileNullHandle;
3782
+  
3783
+  if( cmMidiFileOpen( ctx, &mfH, midiFn ) == kOkMfRC )
3784
+  {
3785
+    cmMidiFileClose(&mfH);
3786
+    return true;
3787
+  }
3788
+
3789
+  cmXScore_t* p = _cmXScoreHandleToPtr(h);
3790
+  cmErrMsg(&p->err,kMidiFailXsRC,"The generated MIDI file '%s' is not valid.", cmStringNullGuard(midiFn));
3791
+  
3792
+  return false;
3793
+}
3794
+
3662
 typedef struct cmXsSvgEvt_str
3795
 typedef struct cmXsSvgEvt_str
3663
 {
3796
 {
3664
   unsigned               flags;    // k???XsFl
3797
   unsigned               flags;    // k???XsFl
3864
   mf->eol = e;
3997
   mf->eol = e;
3865
 }
3998
 }
3866
 
3999
 
3867
-cmXsRC_t _cmXScoreGenSvg( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const cmChar_t* fn )
4000
+cmXsRC_t _cmXScoreGenSvg( cmCtx_t* ctx, cmXsH_t h, int beginMeasNumb, const cmChar_t* dir, const cmChar_t* fn )
3868
 {
4001
 {
3869
   cmXScore_t* p  = _cmXScoreHandleToPtr(h);
4002
   cmXScore_t* p  = _cmXScoreHandleToPtr(h);
3870
   cmXsPart_t* pp = p->partL;
4003
   cmXsPart_t* pp = p->partL;
3877
     const cmXsMeas_t* meas = pp->measL;
4010
     const cmXsMeas_t* meas = pp->measL;
3878
     for(; meas!=NULL; meas=meas->link)
4011
     for(; meas!=NULL; meas=meas->link)
3879
     {
4012
     {
4013
+      if( meas->number < beginMeasNumb )
4014
+        continue;
3880
 
4015
 
3881
       const cmXsNote_t* note = meas->noteL;
4016
       const cmXsNote_t* note = meas->noteL;
3882
       for(; note!=NULL; note=note->slink)
4017
       for(; note!=NULL; note=note->slink)
3929
 
4064
 
3930
 
4065
 
3931
 cmXsRC_t cmXScoreTest(
4066
 cmXsRC_t cmXScoreTest(
3932
-  cmCtx_t* ctx,
4067
+  cmCtx_t*        ctx,
3933
   const cmChar_t* xmlFn,
4068
   const cmChar_t* xmlFn,
3934
   const cmChar_t* editFn,
4069
   const cmChar_t* editFn,
3935
   const cmChar_t* csvOutFn,
4070
   const cmChar_t* csvOutFn,
3936
-  const cmChar_t* midiOutFn)
4071
+  const cmChar_t* midiOutFn,
4072
+  bool            reportFl,
4073
+  int             beginMeasNumb,
4074
+  int             beginBPM )
3937
 {
4075
 {
3938
   cmXsRC_t rc;
4076
   cmXsRC_t rc;
3939
   cmXsH_t h = cmXsNullHandle;
4077
   cmXsH_t h = cmXsNullHandle;
3952
 
4090
 
3953
   if( csvOutFn != NULL )
4091
   if( csvOutFn != NULL )
3954
   {
4092
   {
3955
-    cmScH_t scH = cmScNullHandle;
3956
-    double srate = 44100.0;
3957
     
4093
     
3958
-    cmXScoreWriteCsv(h,csvOutFn);
4094
+    cmXScoreWriteCsv(h,beginMeasNumb,csvOutFn);
3959
 
4095
 
3960
-    cmSymTblH_t stH = cmSymTblCreate(cmSymTblNullHandle, 0, ctx );
3961
-    
3962
-    if( cmScoreInitialize( ctx, &scH, csvOutFn, srate, NULL, 0, NULL, NULL, stH) != kOkScRC )
3963
-      cmErrMsg(&ctx->err,kFileFailXsRC,"The generated CSV file could not be parsed.");
3964
-    else
3965
-    {
3966
-      //cmScorePrintSets(scH,&ctx->rpt);
3967
-      //cmScorePrint(scH,&ctx->rpt);
3968
-      
3969
-      cmScoreFinalize(&scH);
3970
-    }
3971
-
3972
-    cmSymTblDestroy(&stH); 
4096
+    _cmXsIsCsvValid(ctx,h,csvOutFn);
3973
   }
4097
   }
3974
   
4098
   
3975
   if( midiOutFn != NULL )
4099
   if( midiOutFn != NULL )
3976
   {
4100
   {
3977
-
3978
     // measure the score complexity
4101
     // measure the score complexity
3979
     double wndSecs = 1.0;
4102
     double wndSecs = 1.0;
4103
+    
3980
     _cmXsMeasComplexity(h,wndSecs);
4104
     _cmXsMeasComplexity(h,wndSecs);
3981
-
3982
     
4105
     
3983
     cmFileSysPathPart_t* pp = cmFsPathParts(midiOutFn);
4106
     cmFileSysPathPart_t* pp = cmFsPathParts(midiOutFn);
3984
 
4107
 
3985
-    _cmXsWriteMidiFile(ctx, h, pp->dirStr, pp->fnStr );
4108
+    _cmXsWriteMidiFile(ctx, h, beginMeasNumb, beginBPM, pp->dirStr, pp->fnStr );
3986
     
4109
     
3987
-    _cmXScoreGenSvg( ctx, h, pp->dirStr, pp->fnStr );
4110
+    _cmXsIsMidiFileValid(ctx, h, pp->dirStr, pp->fnStr );
4111
+    
4112
+    _cmXScoreGenSvg( ctx, h, beginMeasNumb, pp->dirStr, pp->fnStr );
3988
 
4113
 
3989
     cmFsFreePathParts(pp);
4114
     cmFsFreePathParts(pp);
3990
     
4115
     
3991
   }
4116
   }
3992
-  
3993
-  cmXScoreReport(h,&ctx->rpt,true);
4117
+
4118
+  if(reportFl)
4119
+    cmXScoreReport(h,&ctx->rpt,true);
3994
 
4120
 
3995
   return cmXScoreFinalize(&h);
4121
   return cmXScoreFinalize(&h);
3996
 
4122
 

+ 5
- 2
app/cmXScore.h View File

53
   
53
   
54
   bool     cmXScoreIsValid( cmXsH_t h );
54
   bool     cmXScoreIsValid( cmXsH_t h );
55
 
55
 
56
-  cmXsRC_t cmXScoreWriteCsv( cmXsH_t h, const cmChar_t* csvFn );
56
+  cmXsRC_t cmXScoreWriteCsv( cmXsH_t h, int beginMeasNumb, const cmChar_t* csvFn );
57
 
57
 
58
   void     cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl );
58
   void     cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl );
59
 
59
 
69
   // internal call to cmXScoreGenEditFile().  This file can then be edited
69
   // internal call to cmXScoreGenEditFile().  This file can then be edited
70
   // to include the additional score file information and passed back by a later
70
   // to include the additional score file information and passed back by a later
71
   // call to this same function.
71
   // call to this same function.
72
-  cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* reorderFn, const cmChar_t* csvOutFn, const cmChar_t* midiOutFn );
72
+  // Set reportFl to true to print a report of the score following processing.
73
+  // Set begMeasNumb to the first measure the to be written to the output csv, MIDI and SVG files.
74
+  // Set begBPM to 0 to use the tempo from the score otherwise set it to the tempo at begMeasNumb.
75
+  cmXsRC_t cmXScoreTest( cmCtx_t* ctx, const cmChar_t* xmlFn, const cmChar_t* reorderFn, const cmChar_t* csvOutFn, const cmChar_t* midiOutFn, bool reportFl, int begMeasNumb, int begBPM );
73
   
76
   
74
 #ifdef __cplusplus
77
 #ifdef __cplusplus
75
 }
78
 }

+ 1
- 2
cmFile.c View File

1
-
2
 #include "cmPrefix.h"
1
 #include "cmPrefix.h"
3
 #include "cmGlobal.h"
2
 #include "cmGlobal.h"
4
 #include "cmRpt.h"
3
 #include "cmRpt.h"
11
 #include "cmLinkedHeap.h"
10
 #include "cmLinkedHeap.h"
12
 #include "cmText.h"
11
 #include "cmText.h"
13
 #include <sys/stat.h>
12
 #include <sys/stat.h>
14
-cmFileH_t cmFileNullHandle = { NULL };
13
+cmFileH_t cmFileNullHandle = cmSTATIC_NULL_HANDLE;
15
 
14
 
16
 typedef struct 
15
 typedef struct 
17
 {
16
 {

+ 30
- 0
cmMidiFile.c View File

4
 #include "cmErr.h"
4
 #include "cmErr.h"
5
 #include "cmCtx.h"
5
 #include "cmCtx.h"
6
 #include "cmFile.h"
6
 #include "cmFile.h"
7
+#include "cmRptFile.h"
7
 #include "cmMem.h"
8
 #include "cmMem.h"
8
 #include "cmMallocDebug.h"
9
 #include "cmMallocDebug.h"
9
 #include "cmLinkedHeap.h"
10
 #include "cmLinkedHeap.h"
2071
   return rc;
2072
   return rc;
2072
 }
2073
 }
2073
 
2074
 
2075
+cmMfRC_t  cmMidiFileReport(     cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outTextFn )
2076
+{
2077
+  cmMidiFileH_t mfH = cmMidiFileNullHandle;
2078
+  cmRptFileH_t  rptH = cmRptFileNullHandle;
2079
+  cmMfRC_t rc;
2080
+  
2081
+  if((rc = cmMidiFileOpen(ctx,&mfH,midiFn)) != kOkMfRC )
2082
+  {
2083
+    rc = cmErrMsg(&ctx->err,rc,"Unable to open the MIDI file: %s\n",cmStringNullGuard(midiFn));
2084
+    goto errLabel;
2085
+  }
2086
+
2087
+  if(( rc = cmRptFileCreate(ctx,&rptH, outTextFn, NULL )) != kOkRfRC )
2088
+  {
2089
+    rc = cmErrMsg(&ctx->err,rc,"Unable to open the report file: %s\n",cmStringNullGuard(outTextFn));
2090
+    goto errLabel;
2091
+    
2092
+  }
2093
+
2094
+  cmMidiFilePrintMsgs(mfH, cmRptFileRpt(rptH) );
2095
+
2096
+ errLabel:
2097
+  cmRptFileClose(&rptH);
2098
+  cmMidiFileClose(&mfH);
2099
+
2100
+  return rc;
2101
+}
2102
+
2103
+
2074
 void cmMidiFilePrintControlNumbers( cmCtx_t* ctx, const char* fn )
2104
 void cmMidiFilePrintControlNumbers( cmCtx_t* ctx, const char* fn )
2075
 {
2105
 {
2076
   cmMidiFileH_t h = cmMidiFileNullHandle;
2106
   cmMidiFileH_t h = cmMidiFileNullHandle;

+ 3
- 0
cmMidiFile.h View File

231
 
231
 
232
   cmMfRC_t             cmMidiFileGenSvgFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outSvgFn, const cmChar_t* cssFn );
232
   cmMfRC_t             cmMidiFileGenSvgFile( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outSvgFn, const cmChar_t* cssFn );
233
 
233
 
234
+  // Generate a text file reportusing cmMIdiFilePrintMsgs()
235
+  cmMfRC_t             cmMidiFileReport(     cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* outTextFn );
236
+
234
   void                  cmMidiFileTest( const char* fn, cmCtx_t* ctx );
237
   void                  cmMidiFileTest( const char* fn, cmCtx_t* ctx );
235
 
238
 
236
 
239
 

+ 128
- 0
cmRptFile.c View File

1
+#include "cmPrefix.h"
2
+#include "cmGlobal.h"
3
+#include "cmRpt.h"
4
+#include "cmErr.h"
5
+#include "cmCtx.h"
6
+#include "cmFile.h"
7
+#include "cmMem.h"
8
+#include "cmMallocDebug.h"
9
+#include "cmRptFile.h"
10
+
11
+cmRptFileH_t cmRptFileNullHandle = cmSTATIC_NULL_HANDLE;
12
+
13
+typedef struct
14
+{
15
+  cmErr_t   err;
16
+  cmFileH_t printFileH;
17
+  cmFileH_t errorFileH;
18
+  cmRpt_t   rpt;
19
+  
20
+} cmRptFile_t;
21
+
22
+cmRptFile_t* _cmRptFileHandleToPtr( cmRptFileH_t h )
23
+{
24
+  cmRptFile_t* p = (cmRptFile_t*)h.h;
25
+  assert(p != NULL );
26
+  return p;
27
+}
28
+
29
+void _cmRptFilePrintFunc(void* cmRptUserPtr, const cmChar_t* text)
30
+{
31
+  cmRptFile_t* p = (cmRptFile_t*)cmRptUserPtr;
32
+  if( cmFileIsValid(p->printFileH))
33
+    cmFilePrint(p->printFileH,text);
34
+}
35
+
36
+void _cmRptFileErrorFunc(void* cmRptUserPtr, const cmChar_t* text)
37
+{
38
+  cmRptFile_t* p = (cmRptFile_t*)cmRptUserPtr;
39
+  if( cmFileIsValid(p->errorFileH))
40
+    cmFilePrint(p->errorFileH,text);
41
+}
42
+
43
+cmRfRC_t _cmRptFileClose( cmRptFile_t* p )
44
+{
45
+  if( cmFileClose( &p->printFileH ) != kOkFileRC )
46
+    cmErrMsg(&p->err,kFileFailRfRC,"Unable to close the print file.");
47
+
48
+  if( cmFileClose( &p->errorFileH ) != kOkFileRC )
49
+    cmErrMsg(&p->err,kFileFailRfRC,"Unable to close the error file.");
50
+  
51
+  cmMemFree(p);
52
+  
53
+  return kOkRfRC;
54
+}
55
+
56
+cmRfRC_t cmRptFileCreate( cmCtx_t* ctx, cmRptFileH_t* hp, const cmChar_t* printFn, const cmChar_t* errorFn )
57
+{
58
+  cmRptPrintFunc_t printFunc = NULL;
59
+  cmRptPrintFunc_t errorFunc = NULL;
60
+  cmRfRC_t rc;
61
+  if((rc = cmRptFileClose(hp)) != kOkRfRC )
62
+    return rc;
63
+
64
+  cmRptFile_t* p = cmMemAllocZ( cmRptFile_t, 1 );
65
+  
66
+  cmErrSetup(&p->err,&ctx->rpt,"Rpt File");
67
+  
68
+  if( printFn != NULL )
69
+  {
70
+    if((rc = cmFileOpen(&p->printFileH,printFn,kWriteFileFl,p->err.rpt)) == kOkFileRC )
71
+      printFunc = _cmRptFilePrintFunc;
72
+    else
73
+    {
74
+      rc = cmErrMsg(&p->err,kFileFailRfRC,"Unable to open the print file '%s'.", cmStringNullGuard(printFn));
75
+      goto errLabel;
76
+    }
77
+  }
78
+  
79
+  if( errorFn != NULL )
80
+  {
81
+    if((rc = cmFileOpen(&p->errorFileH,errorFn,kWriteFileFl,p->err.rpt)) == kOkFileRC )
82
+      errorFunc = _cmRptFileErrorFunc;
83
+    else
84
+    {
85
+      rc = cmErrMsg(&p->err,kFileFailRfRC,"Unable to open the error file '%s'.", cmStringNullGuard(errorFn));
86
+      goto errLabel;
87
+    }
88
+  }
89
+  
90
+  if( errorFunc == NULL )
91
+    errorFunc = printFunc;
92
+
93
+  cmRptSetup(&p->rpt,printFunc,errorFunc,p);
94
+
95
+  hp->h = p;
96
+  
97
+ errLabel:
98
+  if( rc != kOkRfRC )
99
+    _cmRptFileClose(p);
100
+
101
+  return rc;
102
+}
103
+
104
+cmRfRC_t     cmRptFileClose( cmRptFileH_t* hp )
105
+{
106
+  cmRfRC_t rc = kOkRfRC;
107
+  
108
+  if( hp==NULL || cmRptFileIsValid(*hp)==false)
109
+    return rc;
110
+
111
+  cmRptFile_t* p = _cmRptFileHandleToPtr( *hp );
112
+
113
+  if((rc = _cmRptFileClose(p)) != kOkRfRC )
114
+    return rc;
115
+
116
+  hp->h = NULL;
117
+  
118
+  return rc;
119
+}
120
+
121
+bool         cmRptFileIsValid( cmRptFileH_t h )
122
+{ return h.h != NULL; }
123
+    
124
+cmRpt_t*     cmRptFileRpt( cmRptFileH_t h )
125
+{
126
+  cmRptFile_t* p = _cmRptFileHandleToPtr( h );
127
+  return &p->rpt;
128
+}

+ 30
- 0
cmRptFile.h View File

1
+#ifndef cmRptFile_h
2
+#define cmRptFile_h
3
+
4
+#ifdef __cplusplus
5
+extern "C" {
6
+#endif
7
+
8
+  enum
9
+  {
10
+    kOkRfRC = cmOkRC,
11
+    kFileFailRfRC
12
+  };
13
+
14
+  typedef unsigned   cmRfRC_t;
15
+  typedef cmHandle_t cmRptFileH_t;
16
+
17
+  extern cmRptFileH_t cmRptFileNullHandle;
18
+
19
+  cmRfRC_t cmRptFileCreate( cmCtx_t* ctx, cmRptFileH_t* hp, const cmChar_t* printFn, const cmChar_t* errorFn );
20
+  cmRfRC_t cmRptFileClose( cmRptFileH_t* hp );
21
+  
22
+  bool     cmRptFileIsValid( cmRptFileH_t h );
23
+    
24
+  cmRpt_t* cmRptFileRpt( cmRptFileH_t h );
25
+
26
+#ifdef __cplusplus
27
+}
28
+#endif
29
+
30
+#endif

Loading…
Cancel
Save