Browse Source

cmXScore.c : Added _cmXScoreGraceInsertTimeXXX().

master
kevin 8 years ago
parent
commit
be6dc19ade
1 changed files with 120 additions and 58 deletions
  1. 120
    58
      app/cmXScore.c

+ 120
- 58
app/cmXScore.c View File

37
 
37
 
38
 enum
38
 enum
39
 {
39
 {
40
-  kSectionXsFl     = 0x0000001,  // rvalue holds section number
41
-  kBarXsFl         = 0x0000002,
42
-  kRestXsFl        = 0x0000004,
43
-  kGraceXsFl       = 0x0000008,
44
-  kDotXsFl         = 0x0000010,
45
-  kChordXsFl       = 0x0000020,
46
-  kDynXsFl         = 0x0000040,
47
-  kEvenXsFl        = 0x0000080,
48
-  kTempoXsFl       = 0x0000100,
49
-  kHeelXsFl        = 0x0000200,
50
-  kTieBegXsFl      = 0x0000400,
51
-  kTieEndXsFl      = 0x0000800,
52
-  kTieProcXsFl     = 0x0001000,
53
-  kDampDnXsFl      = 0x0002000,
54
-  kDampUpXsFl      = 0x0004000,
55
-  kDampUpDnXsFl    = 0x0008000,
56
-  kSostDnXsFl      = 0x0010000,
57
-  kSostUpXsFl      = 0x0020000,
58
-  kMetronomeXsFl   = 0x0040000,  // duration holds BPM
59
-  kOnsetXsFl       = 0x0080000,  // this is a sounding note
60
-  kBegGroupXsFl    = 0x0100000,
61
-  kEndGroupXsFl    = 0x0200000,
62
-  kBegGraceXsFl    = 0x0400000,  // beg grace note group
63
-  kEndGraceXsFl    = 0x0800000,  // end grace note group
64
-  kAddGraceXsFl    = 0x1000000,  // end grace note group operator flag - add time
65
-  kSubGraceXsFl    = 0x2000000,  //  "    "    "     "      "       "  - subtract time
66
-  kFirstGraceXsFl  = 0x4000000,  //  "    "    "     "      "       "  - sync to first note
40
+  kSectionXsFl     = 0x00000001,  // rvalue holds section number
41
+  kBarXsFl         = 0x00000002,
42
+  kRestXsFl        = 0x00000004,
43
+  kGraceXsFl       = 0x00000008,
44
+  kDotXsFl         = 0x00000010,
45
+  kChordXsFl       = 0x00000020,
46
+  kDynXsFl         = 0x00000040,
47
+  kEvenXsFl        = 0x00000080,
48
+  kTempoXsFl       = 0x00000100,
49
+  kHeelXsFl        = 0x00000200,
50
+  kTieBegXsFl      = 0x00000400,
51
+  kTieEndXsFl      = 0x00000800,
52
+  kTieProcXsFl     = 0x00001000,
53
+  kDampDnXsFl      = 0x00002000,
54
+  kDampUpXsFl      = 0x00004000,
55
+  kDampUpDnXsFl    = 0x00008000,
56
+  kSostDnXsFl      = 0x00010000,
57
+  kSostUpXsFl      = 0x00020000,
58
+  kMetronomeXsFl   = 0x00040000,  // duration holds BPM
59
+  kOnsetXsFl       = 0x00080000,  // this is a sounding note
60
+  kBegGroupXsFl    = 0x00100000,
61
+  kEndGroupXsFl    = 0x00200000,
62
+  kBegGraceXsFl    = 0x00400000,  // (b) beg grace note group
63
+  kEndGraceXsFl    = 0x00800000,  //     end grace note group
64
+  kAddGraceXsFl    = 0x01000000,  // (a) end grace note group operator flag - add time
65
+  kSubGraceXsFl    = 0x02000000,  // (s)  "    "    "     "      "       "  - subtract time
66
+  kAFirstGraceXsFl = 0x04000000,  // (A) add time after first note
67
+  kNFirstGraceXsFl = 0x08000000   // (n) grace notes start as soon as possible after first note and add time
67
   
68
   
68
 };
69
 };
