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
   kSubGraceXsFl    = 0x02000000,  // (s)  "    "    "     "      "       "  - subtract time
65
   kSubGraceXsFl    = 0x02000000,  // (s)  "    "    "     "      "       "  - subtract time
66
   kAFirstGraceXsFl = 0x04000000,  // (A) add time after first note
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
   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
   cmXsComplexity_t cplx_max;
177
   cmXsComplexity_t cplx_max;
176
 } cmXScore_t;
178
 } cmXScore_t;
177
 
179
 
180
+void  _cmXScoreReport( cmXScore_t* p, cmRpt_t* rpt, bool sortFl );
181
+
178
 cmXScore_t* _cmXScoreHandleToPtr( cmXsH_t h )
182
 cmXScore_t* _cmXScoreHandleToPtr( cmXsH_t h )
179
 {
183
 {
180
   cmXScore_t* p = (cmXScore_t*)h.h;
184
   cmXScore_t* p = (cmXScore_t*)h.h;
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
   return false;
1173
   return false;
1170
 }
1174
 }
1171
 
1175
 
1789
     // verify that the first note is marked with kBegGraceXsFl
1793
     // verify that the first note is marked with kBegGraceXsFl
1790
     if( cmIsNotFlag(gn0p->flags,kBegGraceXsFl) )
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
       break;
1797
       break;
1794
     }
1798
     }
1795
 
1799
 
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
         {
2042
         {
1957
 
2043
 
1958
 
2044
 
1959
-          if( 0 /*mp->number==17*/)
2045
+          if( 0 /*mp->number==43*/ )
1960
             printf("voice: %i %i loc:%i %i  tick:%i %i pitch:%i %i idx:%i %i\n",
2046
             printf("voice: %i %i loc:%i %i  tick:%i %i pitch:%i %i idx:%i %i\n",
1961
               np->voice->id, r->voice, 
2047
               np->voice->id, r->voice, 
1962
               np->locIdx ,  r->locIdx ,
2048
               np->locIdx ,  r->locIdx ,
1969
             np->locIdx == r->locIdx &&
2055
             np->locIdx == r->locIdx &&
1970
             np->tick == r->tick &&
2056
             np->tick == r->tick &&
1971
             //np->duration == r->durtn &&
2057
             //np->duration == r->durtn &&
1972
-            //np->rvalue == r->rval &&
2058
+            np->rvalue == r->rval &&
1973
             np->pitch == r->midi &&
2059
             np->pitch == r->midi &&
1974
             index == r->idx )
2060
             index == r->idx )
1975
           {
2061
           {
2062
+            //printf("Found: %i \n", r->midi);
1976
             return np;
2063
             return np;
1977
           }
2064
           }
1978
         }
2065
         }
2061
       rV[i].note->vel      = _cmXScoreDynMarkArray[ rV[i].dynIdx ].vel;
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
     // if the tie end flag was set
2159
     // if the tie end flag was set
2065
     if( cmIsFlag(rV[i].newFlags,kTieEndXsFl) )
2160
     if( cmIsFlag(rV[i].newFlags,kTieEndXsFl) )
2066
     {
2161
     {
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
   *dynIdxRef = cmInvalidIdx;
2212
   *dynIdxRef = cmInvalidIdx;
2115
 
2213
 
2126
   if( *s == '(' )
2224
   if( *s == '(' )
2127
     ++s;  // skip the paren.
2225
     ++s;  // skip the paren.
2128
 
2226
 
2227
+  if( *s == '!')
2228
+  {
2229
+    endForkFl = true;
2230
+    ++s;      
2231
+  }   
2232
+
2129
   if( *s == 0 )
2233
   if( *s == 0 )
2130
     return cmErrMsg(&p->err,kSyntaxErrorXsRC,"Unexpected end-of-line on dynamics parsing on line:%i.",lineNumb);
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
   unsigned i      = 0;
2249
   unsigned i      = 0;
2133
   unsigned j      = 0;
2250
   unsigned j      = 0;
2134
   unsigned n      = 6;
2251
   unsigned n      = 6;
2138
   
2255
   
2139
   for(i=0; j<n && doneFl==false; ++i)
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
       case 's':
2262
       case 's':
2144
       case 'm':
2263
       case 'm':
2146
       case 'f':
2265
       case 'f':
2147
       case '+':
2266
       case '+':
2148
       case '-':
2267
       case '-':
2149
-        mark[j++] = s[i];
2268
+        mark[j++] = c;
2150
         break;
2269
         break;
2151
         
2270
         
2152
       case ')':   // ending paren.
2271
       case ')':   // ending paren.
2173
 
2292
 
2174
 
2293
 
2175
   *dynIdxRef = j;
2294
   *dynIdxRef = j;
2295
+  
2296
+  if( begForkFl )
2297
+    *flagsRef = cmSetFlag(*flagsRef,kDynBegForkXsFl);
2298
+
2299
+  if( endForkFl )
2300
+    *flagsRef = cmSetFlag(*flagsRef,kDynEndForkXsFl);
2176
       
2301
       
2177
   return rc;
2302
   return rc;
2178
 }
2303
 }
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
             // parse the flag edits following a '~'
2542
             // parse the flag edits following a '~'
2422
             if((rc = _cmXScoreReorderParseFlags(p,b,ln+1, &r.newFlags)) != kOkXsRC )
2543
             if((rc = _cmXScoreReorderParseFlags(p,b,ln+1, &r.newFlags)) != kOkXsRC )
2423
               goto errLabel;
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
             // parse the @newtick marker
2550
             // parse the @newtick marker
2426
             if((rc = _cmXScoreReorderParseTick(p, b, ln+1, &r.newTick)) != kOkXsRC )
2551
             if((rc = _cmXScoreReorderParseTick(p, b, ln+1, &r.newTick)) != kOkXsRC )
2427
               goto errLabel;
2552
               goto errLabel;
2505
   // inserting grace notes may have left the score unsorted
2630
   // inserting grace notes may have left the score unsorted
2506
   _cmXScoreSort(p);
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
  errLabel:
2642
  errLabel:
2509
   cmFileClose(&fH);
2643
   cmFileClose(&fH);
2510
   cmMemFree(b);
2644
   cmMemFree(b);
3067
   if( note->graceGroupId != 0)
3201
   if( note->graceGroupId != 0)
3068
     cmRptPrintf(rpt," g=%i",note->graceGroupId);
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
   cmXsPart_t* pp = p->partL;
3229
   cmXsPart_t* pp = p->partL;
3077
 
3230
 
3078
   for(; pp!=NULL; pp=pp->link)
3231
   for(; pp!=NULL; pp=pp->link)
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
 void _cmXScoreGenEditFileWrite( void* arg, const cmChar_t* text )
3303
 void _cmXScoreGenEditFileWrite( void* arg, const cmChar_t* text )
3145
 {
3304
 {
3146
   if( text != NULL && arg != NULL )
3305
   if( text != NULL && arg != NULL )
3756
 
3915
 
3757
   if( editFn!=NULL && !cmFsIsFile(editFn) )
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
     cmXScoreGenEditFile(ctx,xmlFn,editFn);
3919
     cmXScoreGenEditFile(ctx,xmlFn,editFn);
3761
     editFn = NULL;
3920
     editFn = NULL;
3762
   }
3921
   }

Loading…
Cancel
Save