Переглянути джерело

cmScoreMatchGraphic.h/c : Added cmScoreMatchGraphicUpdateMidiFromScore() to set the MIDI note velocities based on the score velocities.

master
kevin 8 роки тому
джерело
коміт
3acdeb61a0
2 змінених файлів з 71 додано та 4 видалено
  1. 64
    3
      app/cmScoreMatchGraphic.c
  2. 7
    1
      app/cmScoreMatchGraphic.h

+ 64
- 3
app/cmScoreMatchGraphic.c Переглянути файл

@@ -89,7 +89,8 @@ typedef struct
89 89
 typedef struct
90 90
 {
91 91
   cmErr_t      err;
92
-  
92
+
93
+  cmChar_t*    scFn;
93 94
   cmSmgSc_t*   scV;    // scV[scN] score bars and notes
94 95
   unsigned     scN;
95 96
   
@@ -99,7 +100,8 @@ typedef struct
99 100
   cmSmgLine_t* lines;  // Graphic lines used to indicate that a midi event matches to multiple score notes.
100 101
                        // (Each match after the first gets a line from the box representing the midi event
101 102
                        //  to the matching score event)
102
-  
103
+
104
+  cmChar_t*    mfFn;   // MIDI file name
103 105
   cmSmgMidi_t* mV;     // mV[mN] midi note-on events
104 106
   unsigned     mN;
105 107
   double       mfDurSecs; // midi file duration in seconds
@@ -120,6 +122,7 @@ cmSmg_t* _cmSmgHandleToPtr( cmSmgH_t h )
120 122
 cmSmgRC_t _cmSmgFree( cmSmg_t* p )
121 123
 {
122 124
   unsigned i;
125
+
123 126
   
124 127
   for(i=0; i<p->mN; ++i)
125 128
   {
@@ -155,7 +158,9 @@ cmSmgRC_t _cmSmgFree( cmSmg_t* p )
155 158
     cmMemFree(l0);
156 159
     l0 = l1;
157 160
   }
158
-  
161
+
162
+  cmMemFree(p->scFn);
163
+  cmMemFree(p->mfFn);
159 164
   cmMemFree(p->scV);
160 165
   cmMemFree(p->mV);
161 166
   cmMemFree(p->locV);
@@ -198,6 +203,7 @@ cmSmgRC_t _cmSmgInitFromScore( cmCtx_t* ctx, cmSmg_t* p, const cmChar_t* scoreFn
198 203
   if( cmScoreInitialize(ctx,&scH,scoreFn,44100.0, NULL, 0, NULL, NULL, cmSymTblNullHandle ) != kOkScRC )
199 204
     return cmErrMsg(&p->err,kScoreFailSmgRC,"Score initializatio failed on '%s'.",cmStringNullGuard(scoreFn));
200 205
 
206
+  p->scFn = cmMemAllocStr(scoreFn);
201 207
   p->scN  = cmScoreEvtCount(scH);
202 208
   p->scV  = cmMemAllocZ(cmSmgSc_t,p->scN);
203 209
   
@@ -269,6 +275,7 @@ cmSmgRC_t _cmSmgInitFromMidi( cmCtx_t* ctx, cmSmg_t* p, const cmChar_t* midiFn )
269 275
   p->mV        = cmMemAllocZ(cmSmgMidi_t,mN);
270 276
   p->mN        = mN;
271 277
   p->mfDurSecs = cmMidiFileDurSecs(mfH);
278
+  p->mfFn      = cmMemAllocStr(midiFn);
272 279
   
273 280
   for(i=0,j=0; i<mN; ++i)
274 281
     if( (mV[i]!=NULL) && cmMidiIsChStatus(mV[i]->status) && cmMidiIsNoteOn(mV[i]->status) && (mV[i]->u.chMsgPtr->d1>0) )          
@@ -606,3 +613,57 @@ cmSmgRC_t cmScoreMatchGraphicGenTimeLineBars( cmSmgH_t h, const cmChar_t* fn, un
606 613
   return rc;
607 614
   
608 615
 }
616
+
617
+cmSmgRC_t cmScoreMatchGraphicUpdateMidiFromScore( cmCtx_t* ctx, cmSmgH_t h, const cmChar_t* newMidiFn )
618
+{
619
+  cmSmgRC_t     rc  = kOkSmgRC;
620
+  cmSmg_t*      p   = _cmSmgHandleToPtr(h);
621
+  unsigned      i   = 0;
622
+  cmMidiFileH_t mfH = cmMidiFileNullHandle;
623
+  cmScH_t       scH = cmScNullHandle;
624
+  
625
+  if( cmMidiFileOpen(ctx, &mfH, p->mfFn ) != kOkMfRC )
626
+    return cmErrMsg(&p->err,kMidiFileFailSmgRC,"MIDI file open failed on '%s'.",cmStringNullGuard(p->mfFn));
627
+  
628
+  if( cmScoreInitialize(ctx,&scH,p->scFn,44100.0, NULL, 0, NULL, NULL, cmSymTblNullHandle ) != kOkScRC )
629
+  {
630
+    rc = cmErrMsg(&p->err,kScoreFailSmgRC,"Score initializatio failed on '%s'.",cmStringNullGuard(p->scFn));
631
+    goto errLabel;
632
+  } 
633
+  
634
+  for(i=0; i<p->mN; ++i)
635
+  {
636
+    cmSmgMidi_t* mr = p->mV + i;
637
+
638
+    // only update midi events which were matched exactly once
639
+    if( mr->matchV==NULL || mr->matchV->link!=NULL  )
640
+      continue;
641
+
642
+    // locate the matched score event
643
+    const cmScoreEvt_t* s= cmScoreIdToEvt( scH, mr->matchV->score->csvEventId );
644
+    assert( s!=NULL );
645
+
646
+    // assign the score velocity to the MIDI file
647
+    if(cmMidiFileSetVelocity( mfH, mr->uid, s->vel ) != kOkMfRC )
648
+    {
649
+      rc = cmErrMsg(&p->err,kOpFailSmgRC,"Set velocify operation failed.");
650
+      goto errLabel;
651
+    }
652
+
653
+  }
654
+
655
+  // write the updated MIDI file
656
+  if( cmMidiFileWrite( mfH, newMidiFn ) != kOkMfRC )
657
+  {
658
+    rc = cmErrMsg(&p->err,kMidiFileFailSmgRC,"MIDI file write failed on '%s'.",cmStringNullGuard(newMidiFn));
659
+    goto errLabel;
660
+  }
661
+
662
+
663
+ errLabel:
664
+  cmMidiFileClose(&mfH);
665
+  cmScoreFinalize(&scH);
666
+  
667
+  return rc;
668
+ 
669
+}

+ 7
- 1
app/cmScoreMatchGraphic.h Переглянути файл

@@ -10,7 +10,8 @@ extern "C" {
10 10
     kOkSmgRC = cmOkRC,
11 11
     kFileSmgRC,
12 12
     kScoreFailSmgRC,
13
-    kMidiFileFailSmgRC
13
+    kMidiFileFailSmgRC,
14
+    kOpFailSmgRC
14 15
   };
15 16
   
16 17
   typedef cmRC_t     cmSmgRC_t;
@@ -27,6 +28,11 @@ extern "C" {
27 28
   // Generate a set of markers for use in a cmTimeLine file which forms a marked area
28 29
   // beginning at each bar line and ends at the end of the file.
29 30
   cmSmgRC_t cmScoreMatchGraphicGenTimeLineBars( cmSmgH_t h, const cmChar_t* fn, unsigned srate );
31
+
32
+  // Update the MIDI file velocity values and insert pedal events
33
+  // from from score into MIDI file and then write the updated MIDI
34
+  // file to 'newMidiFn'.
35
+  cmSmgRC_t cmScoreMatchGraphicUpdateMidiFromScore( cmCtx_t* ctx, cmSmgH_t h, const cmChar_t* newMidiFn );
30 36
   
31 37
 #ifdef __cplusplus
32 38
 }

Завантаження…
Відмінити
Зберегти