Browse Source

cmXScore.c : Added code to parse grace note group information during 'reorder' processing.

Added _cmXScoreProcessGraceNotes() to position grace notes.
master
kevin 7 years ago
parent
commit
83734d9949
1 changed files with 313 additions and 155 deletions
  1. 313
    155
      app/cmXScore.c

+ 313
- 155
app/cmXScore.c View File

@@ -37,28 +37,31 @@ cmXsH_t cmXsNullHandle = cmSTATIC_NULL_HANDLE;
37 37
 
38 38
 enum
39 39
 {
40
-  kSectionXsFl   = 0x000001,  // rvalue holds section number
41
-  kBarXsFl       = 0x000002,
42
-  kRestXsFl      = 0x000004,
43
-  kGraceXsFl     = 0x000008,
44
-  kDotXsFl       = 0x000010,
45
-  kChordXsFl     = 0x000020,
46
-  kDynXsFl       = 0x000040,
47
-  kEvenXsFl      = 0x000080,
48
-  kTempoXsFl     = 0x000100,
49
-  kHeelXsFl      = 0x000200,
50
-  kTieBegXsFl    = 0x000400,
51
-  kTieEndXsFl    = 0x000800,
52
-  kTieProcXsFl   = 0x001000,
53
-  kDampDnXsFl    = 0x002000,
54
-  kDampUpXsFl    = 0x004000,
55
-  kDampUpDnXsFl  = 0x008000,
56
-  kSostDnXsFl    = 0x010000,
57
-  kSostUpXsFl    = 0x020000,
58
-  kMetronomeXsFl = 0x040000,  // duration holds BPM
59
-  kOnsetXsFl     = 0x080000,  // this is a sounding note
60
-  kBegGroupXsFl  = 0x100000,
61
-  kEndGroupXsFl  = 0x200000
40
+  kSectionXsFl     = 0x000001,  // rvalue holds section number
41
+  kBarXsFl         = 0x000002,
42
+  kRestXsFl        = 0x000004,
43
+  kGraceXsFl       = 0x000008,
44
+  kDotXsFl         = 0x000010,
45
+  kChordXsFl       = 0x000020,
46
+  kDynXsFl         = 0x000040,
47
+  kEvenXsFl        = 0x000080,
48
+  kTempoXsFl       = 0x000100,
49
+  kHeelXsFl        = 0x000200,
50
+  kTieBegXsFl      = 0x000400,
51
+  kTieEndXsFl      = 0x000800,
52
+  kTieProcXsFl     = 0x001000,
53
+  kDampDnXsFl      = 0x002000,
54
+  kDampUpXsFl      = 0x004000,
55
+  kDampUpDnXsFl    = 0x008000,
56
+  kSostDnXsFl      = 0x010000,
57
+  kSostUpXsFl      = 0x020000,
58
+  kMetronomeXsFl   = 0x040000,  // duration holds BPM
59
+  kOnsetXsFl       = 0x080000,  // this is a sounding note
60
+  kBegGroupXsFl    = 0x100000,
61
+  kEndGroupXsFl    = 0x200000,
62
+  kBegGraceXsFl    = 0x400000,  // beg grace note group
63
+  kEndGraceXsFl    = 0x800000   // end grace note group
64
+  
62 65
 };
63 66
 
64 67
 struct cmXsMeas_str;
@@ -87,6 +90,7 @@ typedef struct cmXsNote_str
87 90
   unsigned                    evenGroupId;   // eveness group id
88 91
   unsigned                    dynGroupId;    // dynamics group id
89 92
   unsigned                    tempoGroupId;  // tempo group id
93
+  unsigned                    graceGroupId;  // grace note group id
90 94
 
91 95
   struct cmXsVoice_str*       voice;    // voice this note belongs to
92 96
   struct cmXsMeas_str*        meas;     // measure this note belongs to
@@ -94,7 +98,8 @@ typedef struct cmXsNote_str
94 98
   const cmXmlNode_t*          xmlNode;  // note xml ptr
95 99
 
96 100
   struct cmXsNote_str*        tied;     // subsequent note tied to this note
97
-
101
+  struct cmXsNote_str*        grace;    // grace note groups link backward in time from the anchor note
102
+ 
98 103
   struct cmXsNote_str*        mlink;    // measure note list