69
 
70
 
1464
       cmErrWarnMsg(&p->err,kPedalStateErrorXsRc,"Sostenuto left down at the end of a part.");
1465
       cmErrWarnMsg(&p->err,kPedalStateErrorXsRc,"Sostenuto left down at the end of a part.");
1465
   }
1466
   }
1466
 
1467
 
1468
+  
1469
+  _cmXScoreSort(p);
1470
+
1467
   return rc;
1471
   return rc;
1468
 }
1472
 }
1469
 
1473
 
1479
   }   
1483
   }   
1480
 }
1484
 }
1481
 
1485
 
1482
-// Insert the grace notes in between the first and last note in the group
1483
-// by inserting time between the first and last note.
1484
-void _cmXScoreGraceInsertTime( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
1486
+void _cmXScoreGraceInsertTimeBase( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN, unsigned initTick )
1485
 {
1487
 {
1486
-  cmXsNote_t* np = NULL;
1487
-  unsigned expand_ticks = 0;
1488
-  unsigned ticks = aV[aN-1]->tick;
1489
-  unsigned i;
1488
+  cmXsNote_t* np           = NULL;
1489
+  unsigned    expand_ticks = 0;
1490
+  unsigned    ticks        = initTick;
1491
+  
1492
+  unsigned    t0           = 0;
1493
+  unsigned    i;
1494
+  
1490
   for(i=0; i<aN; ++i)
1495
   for(i=0; i<aN; ++i)
1491
     if( cmIsFlag(aV[i]->flags,kGraceXsFl) && aV[i]->graceGroupId == graceGroupId )
1496
     if( cmIsFlag(aV[i]->flags,kGraceXsFl) && aV[i]->graceGroupId == graceGroupId )
1492
     {
1497
     {
1493
-      aV[i]->tick   = ticks;
1494
-      ticks        += aV[i]->duration;
1495
-      expand_ticks += aV[i]->duration;
1496
-      np            = aV[i];
1498
+      // if this grace note falls on the same tick as the previous grace note 
1499
+      if( np != NULL && aV[i]->tick == t0 )
1500
+        aV[i]->tick = np->tick;
1501
+      else
1502
+      {
1503
+        t0            = aV[i]->tick;      // store the unmodified tick value of this note
1504
+        aV[i]->tick   = ticks;            // set the new tick value
1505
+        ticks        += aV[i]->duration;  // calc the next grace not location
1506
+        expand_ticks += aV[i]->duration;  // track how much we are expanding time by
1507
+      }
1508
+
1509
+      np = aV[i];
1497
     }
1510
     }
1498
 
1511
 
1499
   np = np->slink;
1512
   np = np->slink;
1502
 }
1515
 }
1503
 
1516
 
1504
 // Insert the grace notes in between the first and last note in the group
1517
 // Insert the grace notes in between the first and last note in the group
1518
+// by inserting time between the first and last note.
1519
+// Note that in effect his means that the last note is pushed back
1520
+// in time by the total duration of the grace notes.
1521
+void _cmXScoreGraceInsertTime( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
1522
+{
1523
+  _cmXScoreGraceInsertTimeBase( p, graceGroupId,aV,aN, aV[aN-1]->tick );
1524
+}
1525
+
1526
+// Insert the grace notes in between the first and last note in the group
1505
 // but do not insert any additional time betwee the first and last note.
1527
 // but do not insert any additional time betwee the first and last note.
1506
 // In effect time is removed from the first note and taken by the grace notes.
1528
 // In effect time is removed from the first note and taken by the grace notes.
1529
+// The time position of the last note is therefore unchanged.
1507
 void _cmXScoreGraceOverlayTime( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
1530
 void _cmXScoreGraceOverlayTime( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
1508
 {
1531
 {
1509
   assert(aN >= 3 );
1532
   assert(aN >= 3 );
1510
   
1533
   
1511
-  unsigned t = aV[aN-1]->tick;
1512
-  int      i = (int)aN-2;
1534
+  int         i  = (int)aN-2;
1535
+  cmXsNote_t* np = aV[aN-1];
1536
+  unsigned    t0 = -1;
1513
   
1537
   
1514
   for(; i>0; --i)
1538
   for(; i>0; --i)
1515
     if( cmIsFlag(aV[i]->flags,kGraceXsFl) && aV[i]->graceGroupId == graceGroupId )
1539
     if( cmIsFlag(aV[i]->flags,kGraceXsFl) && aV[i]->graceGroupId == graceGroupId )
1516
     {
1540
     {
1517
-      aV[i]->tick = t - aV[i]->duration;
1518
-      t           =     aV[i]->tick;
1541
+      if( aV[i]->tick == t0)
1542
+        aV[i]->tick = np->tick;
1543
+      else
1544
+      {
1545
+        t0          = aV[i]->tick;
1546
+        aV[i]->tick = np->tick - aV[i]->duration;
1547
+      }
1548
+
1549
+      np = aV[i];
1519
     }
1550
     }
1520
 }
1551
 }
1521
 
1552
 
1553
+// Play the first grace at the time of the first note in the group (which is a non-grace note)
1554
+// and then expand time while inserting the other grace notes.
1555
+void _cmXScoreGraceInsertAfterFirst( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
1556
+{
1557
+  _cmXScoreGraceInsertTimeBase( p, graceGroupId,aV,aN, aV[0]->tick );
1558
+}
1559
+
1560
+
1561
+// Play the first grace not shortly (one grace note duration) after the first note
1562
+// in the group (which is a non-grace note) and then expand time while inserting the other
1563
+// grace notes.
1564
+void _cmXScoreGraceInsertSoonAfterFirst( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
1565
+{
1566
+  _cmXScoreGraceInsertTimeBase( p, graceGroupId,aV,aN, aV[0]->tick + aV[1]->duration ); 
1567
+}
1568
+
1569
+
1522
 // Adjust the locations of grace notes. Note that this must be done
1570
 // Adjust the locations of grace notes. Note that this must be done
1523
 // after reordering so that we can be sure that the order in time of
1571
 // after reordering so that we can be sure that the order in time of
1524
 // the notes in each group has been set prior to building the
1572
 // the notes in each group has been set prior to building the
1528
   cmXsRC_t rc           = kOkXsRC;
1576
   cmXsRC_t rc           = kOkXsRC;
1529
   unsigned graceGroupId = 1;
1577
   unsigned graceGroupId = 1;
1530
   double   graceDurSec  = 1.0/15.0;  // duration of all grace notes in seconds
1578
   double   graceDurSec  = 1.0/15.0;  // duration of all grace notes in seconds
1531
-  
1579
+
1532
   for(; 1; ++graceGroupId)
1580
   for(; 1; ++graceGroupId)
1533
   {
1581
   {
1534
-    cmXsNote_t* gn0p        = NULL;
1535
-    cmXsNote_t* gn1p        = NULL;
1582
+    cmXsNote_t* gn0p        = NULL;      // first note in the grace group
1583
+    cmXsNote_t* gn1p        = NULL;      // last note in the grace group
1536
     unsigned    gN          = 0;
1584
     unsigned    gN          = 0;
1537
     cmXsPart_t* pp          = p->partL;
1585
     cmXsPart_t* pp          = p->partL;
1538
     double      ticksPerSec = 0;
1586
     double      ticksPerSec = 0;
1587
+
1588
+    // Build a note chain, using cmXsNote_t.grace, between gn0p and
1589
+    // gn1p containing all the grace notes with
1590
+    // cmXsNote_t.graceGroupId == graceGroupId.
1539
     
1591
     
1540
     for(; pp!=NULL; pp=pp->link)
1592
     for(; pp!=NULL; pp=pp->link)
1541
     {
1593
     {
1571
               np->duration = floor(ticksPerSec * graceDurSec);
1623
               np->duration = floor(ticksPerSec * graceDurSec);
1572
 
1624
 
1573
             gN += 1;
1625
             gN += 1;
1574
-          }
1626
+          } 
1575
             
1627
             
1576
-        } //
1577
-      }
1578
-    }
1628
+        } // for each note in this meassure
1629
+      } // for each measure
1630
+    } // for each part
1579
 
1631
 
1580
     // no records were found for this grace id - we're done
1632
     // no records were found for this grace id - we're done
1581
     if( gn0p == NULL )
1633
     if( gn0p == NULL )
1587
       rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"The grace not group ending in meas %i has fewer than 3 (%i) members.", gn1p->meas->number, gN );
1639
       rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"The grace not group ending in meas %i has fewer than 3 (%i) members.", gn1p->meas->number, gN );
