瀏覽代碼

cmTakeSeqBldr.h/c : Partial implementation of cmTakeSeqBldrLoadTake().

master
Kevin Larke 9 年之前
父節點
當前提交
4873885874
共有 2 個檔案被更改,包括 176 行新增36 行删除
  1. 172
    34
      app/cmTakeSeqBldr.c
  2. 4
    2
      app/cmTakeSeqBldr.h

+ 172
- 34
app/cmTakeSeqBldr.c 查看文件

@@ -18,35 +18,79 @@
18 18
 #include "cmTakeSeqBldr.h"
19 19
 
20 20
 
21
-typedef struct cmNoteTsb_str
21
+// Map a score event to a MIDI event. 
22
+typedef struct cmScTrkMidiTsb_str
22 23
 {
23 24
   unsigned mni;      // midi note index as an offset from the take marker
24 25
   unsigned scEvtIdx; // score event index this not is assoc'd with or -1 if it did not match
25 26
   unsigned flags;    // flags from cmScMatcherResult_t 
26
-} cmNoteTsb_t;
27
+} cmScTrkMidiTsb_t;
27 28
 
28
-typedef struct cmTakeTsb_str
29
+
30
+// Score Tracking info. from a single take (time-line marker)
31
+typedef struct cmScTrkTakeTsb_str
32
+{
33
+  unsigned          markerUid;  // marker time line uid assoc'd with this take
34
+  cmScTrkMidiTsb_t* midiV;      // midiV[midiN] score to midi file map recd. array.
35
+  unsigned          midiN;  
36
+  bool              failFl;
37
+} cmScTrkTakeTsb_t;
38
+
39
+enum 
29 40
 {
30
-  unsigned     markerUid;  // marker time line uid assoc'd with this take
31
-  cmNoteTsb_t* noteV;      // noteV[noteN] score to midi file map recd. array.
32
-  unsigned     noteN;  
33
-  bool         failFl;
34
-} cmTakeTsb_t;
41
+  kNoteTsbFl   = 0x01,
42
+  kPedalTsbFl  = 0x02,
43
+  kEnableTsbFl = 0x04
44
+};
45
+
46
+// 
47
+typedef struct cmMidiEvt_str
48
+{  
49
+  unsigned              srcId;     // marker uid or -1 if this event was manually inserted
50
+  unsigned              flags;     // note | pedal | enable  
51
+  struct cmMidiEvt_str* ref;       // previous MIDI event in time
52
+  unsigned              offsetSmp; // time offset from *ref
53
+  unsigned              durSmp;    // duration of this MIDI event
54
+  unsigned              d0;        // d0 MIDI channel msg data.
55
+  unsigned              d1;        // d1 MIDI channel msg data
56
+  struct cmMidiEvt_str* link;      // pointer to next MIDI event in list
57
+} cmMidiEvt_t;
58
+
59
+// This record represents a note or pedal score event 
60
+typedef struct cmScEvtTsb_str
61
+{
62
+  unsigned     flags;    // note | pedal
63
+  unsigned     scEvtIdx; // score event index (into scH)
64
+  cmMidiEvt_t* evtList;  // list of alternate MIDI events which may render this event
65
+} cmScEvtTsb_t;
66
+
67
+// This record contains all the score events and and score synchronized MIDI events
68
+// associated with a given take.  Each call to cmTakeSeqBldrLoadTake() creates
69
+// one of these records.
70
+typedef struct cmTakeScEvtArrayTsb_str
71
+{
72
+  unsigned      tlMarkerUid; // time-line marker uid associated with this take
73
+  cmScEvtTsb_t* scEvtV;      // scEvtV[scEvtN] array of score events contained by this take  
74
+  unsigned      scEvtN;      // count of score events in this take 
75
+} cmTakeScEvtArrayTsb_t;
35 76
 
36 77
 typedef struct