99 104
   struct cmXsNote_str*        slink;    // time sorted event list
100 105
 
@@ -1459,6 +1464,89 @@ cmXsRC_t _cmXScoreProcessPedals( cmXScore_t* p )
1459 1464
   return rc;
1460 1465
 }
1461 1466
 
1467
+
1468
+// Adjust the locations of grace notes. Note that this must be done
1469
+// after reordering so that we can be sure that the order in time of
1470
+// the notes in each group has been set prior to building the
1471
+// grace note groups - which must be in reverse time order.
1472
+cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
1473
+{
1474
+  cmXsRC_t    rc = kOkXsRC;
1475
+  unsigned    graceGroupId = 1;
1476
+  
1477
+  for(; 1; ++graceGroupId)
1478
+  {
1479
+    cmXsNote_t* gnp         = NULL;
1480
+    cmXsPart_t* pp          = p->partL;
1481
+    double      ticksPerSec = 0;
1482
+    
1483
+    for(; pp!=NULL; pp=pp->link)
1484
+    {
1485
+      cmXsMeas_t* mp = pp->measL;
1486
+      for(; mp!=NULL; mp=mp->link)
1487
+      {
1488
+        cmXsNote_t* np = mp->noteL;        
1489
+        for(; np!=NULL; np=np->slink )
1490
+        {
1491
+          // notice change of tempo
1492
+          if( cmIsFlag(np->flags,kMetronomeXsFl) )
1493
+          {
1494
+            // ticks/sec = ticks/qn * qn/sec
1495
+            ticksPerSec  = mp->divisions * np->duration / 60.0;
1496
+          }
1497
+
1498
+          // if this note is part of the grace note group we are searching for
1499
+          if( np->graceGroupId == graceGroupId )
1500
+          {
1501
+            // add the note to the grace note list
1502
+            np->grace = gnp;
1503
+
1504
+            // set each grace note to have 1/20 of a second duration
1505
+            if( cmIsFlag(np->flags,kGraceXsFl) )
1506
+              np->duration = floor(ticksPerSec / 20.0);
1507
+
1508
+            gnp = np;
1509
+          }
1510
+        }
1511
+      }
1512
+    }
1513
+
1514
+    // no records were found for this grace id - we're done
1515
+    if( gnp == NULL )
1516
+      break;
1517
+
1518
+    cmXsNote_t* p0 = NULL;
1519
+    cmXsNote_t* p1 = gnp;
1520
+    
1521
+    for(; p1!=NULL; p1=p1->grace)
1522
+    {
1523
+      if(1)
1524
+      {
1525
+        const char* type = "g";
1526
+        if( cmIsFlag(p1->flags,kBegGraceXsFl) )
1527
+          type           = "b";
1528
+        
1529
+        if( cmIsFlag(p1->flags,kEndGraceXsFl) )
1530
+          type = "i";
1531
+        
1532
+        bool fl = p0 != NULL && p0->tick < p1->tick;
1533
+        printf("%3i %s %i %5i %i\n",p1->graceGroupId,type,p1->tick,p1->duration,fl);
1534
+      }
1535
+
1536
+      // TODO:
1537
+      // position grace notes here
1538
+
1539
+      
1540
+      
1541
+      p0 = p1;
1542
+    }
1543
+
1544
+    
1545
+
1546
+  }
1547
+  return rc;
1548
+}
1549
+
1462 1550
 cmXsRC_t cmXScoreInitialize( cmCtx_t* ctx, cmXsH_t* hp, const cmChar_t* xmlFn )