1588
       break;
1640
       break;
1589
     }
1641
     }
1590
-
1591
     
1642
     
1592
     // gn0p is now set to the first note in th group
1643
     // gn0p is now set to the first note in th group
1593
     // gn1p is now set to the last note in the group
1644
     // gn1p is now set to the last note in the group
1606
       break;
1657
       break;
1607
     }
1658
     }
1608
 
1659
 
1609
-    // count the total number of events between gn0p and gn1p
1660
+    // Count the total number of events between gn0p and gn1p
1610
     cmXsNote_t* n0p = NULL;
1661
     cmXsNote_t* n0p = NULL;
1611
     cmXsNote_t* n1p = gn0p;
1662
     cmXsNote_t* n1p = gn0p;
1612
     cmXsMeas_t* mp  = gn0p->meas;
1663
     cmXsMeas_t* mp  = gn0p->meas;
1624
       if(1)
1675
       if(1)
1625
       {
1676
       {
1626
         bool     fl   = n0p != NULL && n0p->tick < n1p->tick;
1677
         bool     fl   = n0p != NULL && n0p->tick < n1p->tick;
1627
-        unsigned type = n1p->flags & (kBegGraceXsFl|kEndGraceXsFl|kAddGraceXsFl|kSubGraceXsFl|kFirstGraceXsFl);
1628
-        printf("%3i 0x%08x %i %5i %i\n",n1p->graceGroupId,type,n1p->tick,n1p->duration,fl);
1678
+        unsigned type = n1p->flags & (kBegGraceXsFl|kEndGraceXsFl|kAddGraceXsFl|kSubGraceXsFl|kAFirstGraceXsFl|kNFirstGraceXsFl);
1679
+        printf("%3i 0x%08x %i %3i %5i %i\n",n1p->graceGroupId,type,n1p->meas->number,n1p->tick,n1p->duration,fl);
1629
       }
1680
       }
