Browse Source

cmXScore.h/c : Added _cmXScoreProcessOverlappingNotes().

master
kevin 7 years ago
parent
commit
d17b30831d
2 changed files with 89 additions and 6 deletions
  1. 87
    5
      app/cmXScore.c
  2. 2
    1
      app/cmXScore.h

+ 87
- 5
app/cmXScore.c View File

@@ -1208,6 +1208,83 @@ cmXsRC_t  _cmXScoreResolveOctaveShift( cmXScore_t* p )
1208 1208
   return kOkXsRC;
1209 1209
 }
1210 1210
 
1211
+cmXsNote_t*  _cmXScoreFindOverlappingNote( cmXScore_t* p, const cmXsNote_t* knp )
1212
+{
1213
+  cmXsPart_t* pp = p->partL;
1214
+
1215
+  // for each part
1216
+  for(; pp!=NULL; pp=pp->link)
1217
+  {
1218
+    cmXsMeas_t* mp = pp->measL;
1219
+
1220
+    // for each measure
1221
+    for(; mp!=NULL; mp=mp->link)
1222
+    {
1223
+      cmXsNote_t* np = mp->noteL;
1224
+
1225
+      // for each note in this measure
1226
+      for(; np!=NULL; np=np->slink)
1227
+        if( np->uid != knp->uid
1228
+          && cmIsFlag(np->flags,kOnsetXsFl)
1229
+          && knp->pitch == np->pitch
1230
+          && knp->tick >= np->tick 
1231
+          && knp->tick <  (np->tick + np->duration)  )
1232
+        {
1233
+          return np;
1234
+        }
1235
+    }
1236
+  }
1237
+  return NULL;
1238
+}
1239
+
1240
+void  _cmXScoreProcessOverlappingNotes( cmXScore_t* p )
1241
+{
1242
+  cmXsPart_t* pp = p->partL;
1243
+
1244
+  // for each part
1245
+  for(; pp!=NULL; pp=pp->link)
1246
+  {
1247
+    cmXsMeas_t* mp = pp->measL;
1248
+
1249
+    // for each measure
1250
+    for(; mp!=NULL; mp=mp->link)
1251
+    {
1252
+      cmXsNote_t* np = mp->noteL;
1253
+      cmXsNote_t* fnp;
1254
+      
1255
+      // for each note in this measure
1256
+      for(; np!=NULL; np=np->slink)
1257
+        if( cmIsFlag(np->flags,kOnsetXsFl) && (fnp = _cmXScoreFindOverlappingNote(p,np)) != NULL)
1258
+        {
1259
+          // is np entirely contained inside fnp
1260
+          bool embeddedFl = fnp->tick + fnp->duration > np->tick + np->duration;
1261
+          
1262
+          //printf("bar=%3i %4s voice:%2i %2i : %7i %7i : %7i %7i : %7i : %c \n",np->meas->number,cmMidiToSciPitch(np->pitch,NULL,0),np->voice->id,fnp->voice->id,fnp->tick,fnp->tick+fnp->duration,np->tick,np->tick+np->duration, (fnp->tick+fnp->duration) - np->tick, embeddedFl ? 'E' : 'O');
1263
+
1264
+          // turn off embedded notes
1265
+          if( embeddedFl )
1266
+          {
1267
+            if( np->voice->id == fnp->voice->id )
1268
+              cmErrWarnMsg(&p->err,kOverlapWarnXsRC,"A time embedded note (bar=%i %s) was removed even though it overlapped with a note in the same voice.",np->meas->number,cmMidiToSciPitch(np->pitch,NULL,0));
1269
+            
1270
+            np->flags = cmClrFlag(np->flags,kOnsetXsFl);
1271
+          }
1272
+          else
1273
+          {
1274
+            int d = (fnp->tick+fnp->duration) - np->tick;
1275
+
1276
+            // shorten the first note
1277
+            if( d > 0 && d < fnp->duration )
1278
+              fnp->duration -= d;
1279
+
1280
+            // move the second note just past it
1281
+            np->tick       = fnp->tick + fnp->duration + 1;
1282
+          }
1283
+        }
1284
+    }
1285
+  }
1286
+}
1287
+
1211 1288
 
