Browse Source

cmXScore.c : Added dynamic level interpolation during edit file processing via upper case dynamic markings.

master
kevin 7 years ago
parent
commit
af84645fa4
1 changed files with 176 additions and 17 deletions
  1. 176
    17
      app/cmXScore.c

+ 176
- 17
app/cmXScore.c View File

@@ -65,7 +65,9 @@ enum
65 65
   kSubGraceXsFl    = 0x02000000,  // (s)  "    "    "     "      "       "  - subtract time
66 66
   kAFirstGraceXsFl = 0x04000000,  // (A) add time after first note
67 67
   kNFirstGraceXsFl = 0x08000000,  // (n) grace notes start as soon as possible after first note and add time
68
-  kDeleteXsFl      = 0x10000000
68
+  kDeleteXsFl      = 0x10000000,
69
+  kDynBegForkXsFl  = 0x20000000,
70
+  kDynEndForkXsFl  = 0x40000000
69 71
   
70 72
 };
71 73
 
@@ -175,6 +177,8 @@ typedef struct
175 177
   cmXsComplexity_t cplx_max;
176 178
 } cmXScore_t;
177 179
 
180
+void  _cmXScoreReport( cmXScore_t* p, cmRpt_t* rpt, bool sortFl );
181
+
178 182
 cmXScore_t* _cmXScoreHandleToPtr( cmXsH_t h )
179 183
 {
180 184
   cmXScore_t* p = (cmXScore_t*)h.h;
@@ -1165,7 +1169,7 @@ bool  _cmXScoreFindTiedNote( cmXScore_t* p, cmXsMeas_t* mp, cmXsNote_t* n0p, boo
1165 1169
     }
1166 1170
   }
1167 1171
 
1168
-  cmErrWarnMsg(&p->err,kUnterminatedTieXsRC,"The tied %c%c%i in measure %i was not terminated.",n0p->step,acc,n0p->octave,measNumb);
1172
+  cmErrWarnMsg(&p->err,kUnterminatedTieXsRC,"The tied %c%c%i in measure %i (tick:%i) was not terminated.",n0p->step,acc,n0p->octave,measNumb,n0p->tick);
1169 1173
   return false;
1170 1174
 }
1171 1175
 
@@ -1789,7 +1793,7 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
1789 1793
     // verify that the first note is marked with kBegGraceXsFl
1790 1794
     if( cmIsNotFlag(gn0p->flags,kBegGraceXsFl) )
1791 1795
     {
1792
-      rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"The first note in a grace note group in meas %i is not marked with a 'b'.", gn0p->meas->number );
1796
+      rc = cmErrMsg(&p->err,kSyntaxErrorXsRC,"The first note in a grace note group in meas %i tick %i groupid:%i is not marked with a 'b'.", gn0p->meas->number, gn0p->tick, graceGroupId );
1793 1797
       break;
1794 1798
     }
1795 1799
 
@@ -1876,6 +1880,88 @@ cmXsRC_t _cmXScoreProcessGraceNotes( cmXScore_t* p )
1876 1880
 }
1877 1881
 
1878 1882
 