37 78
 {
38
-  cmCtx_t         ctx;
39
-  cmErr_t         err;
40
-  cmJsonH_t       jsH;
41
-  const cmChar_t* tlFn;
42
-  const cmChar_t* scFn;
43
-  const cmChar_t* tlPrefixPath;
44
-
45
-  cmTakeTsb_t*    takeV;  // takeV[ takeN ]
46
-  unsigned        takeN;
79
+  cmCtx_t         ctx;          // application context
80
+  cmErr_t         err;          // internal error object
81
+  cmJsonH_t       jsH;          // JSON tree used to hold score tracker info.
82
+  const cmChar_t* tlFn;         // time line filename
83
+  const cmChar_t* scFn;         // score file name
84
+  const cmChar_t* tlPrefixPath; // path to time line audio and MIDI files
85
+  cmTlH_t         tlH;          // time-line handle
86
+  cmScH_t         scH;          // score handle
87
+
88
+  cmScTrkTakeTsb_t*  scTrkTakeV;  // score tracker scTrkTakeV[ scTrkTakeN ]
89
+  unsigned           scTrkTakeN;  
90
+  
91
+  cmTakeScEvtArrayTsb_t* takes;   // list of scEvt arrays used by this sequence 
92
+  cmTakeScEvtArrayTsb_t* manual;  // list of manually inserted MIDI events
47 93
   
48
-  cmTlH_t        tlH;
49
-  cmScH_t         scH;
50 94
 
51 95
 } cmTsb_t;
52 96
 
@@ -69,10 +113,10 @@ cmTsbRC_t _cmTsbScoreTrkFree( cmTsb_t* p )
69 113
     goto errLabel;
70 114
   }
71 115
   
72
-  for(i=0; i<p->takeN; ++i)
73
-    cmMemPtrFree(&p->takeV[i].noteV);
116
+  for(i=0; i<p->scTrkTakeN; ++i)
117
+    cmMemPtrFree(&p->scTrkTakeV[i].midiV);
74 118
 
75
-  cmMemPtrFree(&p->takeV);
119
+  cmMemPtrFree(&p->scTrkTakeV);
76 120
 
77 121
   if( cmTimeLineFinalize(&p->tlH) != kOkTlRC )
78 122
     rc = cmErrMsg(&p->err,kTimeLineFailTsbRC,"Time line object finalize failed.");
@@ -131,13 +175,13 @@ cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
131 175
   }
132 176
 
133 177
   // count of take records
134
-  p->takeN = cmJsonChildCount(tkArrObj);
178
+  p->scTrkTakeN = cmJsonChildCount(tkArrObj);
135 179
 
136 180
   // array of take records
137
-  p->takeV  = cmMemAllocZ(cmTakeTsb_t,p->takeN);
181
+  p->scTrkTakeV  = cmMemAllocZ(cmScTrkTakeTsb_t,p->scTrkTakeN);
138 182
 
139 183
   // for each take record