1463 1551
 {
1464 1552
   cmXsRC_t rc = kOkXsRC;
@@ -1558,11 +1646,13 @@ typedef struct
1558 1646
   float       rval;     //
1559 1647
   unsigned    midi;     //
1560 1648
   
1561
-  cmXsNote_t* note;     // The cmXsNode_t* associated with this cmXsReorder_t record
1649
+  cmXsNote_t* note;     // The cmXsNote_t* associated with this cmXsReorder_t record
1562 1650
   
1563 1651
   unsigned    dynIdx;    // cmInvalidIdx=ignore otherwise index into _cmXScoreDynMarkArray[]
1564
-  unsigned    newFlags;    // 0=ignore | kSostUp/DnXsFl | kDampUp/DnXsFl  | kTieEndXsFl
1652
+  unsigned    newFlags;  // 0=ignore | kSostUp/DnXsFl | kDampUp/DnXsFl  | kTieEndXsFl
1565 1653
   unsigned    newTick;   // 0=ignore >0 new tick value
1654
+  char        graceType; // 0=ignore g=grace note i=anchor note
1655
+  unsigned    graceGroupId; // 0=ignore >0=grace note group id
1566 1656
   unsigned    pitch;     // 0=ignore >0 new pitch
1567 1657
 } cmXsReorder_t;
1568 1658
 