1883
+cmXsNote_t* _cmXScoreDynamicForkEndNote( cmXsNote_t* bnp )
1884
+{
1885
+  assert( cmIsFlag(bnp->flags,kDynBegForkXsFl) );
1886
+
1887
+  cmXsMeas_t* mp = bnp->meas;
1888
+  cmXsNote_t* np = bnp->slink;
1889
+
1890
+  for(; mp!=NULL; mp=mp->link,np = mp==NULL?NULL :  mp->noteL)
1891
+  {    
1892
+    for(; np!=NULL; np=np->slink)
1893
+    {
1894
+      if( cmIsFlag(np->flags,kDynEndForkXsFl) && np->voice->id == bnp->voice->id )
1895
+        return np;
1896
+    }
1897
+  }
1898
+
1899
+  return NULL;
1900
+}
1901
+
1902
+cmXsRC_t _cmXScoreProcessDynamicFork( cmXScore_t* p, cmXsNote_t* bnp )
1903
+{
1904
+  cmXsNote_t* enp;
1905
+
1906
+  if((enp = _cmXScoreDynamicForkEndNote(bnp)) == NULL)
1907
+    return cmErrMsg(&p->err,kSyntaxErrorXsRC,"The dynamic fork beginning in measure %i at tick %i voice %i was not terminated.", bnp->meas->number,bnp->tick,bnp->voice->id);
1908
+
1909
+
1910
+  double begDynFrac = bnp->dynamics;
1911
+  double begVelFrac = bnp->vel;
1912
+  double endDynFrac = enp->dynamics;
1913
+  double endVelFrac = enp->vel;
1914
+
1915
+  cmXsMeas_t* mp = bnp->meas;
1916
+  cmXsNote_t* np = bnp->slink;
1917
+
1918
+  for(; mp!=NULL && np!=enp; mp=mp->link,np=mp==NULL ? NULL : mp->noteL)
1919
+  {
1920
+    for(; np!=NULL && np!=enp; np=np->slink)
1921
+
1922
+      /*
1923
+
1924
+        Conditioning this on np->dynamics==0 will may cause 'silent' notes to be assigned 
1925
+        a non-zero dynamics value - this is best fixed by using a different special value
1926
+        for silent notes
1927
+
1928
+        BUG BUG BUG BUG BUG
1929
+
1930
+       */       
1931
+      if( np->voice == bnp->voice && np->dynamics == 0 )
1932
+      {
1933
+        double frac     = ((double)np->tick - bnp->tick) / (enp->tick - bnp->tick);
1934
+        np->dynamics =  lround(begDynFrac + ((endDynFrac - begDynFrac) * frac));
1935
+        np->vel      =  lround(begVelFrac + ((endVelFrac - begVelFrac) * frac));        
1936
+      }
1937
+  }
1938
+
1939
+  return kOkXsRC;
1940
+}
1941
+
1942
+
1943
+cmXsRC_t _cmXScoreProcessDynamicForks( cmXScore_t* p )
1944
+{
1945
+  cmXsRC_t    rc = kOkXsRC;
1946
+  cmXsPart_t* pp = p->partL;
1947
+
1948
+  for(; pp!=NULL; pp=pp->link)
1949
+  {
1950
+    cmXsMeas_t* mp = pp->measL;
1951
+    for(; mp!=NULL; mp=mp->link)
1952
+      {
1953
+        cmXsNote_t* np = mp->noteL;        
1954
+        for(; np!=NULL; np=np->slink )
1955
+        {
1956
+          if( cmIsFlag(np->flags,kDynBegForkXsFl) )
1957
+            if((rc =  _cmXScoreProcessDynamicFork(p,np)) != kOkXsRC )
1958
+              return rc;
1959
+        }
1960
+      }
1961
+  }
1962
+  
1963
+  return rc;
1964
+}
1879 1965
 //-------------------------------------------------------------------------------------------
1880 1966
 
1881 1967
 