140
-  for(i=0; i<p->takeN; ++i)
184
+  for(i=0; i<p->scTrkTakeN; ++i)
141 185
   {
142 186
     cmJsonNode_t* takeObj    = NULL;
143 187
     cmJsonNode_t* noteArrObj = NULL;
@@ -152,8 +196,8 @@ cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
152 196
 
153 197
     // parse the take record
154 198
     if((jsRC = cmJsonMemberValues( takeObj, &errMsg,
155
-          "markerUid",kIntTId,   &p->takeV[i].markerUid,
156
-          "failFl",   kIntTId,   &p->takeV[i].failFl,
199
+          "markerUid",kIntTId,   &p->scTrkTakeV[i].markerUid,
200
+          "failFl",   kIntTId,   &p->scTrkTakeV[i].failFl,
157 201
           "array",    kArrayTId, &noteArrObj,
158 202
           0)) != kOkJsRC )
159 203
     {
@@ -166,13 +210,13 @@ cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
166 210
     }
167 211
 
168 212
     // get the count of note records
169
-    p->takeV[i].noteN = cmJsonChildCount(noteArrObj);
213
+    p->scTrkTakeV[i].midiN = cmJsonChildCount(noteArrObj);
170 214
     
171 215
     // allocate a note record array for this take
172
-    p->takeV[i].noteV = cmMemAllocZ(cmNoteTsb_t, p->takeV[i].noteN);
216
+    p->scTrkTakeV[i].midiV = cmMemAllocZ(cmScTrkMidiTsb_t, p->scTrkTakeV[i].midiN);
173 217
 
174 218
     // for each note record
175
-    for(j=0; j<p->takeV[i].noteN; ++j)
219
+    for(j=0; j<p->scTrkTakeV[i].midiN; ++j)
176 220
     {
177 221
       cmJsonNode_t* noteObj = NULL;
178 222
       
@@ -185,9 +229,9 @@ cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
185 229
 
186 230
       // parse the note record
187 231
       if((jsRC = cmJsonMemberValues( noteObj, &errMsg,
188
-            "mni",      kIntTId, &p->takeV[i].noteV[j].mni,
189
-            "scEvtIdx", kIntTId, &p->takeV[i].noteV[j].scEvtIdx,
190
-            "flags",    kIntTId, &p->takeV[i].noteV[j].flags,
232
+            "mni",      kIntTId, &p->scTrkTakeV[i].midiV[j].mni,
233
+            "scEvtIdx", kIntTId, &p->scTrkTakeV[i].midiV[j].scEvtIdx,
234
+            "flags",    kIntTId, &p->scTrkTakeV[i].midiV[j].flags,
191 235
             0)) != kOkJsRC )
192 236
       {
193 237
         if( jsRC == kNodeNotFoundJsRC && errMsg != NULL )
@@ -207,6 +251,30 @@ cmTsbRC_t _cmTsbLoadScoreTrkFile( cmTsb_t* p, const cmChar_t* scoreTrkFn )
207 251
   return rc;
208 252
 }
209 253
 
254
+// Return the count of score events inside a given marker.
255
+unsigned _cmTsbScoreTrkMarkerEventCount( cmTsb_t* p, unsigned markUid )
256
+{
257
+  unsigned i,j;
258
+  unsigned minScEvtIdx = INT_MAX;
259
+  unsigned maxScEvtIdx = 0;
260
+
261
+  for(i=0; i<p->scTrkTakeN; ++i)
262
+    for(j=0; j<p->scTrkTakeV[i].midiN; ++j)
263
+    {
264
+      if( p->scTrkTakeV[i].midiV[j].scEvtIdx < minScEvtIdx )
265
+        minScEvtIdx = p->scTrkTakeV[i].midiV[j].scEvtIdx;
266
+
267
+      if( p->scTrkTakeV[i].midiV[j].scEvtIdx > maxScEvtIdx )
268
+        maxScEvtIdx = p->scTrkTakeV[i].midiV[j].scEvtIdx;
269
+    }
270
+
271
+  if( maxScEvtIdx < minScEvtIdx )
272
+    return 0;
273
+
274
+  return (maxScEvtIdx - minScEvtIdx) + 1;
275
+  
276
+}
277
+
210 278
 cmTsbRC_t cmTakeSeqBldrAlloc( cmCtx_t* ctx, cmTakeSeqBldrH_t* hp )
211 279
 {
212 280
   cmTsbRC_t rc;
@@ -286,7 +354,77 @@ cmTsbRC_t cmTakeSeqBldrInitialize( cmTakeSeqBldrH_t h, const cmChar_t* scoreTrkF
286 354
 
287 355
 cmTsbRC_t cmTakeSeqBldrLoadTake( cmTakeSeqBldrH_t h, unsigned tlMarkUid, bool overwriteFL )
288 356
 {
289
-  cmTsbRC_t rc = kOkTsbRC;
357
+  cmTsbRC_t       rc   = kOkTsbRC;
358
+  cmTsb_t*        p    = _cmTsbHandleToPtr(h);
359
+  cmTlMarker_t*   mark = NULL;
360
+  cmTlMidiFile_t* mf   = NULL;
361
+  cmMidiFileH_t   mfH  = cmMidiFileNullHandle;
362
+  
363
+  // get a pointer to the time-line marker object
364
+  if((mark = cmTlMarkerObjPtr( p->tlH, cmTimeLineIdToObj( p->tlH, cmInvalidId, tlMarkUid))) == NULL )
365
+  {
366
+    rc = cmErrMsg(&p->err,kInvalidArgTsbRC,"The time-line marker uid '%i' is not valid.",tlMarkUid);
367
+    goto errLabel;
368
+  }
369
+
370
+  // get the name of the MIDI file which contains the marker
371
+  if((mf = cmTimeLineMidiFileAtTime( p->tlH, mark->obj.seqId, mark->obj.seqSmpIdx )) == NULL )
372
+  {
373
+    rc = cmErrMsg(&p->err,kInvalidArgTsbRC,"The time-line marker '%i' does not intersect with a MIDI file.",tlMarkUid);
374
+    goto errLabel;
375
+  }
376
+
377
+  // open the MIDI file
378
+  if( cmMidiFileOpen( cmMidiFileName(mf->h), &mfH, &p->ctx ) != kOkMfRC )
379
+  {
380
+    rc = cmErrMsg(&p->err,kInvalidArgTsbRC,"The MIDI file '%s' could not be opened.", cmStringNullGuard(cmMidiFileName(mf->h)));
381
+    goto errLabel;
382
+  }
383
+
384
+  // convert the dtick field to absolute sample indexes
385
+  cmMidiFileTickToSamples( mfH, cmTimeLineSampleRate(p->tlH), true );
386
+  
387
+  // calculate MIDI note and pedal durations (see cmMidiChMsg_t.durTicks)
388
+  cmMidiFileCalcNoteDurations( mfH );
389
+  
390
+  // convert the marker beg/end sample position to be relative to the MIDI file start time
391
+  unsigned                 bsi = mark->obj.seqSmpIdx - mf->obj.seqSmpIdx;
392
+  unsigned                 esi = mark->obj.seqSmpIdx + mark->obj.durSmpCnt - mf->obj.seqSmpIdx;
393
+  unsigned                 i   = 0;
394
+  unsigned                 n   = cmMidiFileMsgCount(mfH);
395
+  const cmMidiTrackMsg_t** a   = cmMidiFileMsgArray(mfH);
396
+  
397
+  // seek to the first MIDI msg after bsi
398
+  for(i=0; i<n; ++i)
399
+    if( a[i]->dtick >= bsi )
400
+      break;
401
+
402
+  if( i == n )
403
+  {
404
+    rc = cmErrMsg(&p->err,kInvalidArgTsbRC,"No MIDI events were found in the marker.");
405
+    goto errLabel;
406
+  }
407
+
408
+  // for each MIDI message between bsi and esi
409
+  for(; i<n && a[i]->dtick < esi; ++i)
410
+  {
411
+    const cmMidiTrackMsg_t* m = a[i];
412
+    switch( m->status )
413
+    {
414
+      case kNoteOffMdId:
415
+      case kNoteOnMdId:
416
+      case kCtlMdId:
417
+        
418
+        break;
419
+    }
420
+  }
421
+
422
+
423
+  
424
+ errLabel:
425
+  if( cmMidiFileClose(&mfH) != kOkMfRC )
426
+    rc = cmErrMsg(&p->err,kMidiFileFailTsbRC,"MIDI file close failed.");
427
+  
290 428
   return rc;
291 429
 }
292 430
 

+ 4
- 2
app/cmTakeSeqBldr.h 查看文件

@@ -12,7 +12,9 @@ extern "C" {
12 12
     kJsonFailTsbRC,
13 13
     kParseFailTsbRC,
14 14
     kTimeLineFailTsbRC,
15
-    kScoreFailTsbRC
15
+    kScoreFailTsbRC,
16
+    kInvalidArgTsbRC,
17
+    kMidiFileFailTsbRC
16 18
   };
17 19
 
18 20
   typedef cmRC_t     cmTsbRC_t;
@@ -47,7 +49,7 @@ extern "C" {
47 49
   cmTsbRC_t cmTakeSeqBldrInsertScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId );
48 50
   cmTsbRC_t cmTakeSeqBldrRemoveScoreNotes( cmTakeSeqBldrH_t h, unsigned begScEvtIdx, unsigned endScEvtId );
49 51
 
50
-  enum { kMarkTsbFl = 0x01, kTlNoteTsbFl=0x02, kScoreNoteTsbFl = 0x04, kPedalTsbFl = 0x08 };
52
+  //enum { kMarkTsbFl = 0x01, kTlNoteTsbFl=0x02, kScoreNoteTsbFl = 0x04, kPedalTsbFl = 0x08 };
51 53
   cmTsbRC_t cmTakeSeqBldrSelectEnable( cmTakeSeqBldrH_t h, unsigned flags, unsigned id, bool selectFl );
52 54
   cmTsbRC_t cmTakeSeqBldrEnableNote( cmTakeSeqBldrH_t h, unsigned ssqId, bool enableFl );
53 55
 

Loading…
取消
儲存