@@ -1678,10 +1768,8 @@ cmXsRC_t _cmXScoreReorderMeas( cmXScore_t* p, unsigned measNumb, cmXsReorder_t*
1678 1768
 
1679 1769
   // set the 'note' field on each cmXsReorder_t record
1680 1770
   for(i=0; i<rN; ++i)
1681
-  {
1682 1771
     if((rV[i].note = _cmXsReorderFindNote(p,measNumb,rV+i,i)) == NULL )
1683 1772
       return kSyntaxErrorXsRC;
1684
-  }
1685 1773
   
1686 1774
   cmXsMeas_t* mp  = rV[0].note->meas;
1687 1775
   cmXsNote_t* n0p = NULL;
@@ -1719,6 +1807,25 @@ cmXsRC_t _cmXScoreReorderMeas( cmXScore_t* p, unsigned measNumb, cmXsReorder_t*
1719 1807
     // if a new note value was specified
1720 1808
     if( rV[i].pitch != 0 )
1721 1809
       rV[i].note->pitch = rV[i].pitch;
1810
+
1811
+    switch(rV[i].graceType)
1812
+    {
1813
+      case 'b':
1814
+        rV[i].note->flags = cmSetFlag(rV[i].note->flags,kBegGraceXsFl);
1815
+        break;
1816
+        
1817
+      case 'g':
1818
+        break;
1819
+        
1820
+      case 'a':
1821
+      case 's':
1822
+      case 'f':
1823
+        rV[i].note->flags = cmSetFlag(rV[i].note->flags,kEndGraceXsFl);
1824
+        break;
1825
+
1826
+    }
1827
+
1828
+    rV[i].note->graceGroupId = rV[i].graceGroupId;
1722 1829
     
1723 1830
     n0p        = rV[i].note;
1724 1831
     n0p->slink = NULL;
@@ -1897,6 +2004,36 @@ cmXsRC_t  _cmXScoreReorderParseTick(cmXScore_t* p, const cmChar_t* b, unsigned l
1897 2004
   return rc;
1898 2005
 }
1899 2006
 
2007
+cmXsRC_t  _cmXScoreReorderParseGrace(cmXScore_t* p, const cmChar_t* b, unsigned line, char* graceTypeRef )
2008
+{
2009
+  cmXsRC_t        rc = kOkXsRC;
2010
+  const cmChar_t* s;
2011
+
2012
+  *graceTypeRef = 0;
2013
+
2014
+  if((s = strchr(b,'%')) == NULL )
2015
+    return rc;
2016
+
2017
+  ++s;
2018
+
2019
+  switch(*s)
2020
+  {
2021
+    case 'b':
2022
+    case 'g':
2023
+    case 'a':
2024
+    case 's':
2025
+    case 'f':
2026
+      *graceTypeRef = *s;
2027
+      break;
2028
+
2029
+    default:
2030
+      { assert(0); }
2031
+  }
2032
+  
2033
+  return rc;
2034
+  
2035
+}
2036
+
1900 2037
 cmXsRC_t  _cmXScoreReorderParsePitch(cmXScore_t* p, const cmChar_t* b, unsigned line, unsigned* pitchRef )
1901 2038
 {
1902 2039
   cmXsRC_t rc = kOkXsRC;
@@ -1937,26 +2074,24 @@ cmXsRC_t  _cmXScoreReorderParsePitch(cmXScore_t* p, const cmChar_t* b, unsigned
1937 2074
   else
1938 2075
     rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"Pitch conversion from '%s' failed on line %i.",buf,line); 
1939 2076
 
1940
-  return rc;
1941
-  
2077
+  return rc;  
1942 2078
 }
1943 2079
 
1944
-
1945
-
1946 2080
 cmXsRC_t cmXScoreReorder( cmXsH_t h, const cmChar_t* fn )
1947 2081
 {
1948 2082
   typedef enum { kFindMeasStId, kFindEventStId, kReadEventStId } stateId_t;
1949 2083
 
1950
-  cmXsRC_t      rc      = kOkXsRC;
1951
-  cmXScore_t*   p       = _cmXScoreHandleToPtr(h);
1952
-  cmFileH_t     fH      = cmFileNullHandle;
1953
-  cmChar_t*     b       = NULL;
1954
-  unsigned      bN      = 0;
1955
-  unsigned      ln      = 0;
1956
-  stateId_t     stateId = kFindMeasStId;
1957
-  unsigned      rN      = 1024;
1958
-  unsigned      ri      = 0;
1959
-  unsigned     measNumb = 0;
2084
+  cmXsRC_t      rc       = kOkXsRC;
2085
+  cmXScore_t*   p        = _cmXScoreHandleToPtr(h);
2086
+  cmFileH_t     fH       = cmFileNullHandle;
2087
+  cmChar_t*     b        = NULL;
2088
+  unsigned      bN       = 0;
2089
+  unsigned      ln       = 0;
2090
+  stateId_t     stateId  = kFindMeasStId;
2091
+  unsigned      rN       = 1024;
2092
+  unsigned      ri       = 0;
2093
+  unsigned      measNumb = 0;
2094
+  unsigned      graceGroupId = 1;
1960 2095
   cmXsReorder_t rV[ rN ];
1961 2096
   
1962 2097
   if( cmFileOpen(&fH,fn,kReadFileFl,p->err.rpt) != kOkFileRC )
@@ -2029,10 +2164,27 @@ cmXsRC_t cmXScoreReorder( cmXsH_t h, const cmChar_t* fn )
2029 2164
             if((rc = _cmXScoreReorderParseTick(p, b, ln+1, &r.newTick)) != kOkXsRC )
2030 2165
               goto errLabel;
2031 2166
 
2167
+            // parse the %grace note marker
2168
+            if((rc = _cmXScoreReorderParseGrace(p, b, ln+1, &r.graceType)) != kOkXsRC )
2169
+              goto errLabel;
2170
+
2032 2171
             // parse the $pitch marker
2033 2172
             if((rc =  _cmXScoreReorderParsePitch(p, b, ln+1, &r.pitch )) != kOkXsRC )
2034 2173
               goto errLabel;
2035 2174
 
2175
+            // process grace notes - these need to be processed separate from
2176
+            // the _cmXScoreReorderMeas() because grace notes may cross measure boundaries.
2177
+            if( r.graceType != 0 )
2178
+            {
2179
+              r.graceGroupId = graceGroupId;
2180
+
2181
+              // if this is an end of a grace note group
2182
+              if( r.graceType != 'g' && r.graceType != 'b' )
2183
+              {
2184
+                graceGroupId += 1;
2185
+              }
2186
+              
2187
+            }
2036 2188
 
2037 2189
             // store the record
2038 2190
             assert( ri < rN );
@@ -2075,6 +2227,8 @@ cmXsRC_t cmXScoreReorder( cmXsH_t h, const cmChar_t* fn )
2075 2227
 
2076 2228
   // resort to force the links to be correct
2077 2229
   _cmXScoreSort(p);
2230
+
2231
+  _cmXScoreProcessGraceNotes( p );
2078 2232
   
2079 2233
  errLabel:
2080 2234
   cmFileClose(&fH);
@@ -2608,7 +2762,105 @@ void  cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl )
2608 2762
   }
2609 2763
 }
2610 2764
 