@@ -1956,7 +2042,7 @@ cmXsNote_t*  _cmXsReorderFindNote( cmXScore_t* p, unsigned measNumb, const cmXsR
1956 2042
         {
1957 2043
 
1958 2044
 
1959
-          if( 0 /*mp->number==17*/)
2045
+          if( 0 /*mp->number==43*/ )
1960 2046
             printf("voice: %i %i loc:%i %i  tick:%i %i pitch:%i %i idx:%i %i\n",
1961 2047
               np->voice->id, r->voice, 
1962 2048
               np->locIdx ,  r->locIdx ,
@@ -1969,10 +2055,11 @@ cmXsNote_t*  _cmXsReorderFindNote( cmXScore_t* p, unsigned measNumb, const cmXsR
1969 2055
             np->locIdx == r->locIdx &&
1970 2056
             np->tick == r->tick &&
1971 2057
             //np->duration == r->durtn &&
1972
-            //np->rvalue == r->rval &&
2058
+            np->rvalue == r->rval &&
1973 2059
             np->pitch == r->midi &&
1974 2060
             index == r->idx )
1975 2061
           {
2062
+            //printf("Found: %i \n", r->midi);
1976 2063
             return np;
1977 2064
           }
1978 2065
         }
@@ -2061,6 +2148,14 @@ cmXsRC_t _cmXScoreReorderMeas( cmXScore_t* p, unsigned measNumb, cmXsReorder_t*
2061 2148
       rV[i].note->vel      = _cmXScoreDynMarkArray[ rV[i].dynIdx ].vel;
2062 2149
     }
2063 2150
 
2151
+    // Set the dynamic fork begin/end flags for later _cmXScoreProcessDynamicForks()
2152
+    if( cmIsFlag(rV[i].newFlags,kDynBegForkXsFl) )
2153
+      rV[i].note->flags = cmSetFlag(rV[i].note->flags,kDynBegForkXsFl); 
2154
+
2155
+    if( cmIsFlag(rV[i].newFlags,kDynEndForkXsFl) )
2156
+      rV[i].note->flags = cmSetFlag(rV[i].note->flags,kDynEndForkXsFl); 
2157
+
2158
+    
2064 2159
     // if the tie end flag was set
2065 2160
     if( cmIsFlag(rV[i].newFlags,kTieEndXsFl) )
2066 2161
     {
@@ -2106,10 +2201,13 @@ cmXsRC_t _cmXScoreReorderMeas( cmXScore_t* p, unsigned measNumb, cmXsReorder_t*
2106 2201
 
2107 2202
 }
2108 2203
 
2109
-cmXsRC_t _cmXScoreReorderParseDyn(cmXScore_t* p, const cmChar_t* b, unsigned lineNumb, unsigned* dynIdxRef )
2204
+cmXsRC_t _cmXScoreReorderParseDyn(cmXScore_t* p, const cmChar_t* b, unsigned lineNumb, unsigned* dynIdxRef, unsigned* flagsRef )
2110 2205
 {
2111
-  cmXsRC_t rc = kOkXsRC;
2112
-  const cmChar_t* s;
2206
+  cmXsRC_t        rc        = kOkXsRC;
2207
+  const cmChar_t* s         = NULL;
2208
+  bool            begForkFl = false;
2209
+  bool            endForkFl = false;
2210
+    
2113 2211
 
2114 2212
   *dynIdxRef = cmInvalidIdx;
2115 2213
 
@@ -2126,9 +2224,28 @@ cmXsRC_t _cmXScoreReorderParseDyn(cmXScore_t* p, const cmChar_t* b, unsigned lin
2126 2224
   if( *s == '(' )
2127 2225
     ++s;  // skip the paren.
2128 2226
 
2227
+  if( *s == '!')
2228
+  {
2229
+    endForkFl = true;
2230
+    ++s;      
2231
+  }   
2232
+
2129 2233
   if( *s == 0 )
2130 2234
     return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Unexpected end-of-line on dynamics parsing on line:%i.",lineNumb);
2131 2235
 
2236
+
2237
+  // check for beg/end fork dynamic 
2238
+  if( isupper(*s) )
2239
+  {
2240
+    if( !endForkFl)
2241
+      begForkFl=true;
2242
+  }
2243
+  else
2244
+  {
2245
+    if( endForkFl )
2246
+      return cmErrMsg(&p->err,kSyntaxErrorXsRC,"A double exclaimation point (end-of-dynamic fork) must always be followed by an upper case M,P, or F. See line:%i",lineNumb);
2247
+  }
2248
+
2132 2249
   unsigned i      = 0;
2133 2250
   unsigned j      = 0;
2134 2251
   unsigned n      = 6;
@@ -2138,7 +2255,9 @@ cmXsRC_t _cmXScoreReorderParseDyn(cmXScore_t* p, const cmChar_t* b, unsigned lin
2138 2255
   
2139 2256
   for(i=0; j<n && doneFl==false; ++i)
2140 2257
   {
2141
-    switch(s[i])
2258
+    char c = tolower(s[i]);
2259
+    
2260
+    switch(c)
2142 2261
     {
2143 2262
       case 's':
2144 2263
       case 'm':
@@ -2146,7 +2265,7 @@ cmXsRC_t _cmXScoreReorderParseDyn(cmXScore_t* p, const cmChar_t* b, unsigned lin
2146 2265
       case 'f':
2147 2266
       case '+':
2148 2267
       case '-':
2149
-        mark[j++] = s[i];
2268
+        mark[j++] = c;
2150 2269
         break;
2151 2270
         
2152 2271
       case ')':   // ending paren.
@@ -2173,6 +2292,12 @@ cmXsRC_t _cmXScoreReorderParseDyn(cmXScore_t* p, const cmChar_t* b, unsigned lin
2173 2292
 
2174 2293
 
2175 2294
   *dynIdxRef = j;
2295
+  
2296
+  if( begForkFl )
2297
+    *flagsRef = cmSetFlag(*flagsRef,kDynBegForkXsFl);
2298
+
2299
+  if( endForkFl )
2300
+    *flagsRef = cmSetFlag(*flagsRef,kDynEndForkXsFl);
2176 2301
       
2177 2302
   return rc;
2178 2303
 }
@@ -2414,14 +2539,14 @@ cmXsRC_t _cmXsApplyEditFile( cmXScore_t* p, const cmChar_t* fn )
2414 2539
             }
2415 2540
 
2416 2541
             
2417
-            // parse the dynamic marking following a '!'
2418
-            if((rc = _cmXScoreReorderParseDyn(p,b,ln+1,&r.dynIdx)) != kOkXsRC )
2419
-              goto errLabel;
2420
-            
2421 2542
             // parse the flag edits following a '~'
2422 2543
             if((rc = _cmXScoreReorderParseFlags(p,b,ln+1, &r.newFlags)) != kOkXsRC )
2423 2544
               goto errLabel;
2424 2545
 
2546
+            // parse the dynamic marking following a '!'
2547
+            if((rc = _cmXScoreReorderParseDyn(p,b,ln+1,&r.dynIdx, &r.newFlags)) != kOkXsRC )
2548
+              goto errLabel;
2549
+                        
2425 2550
             // parse the @newtick marker
2426 2551
             if((rc = _cmXScoreReorderParseTick(p, b, ln+1, &r.newTick)) != kOkXsRC )
2427 2552
               goto errLabel;
@@ -2505,6 +2630,15 @@ cmXsRC_t _cmXsApplyEditFile( cmXScore_t* p, const cmChar_t* fn )
2505 2630
   // inserting grace notes may have left the score unsorted
2506 2631
   _cmXScoreSort(p);
2507 2632
   
2633
+  // process the dynamic forks
2634
+  _cmXScoreProcessDynamicForks(p);
2635
+
2636
+
2637
+
2638
+  _cmXScoreReport(p, NULL, true );
2639
+
2640
+
2641
+  
2508 2642
  errLabel:
2509 2643
   cmFileClose(&fH);
2510 2644
   cmMemFree(b);
@@ -3067,12 +3201,31 @@ void _cmXScoreReportNote( cmRpt_t* rpt, const cmXsNote_t* note,unsigned index )
3067 3201
   if( note->graceGroupId != 0)
3068 3202
     cmRptPrintf(rpt," g=%i",note->graceGroupId);
3069 3203
 
3204
+  /*
3205
+  if( cmIsFlag(note->flags,kBegGraceXsFl) )
3206
+    cmRptPrintf(rpt," B");
3207
+
3208
+  if( cmIsFlag(note->flags,kEndGraceXsFl) )
3209
+    cmRptPrintf(rpt," E");
3210
+
3211
+  if( note->dynamics != 0)
3212
+    cmRptPrintf(rpt," dyn=%i",note->dynamics);
3213
+
3214
+  if( cmIsFlag(note->flags,kDynBegForkXsFl) )
3215
+    cmRptPrintf(rpt," B");
3216
+
3217
+  if( cmIsFlag(note->flags,kDynEndForkXsFl) )
3218
+    cmRptPrintf(rpt," E");
3219
+  
3220
+  */
3070 3221
 }
3071 3222
 
3072 3223
 
3073
-void  cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl )
3224
+void  _cmXScoreReport( cmXScore_t* p, cmRpt_t* rpt, bool sortFl )
3074 3225
 {
3075
-  cmXScore_t* p  = _cmXScoreHandleToPtr(h);
3226
+  if( rpt == NULL )
3227
+    rpt = p->err.rpt;
3228
+  
3076 3229
   cmXsPart_t* pp = p->partL;
3077 3230
 
3078 3231
   for(; pp!=NULL; pp=pp->link)
@@ -3141,6 +3294,12 @@ void  cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl )
3141 3294
   }
3142 3295
 }
3143 3296
 
3297
+void  cmXScoreReport( cmXsH_t h, cmRpt_t* rpt, bool sortFl )
3298
+{
3299
+  cmXScore_t* p  = _cmXScoreHandleToPtr(h);
3300
+  return _cmXScoreReport(p,rpt,sortFl);
3301
+}
3302
+
3144 3303
 void _cmXScoreGenEditFileWrite( void* arg, const cmChar_t* text )
3145 3304
 {
3146 3305
   if( text != NULL && arg != NULL )
@@ -3756,7 +3915,7 @@ cmXsRC_t cmXScoreTest(
3756 3915
 
3757 3916
   if( editFn!=NULL && !cmFsIsFile(editFn) )
3758 3917
   {
3759
-    cmRptPrintf(&ctx->rpt,"The edit file %s does not exist. A new edit file is therefore being created.",editFn);
3918
+    cmRptPrintf(&ctx->rpt,"The edit file %s does not exist. A new edit file will be created.",editFn);
3760 3919
     cmXScoreGenEditFile(ctx,xmlFn,editFn);
3761 3920
     editFn = NULL;
3762 3921
   }

Loading…
Cancel
Save