Преглед изворни кода

cmXScore.c : Added _cmXScoreGraceInsertTimeXXX().

master
kevin пре 8 година
родитељ
комит
be6dc19ade
1 измењених фајлова са 120 додато и 58 уклоњено
  1. 120
    58
      app/cmXScore.c

+ 120
- 58
app/cmXScore.c Прегледај датотеку

@@ -37,33 +37,34 @@ cmXsH_t cmXsNullHandle = cmSTATIC_NULL_HANDLE;
37 37
 
38 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,6 +1465,9 @@ cmXsRC_t _cmXScoreProcessPedals( cmXScore_t* p )
1464 1465
       cmErrWarnMsg(&p->err,kPedalStateErrorXsRc,"Sostenuto left down at the end of a part.");
1465 1466
   }
1466 1467
 
1468
+  
1469
+  _cmXScoreSort(p);
1470
+
1467 1471
   return rc;
1468 1472
 }
1469 1473
 
@@ -1479,21 +1483,30 @@ void _cmXScoreInsertTime( cmXScore_t* p, cmXsMeas_t* mp, cmXsNote_t* np, unsigne
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 1495
   for(i=0; i<aN; ++i)
1491 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 1512
   np = np->slink;
@@ -1502,23 +1515,58 @@ void _cmXScoreGraceInsertTime( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t*
1502 1515
 }
1503 1516
 
1504 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 1527
 // but do not insert any additional time betwee the first and last note.
1506 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 1530
 void _cmXScoreGraceOverlayTime( cmXScore_t* p, unsigned graceGroupId, cmXsNote_t* aV[], unsigned aN )
1508 1531
 {
1509 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 1538
   for(; i>0; --i)
1515 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 1570
 // Adjust the locations of grace notes. Note that this must be done
1523 1571
 // after reordering so that we can be sure that the order in time of
1524 1572
 // the notes in each group has been set prior to building the
@@ -1528,14 +1576,18 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
1528 1576
   cmXsRC_t rc           = kOkXsRC;
1529 1577
   unsigned graceGroupId = 1;
1530 1578
   double   graceDurSec  = 1.0/15.0;  // duration of all grace notes in seconds
1531
-  
1579
+
1532 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 1584
     unsigned    gN          = 0;
1537 1585
     cmXsPart_t* pp          = p->partL;
1538 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 1592
     for(; pp!=NULL; pp=pp->link)
1541 1593
     {
@@ -1571,11 +1623,11 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
1571 1623
               np->duration = floor(ticksPerSec * graceDurSec);
1572 1624
 
1573 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 1632
     // no records were found for this grace id - we're done
1581 1633
     if( gn0p == NULL )
@@ -1587,7 +1639,6 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
1587 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 1640
       break;
1589 1641
     }
1590
-
1591 1642
     
1592 1643
     // gn0p is now set to the first note in th group
1593 1644
     // gn1p is now set to the last note in the group
@@ -1606,7 +1657,7 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
1606 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 1661
     cmXsNote_t* n0p = NULL;
1611 1662
     cmXsNote_t* n1p = gn0p;
1612 1663
     cmXsMeas_t* mp  = gn0p->meas;
@@ -1624,8 +1675,8 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
1624 1675
       if(1)
1625 1676
       {
1626 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 1682
       ++aN;
@@ -1653,7 +1704,7 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
1653 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 1709
       case kAddGraceXsFl:
1659 1710
         _cmXScoreGraceInsertTime(p, graceGroupId, aV, aN );
@@ -1663,7 +1714,12 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
1663 1714
         _cmXScoreGraceOverlayTime(p, graceGroupId, aV, aN );
1664 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 1723
         break;
1668 1724
         
1669 1725
       default:
@@ -2136,7 +2192,8 @@ cmXsRC_t  _cmXScoreReorderParseGrace(cmXScore_t* p, const cmChar_t* b, unsigned
2136 2192
       case 'b': r->graceFlags |= kBegGraceXsFl;                   break;        
2137 2193
       case 'a': r->graceFlags |= kAddGraceXsFl   | kEndGraceXsFl; break;
2138 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 2197
       case 'g': break;
2141 2198
 
2142 2199
       case '%':
@@ -3015,7 +3072,7 @@ cmXsRC_t _cmXsWriteMidiSvg( cmCtx_t* ctx, cmXScore_t* p, cmXsMidiFile_t* mf, con
3015 3072
 {
3016 3073
   cmXsRC_t        rc         = kOkXsRC;
3017 3074
   cmSvgH_t        svgH       = cmSvgNullHandle;
3018
-  cmXsSvgEvt_t*  e          = mf->elist;
3075
+  cmXsSvgEvt_t*   e          = mf->elist;
3019 3076
   unsigned        noteHeight = 10;
3020 3077
   const cmChar_t* svgFn      = cmFsMakeFn(dir,fn,"html",NULL);
3021 3078
   const cmChar_t* cssFn      = cmFsMakeFn(NULL,fn,"css",NULL);
@@ -3198,7 +3255,11 @@ cmXsRC_t cmXScoreTest(
3198 3255
     return cmErrMsg(&ctx->err,rc,"XScore alloc failed.");
3199 3256
 
3200 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 3264
   // assign durations to pedal down events
3204 3265
   _cmXScoreProcessPedals(_cmXScoreHandleToPtr(h));
@@ -3239,6 +3300,7 @@ cmXsRC_t cmXScoreTest(
3239 3300
   
3240 3301
   cmXScoreReport(h,&ctx->rpt,true);
3241 3302
 
3303
+ errLabel:
3242 3304
   return cmXScoreFinalize(&h);
3243 3305
 
3244 3306
 }

Loading…
Откажи
Сачувај