2611
-typedef struct cmXsMidiEvt_str
2765
+cmXsRC_t _cmXsWriteMidiFile( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const cmChar_t* fn )
2766
+{
2767
+  cmXsRC_t rc = kOkXsRC;
2768
+  cmXScore_t* p = _cmXScoreHandleToPtr(h);
2769
+  
2770
+  if( p->partL==NULL || p->partL->measL == NULL )
2771
+    return rc;
2772
+  
2773
+  cmMidiFileH_t   mfH        = cmMidiFileNullHandle;
2774
+  unsigned        trkN       = 2;
2775
+  unsigned        ticksPerQN = p->partL->measL->divisions;
2776
+  const cmChar_t* outFn      = cmFsMakeFn(dir,fn,"mid",NULL);
2777
+
2778
+  if( cmMidiFileCreate( ctx, &mfH, trkN, ticksPerQN ) != kOkMfRC )
2779
+    return cmErrMsg(&p->err,kMidiFailXsRC,"Unable to create the MIDI file object.");
2780
+  
2781
+  cmXsPart_t* pp = p->partL;
2782
+
2783
+  // for each part
2784
+  for(; pp!=NULL; pp=pp->link)
2785
+  {
2786
+    cmXsMeas_t* mp = pp->measL;
2787
+
2788
+    // for each measure
2789
+    for(; mp!=NULL; mp=mp->link)
2790
+    {
2791
+      cmXsNote_t* np = mp->noteL;
2792
+
2793
+      if( mp->divisions != ticksPerQN )
2794
+        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);
2795
+
2796
+      // for each note in this measure
2797
+      for(; np!=NULL; np=np->slink)
2798
+      {
2799
+        switch( np->flags & (kOnsetXsFl|kMetronomeXsFl|kDampDnXsFl|kDampUpDnXsFl|kSostDnXsFl) )
2800
+        {
2801
+          case kOnsetXsFl:
2802
+            if( cmMidiFileInsertTrackChMsg(mfH, 1, np->tick,                kNoteOnMdId,  np->pitch, np->vel ) != kOkMfRC
2803
+              ||cmMidiFileInsertTrackChMsg(mfH, 1, np->tick + np->duration, kNoteOffMdId, np->pitch, 0 ) != kOkMfRC )
2804
+            {
2805
+              rc = kMidiFailXsRC;
2806
+            }
2807
+
2808
+            break;
2809
+            
2810
+          case kDampDnXsFl:
2811
+          case kDampUpDnXsFl:
2812
+          case kSostDnXsFl:
2813
+            {
2814
+              cmMidiByte_t d0     = cmIsFlag(np->flags,kSostDnXsFl) ? kSostenutoCtlMdId : kSustainCtlMdId;              
2815
+              if( (cmMidiFileInsertTrackChMsg(mfH, 1, np->tick,                kCtlMdId, d0, 127 ) != kOkMfRC )
2816
+                ||(cmMidiFileInsertTrackChMsg(mfH, 1, np->tick + np->duration, kCtlMdId, d0,   0 ) != kOkMfRC ) )
2817
+              {
2818
+                rc = kMidiFailXsRC;
2819
+              }
2820
+            }
2821
+            break;
2822
+
2823
+          case kMetronomeXsFl:
2824
+            if( cmMidFileInsertTrackTempoMsg(mfH, 0, np->tick, np->duration ) != kOkMfRC )
2825
+              rc = kMidiFailXsRC;            
2826
+            break;
2827
+            
2828
+          case 0:
2829
+            break;
2830
+            
2831
+          default:
2832
+            { assert(0); }
2833
+        }
2834
+
2835
+        if( rc != kOkXsRC )
2836
+        {
2837
+          rc = cmErrMsg(&p->err,rc,"MIDI message insert failed on '%s'.",cmStringNullGuard(outFn));
2838
+          goto errLabel;
2839
+        }
2840
+      }
2841
+    }
2842
+  }
2843
+  
2844
+  if( cmMidiFileWrite(mfH,outFn) != kOkMfRC )
2845
+  {
2846
+    rc = cmErrMsg(&p->err,kMidiFailXsRC,"MIDI file write failed on '%s'.",cmStringNullGuard(outFn));
2847
+    goto errLabel;
2848
+  }
2849
+  
2850
+ errLabel:
2851
+  cmFsFreeFn(outFn);
2852
+  if( cmMidiFileClose(&mfH) != kOkMfRC )
2853
+  {
2854
+    rc = cmErrMsg(&p->err,kMidiFailXsRC,"Unable to create the MIDI file object.");
2855
+    goto errLabel;
2856
+  }
2857
+  
2858
+  return rc;
2859
+}
2860
+
2861
+
2862
+
2863
+typedef struct cmXsSvgEvt_str
2612 2864
 {
2613 2865
   unsigned         flags;     // k???XsFl
2614 2866
   unsigned         tick;      // start tick
@@ -2616,13 +2868,13 @@ typedef struct cmXsMidiEvt_str
2616 2868
   unsigned         voice;     // score voice number
2617 2869
   unsigned         d0;        // MIDI d0   (barNumb)
2618 2870
   unsigned         d1;        // MIDI d1
2619
-  struct cmXsMidiEvt_str* link;
2620
-} cmXsMidiEvt_t;
2871
+  struct cmXsSvgEvt_str* link;
2872
+} cmXsSvgEvt_t;
2621 2873
 
