|
@@ -29,6 +29,7 @@ enum
|
29
|
29
|
kNoMatchSmgFl = 0x0010
|
30
|
30
|
};
|
31
|
31
|
|
|
32
|
+// Graphic box representing a score label or MIDI event
|
32
|
33
|
typedef struct cmSmgBox_str
|
33
|
34
|
{
|
34
|
35
|
unsigned flags;
|
|
@@ -42,38 +43,45 @@ typedef struct cmSmgBox_str
|
42
|
43
|
struct cmSmgBox_str* link;
|
43
|
44
|
} cmSmgBox_t;
|
44
|
45
|
|
|
46
|
+// Graphic line linking secondary MIDI matches to score events
|
45
|
47
|
typedef struct cmSmgLine_str
|
46
|
48
|
{
|
47
|
|
- cmSmgBox_t* b0;
|
48
|
|
- cmSmgBox_t* b1;
|
|
49
|
+ cmSmgBox_t* b0;
|
|
50
|
+ cmSmgBox_t* b1;
|
49
|
51
|
struct cmSmgLine_str* link;
|
50
|
52
|
} cmSmgLine_t;
|
51
|
53
|
|
|
54
|
+// Score Location
|
52
|
55
|
typedef struct cmSmgLoc_str
|
53
|
56
|
{
|
54
|
|
- cmSmgBox_t* bV;
|
|
57
|
+ cmSmgBox_t* bV; // List of graphic boxes assigned to this score location
|
55
|
58
|
} cmSmgLoc_t;
|
56
|
59
|
|
|
60
|
+// Score label
|
57
|
61
|
typedef struct
|
58
|
62
|
{
|
59
|
|
- unsigned type;
|
|
63
|
+ unsigned type; // kBarEvtScId | kNonEvtScId
|
|
64
|
+ unsigned barNumb;
|
60
|
65
|
unsigned csvEventId;
|
61
|
66
|
unsigned locIdx;
|
62
|
67
|
cmSmgBox_t* box;
|
63
|
68
|
} cmSmgSc_t;
|
64
|
69
|
|
|
70
|
+// Link a MIDI event to it's matched score label.
|
65
|
71
|
typedef struct cmSmgMatch_str
|
66
|
72
|
{
|
67
|
73
|
cmSmgSc_t* score;
|
68
|
74
|
struct cmSmgMatch_str* link;
|
69
|
75
|
} cmSmgMatch_t;
|
70
|
76
|
|
71
|
|
-typedef struct
|
|
77
|
+// MIDI file event
|
|
78
|
+typedef struct
|
72
|
79
|
{
|
|
80
|
+ double secs;
|
73
|
81
|
unsigned uid;
|
74
|
82
|
unsigned pitch;
|
75
|
83
|
unsigned vel;
|
76
|
|
- cmSmgMatch_t* matchV;
|
|
84
|
+ cmSmgMatch_t* matchV; // list of matches to score events
|
77
|
85
|
cmSmgBox_t* box;
|
78
|
86
|
} cmSmgMidi_t;
|
79
|
87
|
|
|
@@ -82,17 +90,21 @@ typedef struct
|
82
|
90
|
{
|
83
|
91
|
cmErr_t err;
|
84
|
92
|
|
85
|
|
- cmSmgSc_t* scV;
|
|
93
|
+ cmSmgSc_t* scV; // scV[scN] score bars and notes
|
86
|
94
|
unsigned scN;
|
87
|
95
|
|
88
|
|
- cmSmgMidi_t* mV;
|
89
|
|
- unsigned mN;
|
90
|
|
-
|
91
|
|
- cmSmgLoc_t* locV;
|
|
96
|
+ cmSmgLoc_t* locV; // locV[locN] score locations (from the score file)
|
92
|
97
|
unsigned locN;
|
93
|
|
- cmSmgLine_t* lines;
|
94
|
98
|
|
95
|
|
- unsigned boxW;
|
|
99
|
+ cmSmgLine_t* lines; // Graphic lines used to indicate that a midi event matches to multiple score notes.
|
|
100
|
+ // (Each match after the first gets a line from the box representing the midi event
|
|
101
|
+ // to the matching score event)
|
|
102
|
+
|
|
103
|
+ cmSmgMidi_t* mV; // mV[mN] midi note-on events
|
|
104
|
+ unsigned mN;
|
|
105
|
+ double mfDurSecs; // midi file duration in seconds
|
|
106
|
+
|
|
107
|
+ unsigned boxW; // graphic box width and height
|
96
|
108
|
unsigned boxH;
|
97
|
109
|
} cmSmg_t;
|
98
|
110
|
|
|
@@ -219,6 +231,7 @@ cmSmgRC_t _cmSmgInitFromScore( cmCtx_t* ctx, cmSmg_t* p, const cmChar_t* scoreFn
|
219
|
231
|
p->scV[k].type = e->type;
|
220
|
232
|
p->scV[k].csvEventId = e->csvEventId;
|
221
|
233
|
p->scV[k].locIdx = i;
|
|
234
|
+ p->scV[k].barNumb = e->barNumb;
|
222
|
235
|
|
223
|
236
|
if( e->type == kBarEvtScId )
|
224
|
237
|
text = cmTsPrintfP(NULL,"%i",e->barNumb);
|
|
@@ -253,16 +266,19 @@ cmSmgRC_t _cmSmgInitFromMidi( cmCtx_t* ctx, cmSmg_t* p, const cmChar_t* midiFn )
|
253
|
266
|
const cmMidiTrackMsg_t** mV = cmMidiFileMsgArray(mfH);
|
254
|
267
|
unsigned mN = cmMidiFileMsgCount(mfH);
|
255
|
268
|
|
256
|
|
- p->mV = cmMemAllocZ(cmSmgMidi_t,mN);
|
257
|
|
- p->mN = mN;
|
|
269
|
+ p->mV = cmMemAllocZ(cmSmgMidi_t,mN);
|
|
270
|
+ p->mN = mN;
|
|
271
|
+ p->mfDurSecs = cmMidiFileDurSecs(mfH);
|
258
|
272
|
|
259
|
273
|
for(i=0,j=0; i<mN; ++i)
|
260
|
274
|
if( (mV[i]!=NULL) && cmMidiIsChStatus(mV[i]->status) && cmMidiIsNoteOn(mV[i]->status) && (mV[i]->u.chMsgPtr->d1>0) )
|
261
|
275
|
{
|
262
|
276
|
assert(j < mN);
|
|
277
|
+ p->mV[j].secs = mV[i]->amicro / 1000000.0;
|
263
|
278
|
p->mV[j].uid = mV[i]->uid;
|
264
|
279
|
p->mV[j].pitch = mV[i]->u.chMsgPtr->d0;
|
265
|
280
|
p->mV[j].vel = mV[i]->u.chMsgPtr->d1;
|
|
281
|
+
|
266
|
282
|
++j;
|
267
|
283
|
}
|
268
|
284
|
|
|
@@ -565,3 +581,28 @@ cmSmgRC_t cmScoreMatchGraphicWrite( cmSmgH_t h, const cmChar_t* fn )
|
565
|
581
|
cmFileClose(&fH);
|
566
|
582
|
return kOkSmgRC;
|
567
|
583
|
}
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+cmSmgRC_t cmScoreMatchGraphicGenTimeLineBars( cmSmgH_t h, const cmChar_t* fn, unsigned srate )
|
|
587
|
+{
|
|
588
|
+ cmSmgRC_t rc = kOkSmgRC;
|
|
589
|
+ cmFileH_t f = cmFileNullHandle;
|
|
590
|
+ cmSmg_t* p = _cmSmgHandleToPtr(h);
|
|
591
|
+ unsigned i = 0;
|
|
592
|
+
|
|
593
|
+ if( cmFileOpen(&f,fn,kWriteFileFl,p->err.rpt) != kOkFileRC )
|
|
594
|
+ return cmErrMsg(&p->err,kFileSmgRC,"The time-line bar file '%s' could not be created.",cmStringNullGuard(fn));
|
|
595
|
+
|
|
596
|
+ for(i=0; i<p->mN; ++i)
|
|
597
|
+ if( p->mV[i].matchV != NULL && p->mV[i].matchV->score != NULL && p->mV[i].matchV->score > p->scV && p->mV[i].matchV->score[-1].type==kBarEvtScId )
|
|
598
|
+ {
|
|
599
|
+ unsigned bar = p->mV[i].matchV->score->barNumb;
|
|
600
|
+ unsigned offset = p->mV[i].secs * srate;
|
|
601
|
+ unsigned smpCnt = p->mfDurSecs * srate - offset;
|
|
602
|
+ cmFilePrintf(f,"{ label: \"%i\" type: \"mk\" ref: \"mf-0\" offset: %8i smpCnt:%8i trackId: 0 textStr: \"Bar %3i\" bar: %3i sec:\"%3i\" }\n",bar,offset,smpCnt,bar,bar,bar);
|
|
603
|
+ }
|
|
604
|
+
|
|
605
|
+ cmFileClose(&f);
|
|
606
|
+ return rc;
|
|
607
|
+
|
|
608
|
+}
|