1212 1289
 // The identical pitch may be notated to play simultaneously on different voices.
1213 1290
 // As performed on the piano this will equate to a single sounding note.
@@ -2426,7 +2503,7 @@ cmXsRC_t cmXScoreReorder( cmXsH_t h, const cmChar_t* fn )
2426 2503
 
2427 2504
 
2428 2505
 
2429
-/*
2506
+/* CSV score columns
2430 2507
   kMidiFileIdColScIdx= 0,
2431 2508
   kTypeLabelColScIdx = 3,
2432 2509
   kDSecsColScIdx     = 4,
@@ -2719,7 +2796,6 @@ cmXsRC_t _cmXScoreWriteCsvRow(
2719 2796
 
2720 2797
  errLabel:
2721 2798
   return rc;
2722
-
2723 2799
 }
2724 2800
 
2725 2801
 cmXsRC_t cmXScoreWriteCsv( cmXsH_t h, const cmChar_t* csvFn )
@@ -3076,9 +3152,12 @@ cmXsRC_t _cmXsWriteMidiSvg( cmCtx_t* ctx, cmXScore_t* p, cmXsMidiFile_t* mf, con
3076 3152
   cmSvgH_t        svgH       = cmSvgNullHandle;
3077 3153
   cmXsSvgEvt_t*   e          = mf->elist;
3078 3154
   unsigned        noteHeight = 10;
3079
-  const cmChar_t* svgFn      = cmFsMakeFn(dir,fn,"html",NULL);
3155
+  cmChar_t*       fn0        = cmMemAllocStr( fn );  
3156
+  const cmChar_t* svgFn      = cmFsMakeFn(dir,fn0 = cmTextAppendSS(fn0,"_midi_svg"),"html",NULL);
3080 3157
   const cmChar_t* cssFn      = cmFsMakeFn(NULL,fn,"css",NULL);
3081 3158
   cmChar_t*       t0         = NULL;  // temporary dynamic string
3159
+
3160
+  cmMemFree(fn0);
3082 3161
   
3083 3162
   // create the SVG writer
3084 3163
   if( cmSvgWriterAlloc(ctx,&svgH) != kOkSvgRC )
@@ -3265,7 +3344,10 @@ cmXsRC_t cmXScoreTest(
3265 3344
 
3266 3345
   // assign durations to pedal down events
3267 3346
   _cmXScoreProcessPedals(_cmXScoreHandleToPtr(h));
3268
-  
3347
+
3348
+  // remove some notes which share a pitch which are overlapped or embedded
3349
+  _cmXScoreProcessOverlappingNotes(_cmXScoreHandleToPtr(h));
3350
+
3269 3351
   if( csvOutFn != NULL )
3270 3352
   {
3271 3353
     cmScH_t scH = cmScNullHandle;
@@ -3287,7 +3369,7 @@ cmXsRC_t cmXScoreTest(
3287 3369
 
3288 3370
     cmSymTblDestroy(&stH); 
3289 3371
   }
3290
-
3372
+  
3291 3373
   if( midiOutFn != NULL )
3292 3374
   {
3293 3375
     cmFileSysPathPart_t* pp = cmFsPathParts(midiOutFn);

+ 2
- 1
app/cmXScore.h View File

@@ -18,7 +18,8 @@ extern "C" {
18 18
     kPedalStateErrorXsRc,
19 19
     kMidiFailXsRC,
20 20
     kFileFailXsRC,
21
-    kSvgFailXsRC
21
+    kSvgFailXsRC,
22
+    kOverlapWarnXsRC
22 23
   };
23 24
 
24 25
   typedef cmRC_t     cmXsRC_t;

Loading…
Cancel
Save