2622 2874
 typedef struct cmXsMidiFile_str
2623 2875
 {
2624
-  cmXsMidiEvt_t* elist;
2625
-  cmXsMidiEvt_t* eol;
2876
+  cmXsSvgEvt_t* elist;
2877
+  cmXsSvgEvt_t* eol;
2626 2878
 
2627 2879
   unsigned pitch_min;
2628 2880
   unsigned pitch_max;
@@ -2633,7 +2885,7 @@ cmXsRC_t _cmXsWriteMidiSvg( cmCtx_t* ctx, cmXScore_t* p, cmXsMidiFile_t* mf, con
2633 2885
 {
2634 2886
   cmXsRC_t        rc         = kOkXsRC;
2635 2887
   cmSvgH_t        svgH       = cmSvgNullHandle;
2636
-  cmXsMidiEvt_t*  e          = mf->elist;
2888
+  cmXsSvgEvt_t*  e          = mf->elist;
2637 2889
   unsigned        noteHeight = 10;
2638 2890
   const cmChar_t* svgFn      = cmFsMakeFn(dir,fn,"html",NULL);
2639 2891
   const cmChar_t* cssFn      = cmFsMakeFn(NULL,fn,"css",NULL);
@@ -2712,105 +2964,10 @@ cmXsRC_t _cmXsWriteMidiSvg( cmCtx_t* ctx, cmXScore_t* p, cmXsMidiFile_t* mf, con
2712 2964
   return rc;
2713 2965
 }
2714 2966
 
2715
-cmXsRC_t _cmXsWriteMidiFile( cmCtx_t* ctx, cmXScore_t* p, cmXsMidiFile_t* mf, const cmChar_t* dir, const cmChar_t* fn )
2716
-{
2717
-  cmXsRC_t rc = kOkXsRC;
2718
-  
2719
-  if( p->partL==NULL || p->partL->measL == NULL )
2720
-    return rc;
2721
-  
2722
-  cmMidiFileH_t   mfH        = cmMidiFileNullHandle;
2723
-  unsigned        trkN       = 2;
2724
-  unsigned        ticksPerQN = p->partL->measL->divisions;
2725
-  const cmChar_t* outFn      = cmFsMakeFn(dir,fn,"mid",NULL);
2726 2967
 
2727
-  if( cmMidiFileCreate( ctx, &mfH, trkN, ticksPerQN ) != kOkMfRC )
2728
-    return cmErrMsg(&p->err,kMidiFailXsRC,"Unable to create the MIDI file object.");
2729
-  
2730
-  cmXsPart_t* pp = p->partL;
2731
-
2732
-  // for each part
2733
-  for(; pp!=NULL; pp=pp->link)
2734
-  {
2735
-    cmXsMeas_t* mp = pp->measL;
2736
-
2737
-    // for each measure
2738
-    for(; mp!=NULL; mp=mp->link)
2739
-    {
2740
-      cmXsNote_t* np = mp->noteL;
2741
-
2742
-      if( mp->divisions != ticksPerQN )
2743
-        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);
2744
-
2745
-      // for each note in this measure
2746
-      for(; np!=NULL; np=np->slink)
2747
-      {
2748
-        switch( np->flags & (kOnsetXsFl|kMetronomeXsFl|kDampDnXsFl|kDampUpDnXsFl|kSostDnXsFl) )
2749
-        {
2750
-          case kOnsetXsFl:
2751
-            if( cmMidiFileInsertTrackChMsg(mfH, 1, np->tick,                kNoteOnMdId,  np->pitch, np->vel ) != kOkMfRC
2752
-              ||cmMidiFileInsertTrackChMsg(mfH, 1, np->tick + np->duration, kNoteOffMdId, np->pitch, 0 ) != kOkMfRC )
2753
-            {
2754
-              rc = kMidiFailXsRC;
2755
-            }
2756
-
2757
-            break;
2758
-            
2759
-          case kDampDnXsFl:
2760
-          case kDampUpDnXsFl:
2761
-          case kSostDnXsFl:
2762
-            {
2763
-              cmMidiByte_t d0     = cmIsFlag(np->flags,kSostDnXsFl) ? kSostenutoCtlMdId : kSustainCtlMdId;              
2764
-              if( (cmMidiFileInsertTrackChMsg(mfH, 1, np->tick,                kCtlMdId, d0, 127 ) != kOkMfRC )
2765
-                ||(cmMidiFileInsertTrackChMsg(mfH, 1, np->tick + np->duration, kCtlMdId, d0,   0 ) != kOkMfRC ) )
2766
-              {
2767
-                rc = kMidiFailXsRC;
2768
-              }
2769
-            }
2770
-            break;
2771
-
2772
-          case kMetronomeXsFl:
2773
-            if( cmMidFileInsertTrackTempoMsg(mfH, 0, np->tick, np->duration ) != kOkMfRC )
2774
-              rc = kMidiFailXsRC;            
2775
-            break;
2776
-            
2777
-          case 0:
2778
-            break;
2779
-            
2780
-          default:
2781
-            { assert(0); }
2782
-        }
2783
-
2784
-        if( rc != kOkXsRC )
2785
-        {
2786
-          rc = cmErrMsg(&p->err,rc,"MIDI message insert failed on '%s'.",cmStringNullGuard(outFn));
2787
-          goto errLabel;
2788
-        }
2789
-      }
2790
-    }
2791
-  }
2792
-  
2793
-  if( cmMidiFileWrite(mfH,outFn) != kOkMfRC )
2794
-  {
2795
-    rc = cmErrMsg(&p->err,kMidiFailXsRC,"MIDI file write failed on '%s'.",cmStringNullGuard(outFn));
2796
-    goto errLabel;
2797
-  }
2798
-  
2799
- errLabel:
2800
-  cmFsFreeFn(outFn);
2801
-  if( cmMidiFileClose(&mfH) != kOkMfRC )
2802
-  {
2803
-    rc = cmErrMsg(&p->err,kMidiFailXsRC,"Unable to create the MIDI file object.");
2804
-    goto errLabel;
2805
-  }
2806
-  
2807
-  return rc;
2808
-}
2809
-
2810
-
2811
-void _cmXsPushMidiEvent( cmXScore_t* p, cmXsMidiFile_t* mf, unsigned flags, unsigned tick, unsigned durTick, unsigned voice, unsigned d0, unsigned d1 )
2968
+void _cmXsPushSvgEvent( cmXScore_t* p, cmXsMidiFile_t* mf, unsigned flags, unsigned tick, unsigned durTick, unsigned voice, unsigned d0, unsigned d1 )
2812 2969
 {
2813
-  cmXsMidiEvt_t* e = cmLhAllocZ(p->lhH,cmXsMidiEvt_t,1);
2970
+  cmXsSvgEvt_t* e = cmLhAllocZ(p->lhH,cmXsSvgEvt_t,1);
2814 2971
   e->flags    = flags;
2815 2972
   e->tick     = tick;
2816 2973
   e->durTicks = durTick;
@@ -2832,17 +2989,14 @@ void _cmXsPushMidiEvent( cmXScore_t* p, cmXsMidiFile_t* mf, unsigned flags, unsi
2832 2989
   mf->eol = e;
2833 2990
 }
2834 2991
 
2835
-cmXsRC_t _cmXScoreGenMidi( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const cmChar_t* fn )
2992
+cmXsRC_t _cmXScoreGenSvg( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const cmChar_t* fn )
2836 2993
 {
2837 2994
   cmXScore_t* p  = _cmXScoreHandleToPtr(h);
2838 2995
   cmXsPart_t* pp = p->partL;
2839
-
2996
+  
2840 2997
   cmXsMidiFile_t mf;
2841 2998
   memset(&mf,0,sizeof(mf));
2842 2999
 
2843
-  // assign durations to pedal down events
2844
-  _cmXScoreProcessPedals(p);
2845
-
2846 3000
   for(; pp!=NULL; pp=pp->link)
2847 3001
   {
2848 3002
     const cmXsMeas_t* meas = pp->measL;
@@ -2856,7 +3010,7 @@ cmXsRC_t _cmXScoreGenMidi( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const c
2856 3010
         if( cmIsFlag(note->flags,kMetronomeXsFl) )
2857 3011
         {
2858 3012
           // set BPM as d0
2859
-          _cmXsPushMidiEvent(p,&mf,note->flags,note->tick,0,0,note->duration,0);
3013
+          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,0,0,note->duration,0);
2860 3014
           continue;
2861 3015
           
2862 3016
         }
@@ -2872,14 +3026,14 @@ cmXsRC_t _cmXScoreGenMidi( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const c
2872 3026
             for(; tn!=NULL; tn=tn->tied)
2873 3027
               durTick += tn->duration;
2874 3028
           }
2875
-          _cmXsPushMidiEvent(p,&mf,note->flags,note->tick,durTick,note->voice->id,d0,note->vel);
3029
+          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,durTick,note->voice->id,d0,note->vel);
2876 3030
           continue;
2877 3031
         }
2878 3032
 
2879 3033
         // if this is a bar event
2880 3034
         if( cmIsFlag(note->flags,kBarXsFl) )
2881 3035
         {
2882
-          _cmXsPushMidiEvent(p,&mf,note->flags,note->tick,0,0,note->meas->number,0);
3036
+          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,0,0,note->meas->number,0);
2883 3037
           continue;
2884 3038
         }
2885 3039
 
@@ -2887,7 +3041,7 @@ cmXsRC_t _cmXScoreGenMidi( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const c
2887 3041
         if( cmIsFlag(note->flags,kDampDnXsFl|kDampUpDnXsFl|kSostDnXsFl) )
2888 3042
         {
2889 3043
           unsigned d0 = cmIsFlag(note->flags,kSostDnXsFl) ? kSostenutoCtlMdId : kSustainCtlMdId;          
2890
-          _cmXsPushMidiEvent(p,&mf,note->flags,note->tick,note->duration,0,d0,127);
3044
+          _cmXsPushSvgEvent(p,&mf,note->flags,note->tick,note->duration,0,d0,127);
2891 3045
           continue;
2892 3046
         }
2893 3047
         
@@ -2895,7 +3049,6 @@ cmXsRC_t _cmXScoreGenMidi( cmCtx_t* ctx, cmXsH_t h, const cmChar_t* dir, const c
2895 3049
     }
2896 3050
   }
2897 3051
 
2898
-  _cmXsWriteMidiFile( ctx, p, &mf, dir, fn );
2899 3052
 
2900 3053
   return _cmXsWriteMidiSvg( ctx, p, &mf, dir, fn );
2901 3054
 
@@ -2916,6 +3069,9 @@ cmXsRC_t cmXScoreTest(
2916 3069
 
2917 3070
   if( reorderFn != NULL )
2918 3071
     cmXScoreReorder(h,reorderFn);
3072
+
3073
+  // assign durations to pedal down events
3074
+  _cmXScoreProcessPedals(_cmXScoreHandleToPtr(h));
2919 3075
   
2920 3076
   if( csvOutFn != NULL )
2921 3077
   {
@@ -2943,7 +3099,9 @@ cmXsRC_t cmXScoreTest(
2943 3099
   {
2944 3100
     cmFileSysPathPart_t* pp = cmFsPathParts(midiOutFn);
2945 3101
     
2946
-    _cmXScoreGenMidi( ctx, h, pp->dirStr, pp->fnStr );
3102
+    _cmXScoreGenSvg( ctx, h, pp->dirStr, pp->fnStr );
3103
+
3104
+    _cmXsWriteMidiFile(ctx, h, pp->dirStr, pp->fnStr );
2947 3105
 
2948 3106
     cmFsFreePathParts(pp);
2949 3107
     

Loading…
Cancel
Save