1630
       
1681
       
1631
       ++aN;
1682
       ++aN;
1653
       n0p     = n1p;
1704
       n0p     = n1p;
1654
     }
1705
     }
1655
 
1706
 
1656
-    switch( gn1p->flags & (kAddGraceXsFl | kSubGraceXsFl | kFirstGraceXsFl) )
1707
+    switch( gn1p->flags & (kAddGraceXsFl | kSubGraceXsFl | kAFirstGraceXsFl | kNFirstGraceXsFl ) )
1657
     {
1708
     {
1658
       case kAddGraceXsFl:
1709
       case kAddGraceXsFl:
1659
         _cmXScoreGraceInsertTime(p, graceGroupId, aV, aN );
1710
         _cmXScoreGraceInsertTime(p, graceGroupId, aV, aN );
1663
         _cmXScoreGraceOverlayTime(p, graceGroupId, aV, aN );
1714
         _cmXScoreGraceOverlayTime(p, graceGroupId, aV, aN );
1664
         break;
1715
         break;
1665
         
1716
         
1666
-      case kFirstGraceXsFl:
1717
+      case kAFirstGraceXsFl:
1718
+        _cmXScoreGraceInsertAfterFirst(p,graceGroupId,aV,aN);
1719
+        break;
1720
+        
1721
+      case kNFirstGraceXsFl:
1722
+        _cmXScoreGraceInsertSoonAfterFirst(p,graceGroupId,aV,aN);        
1667
         break;
1723
         break;
1668
         
1724
         
1669
       default:
1725
       default:
2136
       case 'b': r->graceFlags |= kBegGraceXsFl;                   break;        
2192
       case 'b': r->graceFlags |= kBegGraceXsFl;                   break;        
2137
       case 'a': r->graceFlags |= kAddGraceXsFl   | kEndGraceXsFl; break;
2193
       case 'a': r->graceFlags |= kAddGraceXsFl   | kEndGraceXsFl; break;
2138
       case 's': r->graceFlags |= kSubGraceXsFl   | kEndGraceXsFl; break;
2194
       case 's': r->graceFlags |= kSubGraceXsFl   | kEndGraceXsFl; break;
2139
-      case 'f': r->graceFlags |= kFirstGraceXsFl | kEndGraceXsFl; break;
2195
+      case 'A': r->graceFlags |= kAFirstGraceXsFl| kEndGraceXsFl; break;
2196
+      case 'n': r->graceFlags |= kNFirstGraceXsFl| kEndGraceXsFl; break;
2140
       case 'g': break;
2197
       case 'g': break;
2141
 
2198
 
2142
       case '%':
2199
       case '%':
3015
 {
3072
 {
3016
   cmXsRC_t        rc         = kOkXsRC;
3073
   cmXsRC_t        rc         = kOkXsRC;
3017
   cmSvgH_t        svgH       = cmSvgNullHandle;
3074
   cmSvgH_t        svgH       = cmSvgNullHandle;
3018
-  cmXsSvgEvt_t*  e          = mf->elist;
3075
+  cmXsSvgEvt_t*   e          = mf->elist;
3019
   unsigned        noteHeight = 10;
3076
   unsigned        noteHeight = 10;
3020
   const cmChar_t* svgFn      = cmFsMakeFn(dir,fn,"html",NULL);
3077
   const cmChar_t* svgFn      = cmFsMakeFn(dir,fn,"html",NULL);
3021
   const cmChar_t* cssFn      = cmFsMakeFn(NULL,fn,"css",NULL);
3078
   const cmChar_t* cssFn      = cmFsMakeFn(NULL,fn,"css",NULL);
3198
     return cmErrMsg(&ctx->err,rc,"XScore alloc failed.");
3255
     return cmErrMsg(&ctx->err,rc,"XScore alloc failed.");
3199
 
3256
 
3200
   if( reorderFn != NULL )
3257
   if( reorderFn != NULL )
3201
-    cmXScoreReorder(h,reorderFn);
3258
+    if((rc = cmXScoreReorder(h,reorderFn)) != kOkXsRC )
3259
+    {
3260
+      cmErrMsg(&ctx->err,rc,"XScore reorder failed.");
3261
+      goto errLabel;
3262
+    }
3202
 
3263
 
3203
   // assign durations to pedal down events
3264
   // assign durations to pedal down events
3204
   _cmXScoreProcessPedals(_cmXScoreHandleToPtr(h));
3265
   _cmXScoreProcessPedals(_cmXScoreHandleToPtr(h));
3239
   
3300
   
3240
   cmXScoreReport(h,&ctx->rpt,true);
3301
   cmXScoreReport(h,&ctx->rpt,true);
3241
 
3302
 
3303
+ errLabel:
3242
   return cmXScoreFinalize(&h);
3304
   return cmXScoreFinalize(&h);
3243
 
3305
 
3244
 }
3306
 }

Loading…
Cancel
Save