|
@@ -8,6 +8,7 @@
|
8
|
8
|
#include "cmLinkedHeap.h"
|
9
|
9
|
#include "cmSymTbl.h"
|
10
|
10
|
#include "cmJson.h"
|
|
11
|
+#include "cmFile.h"
|
11
|
12
|
#include "cmMidi.h"
|
12
|
13
|
#include "cmMidiFile.h"
|
13
|
14
|
#include "cmAudioFile.h"
|
|
@@ -15,18 +16,33 @@
|
15
|
16
|
#include "cmTimeLine.h"
|
16
|
17
|
#include "cmScoreProc.h"
|
17
|
18
|
|
|
19
|
+#include "cmProcObj.h"
|
|
20
|
+#include "cmProc4.h"
|
|
21
|
+
|
18
|
22
|
enum
|
19
|
23
|
{
|
20
|
24
|
kOkSpRC,
|
21
|
25
|
kJsonFailSpRC,
|
22
|
26
|
kScoreFailSpRC,
|
23
|
|
- kTimeLineFailSpRC
|
|
27
|
+ kTimeLineFailSpRC,
|
|
28
|
+ kScoreMatchFailSpRC,
|
|
29
|
+ kFileFailSpRC,
|
24
|
30
|
};
|
25
|
31
|
|
|
32
|
+typedef struct _cmScMeas_t
|
|
33
|
+{
|
|
34
|
+ cmTlMarker_t* markPtr; // time-line marker in which this 'set' exists
|
|
35
|
+ cmScoreSet_t* setPtr; // score set on which this measurment is based
|
|
36
|
+ double value; // the value of the measurement
|
|
37
|
+ double cost; // the quality of the perf->score match
|
|
38
|
+ struct _cmScMeas_t* link;
|
|
39
|
+} _cmScMeas_t;
|
|
40
|
+
|
26
|
41
|
|
27
|
42
|
typedef struct
|
28
|
43
|
{
|
29
|
44
|
cmErr_t err;
|
|
45
|
+ cmCtx* ctx;
|
30
|
46
|
cmScH_t scH;
|
31
|
47
|
const cmChar_t* tlFn;
|
32
|
48
|
cmTlH_t tlH;
|
|
@@ -34,6 +50,12 @@ typedef struct
|
34
|
50
|
unsigned* dynArray;
|
35
|
51
|
unsigned dynCnt;
|
36
|
52
|
double srate;
|
|
53
|
+ cmScMeas* meas;
|
|
54
|
+ cmScMatcher* match;
|
|
55
|
+
|
|
56
|
+ cmTlMarker_t* curMarkPtr;
|
|
57
|
+ _cmScMeas_t* list_beg;
|
|
58
|
+ _cmScMeas_t* list_end;
|
37
|
59
|
} cmSp_t;
|
38
|
60
|
|
39
|
61
|
|
|
@@ -102,12 +124,15 @@ cmSpRC_t _cmScoreProcInit( cmCtx_t* ctx, cmSp_t* p, const cmChar_t* rsrcFn )
|
102
|
124
|
goto errLabel;
|
103
|
125
|
}
|
104
|
126
|
|
105
|
|
- if( cmTimeLineInitialize(ctx, &p->tlH, NULL, NULL ) != kOkTlRC )
|
|
127
|
+ // load the time-line file
|
|
128
|
+ if( cmTimeLineInitializeFromFile(ctx, &p->tlH, NULL, NULL, tlFn ) != kOkTlRC )
|
106
|
129
|
{
|
107
|
130
|
rc = cmErrMsg(&p->err,kTimeLineFailSpRC,"Time line load failed for time line file:%s.",cmStringNullGuard(tlFn));
|
108
|
131
|
goto errLabel;
|
109
|
132
|
}
|
110
|
133
|
|
|
134
|
+ p->ctx = cmCtxAlloc(NULL, &ctx->rpt, cmLHeapNullHandle, cmSymTblNullHandle );
|
|
135
|
+
|
111
|
136
|
errLabel:
|
112
|
137
|
return rc;
|
113
|
138
|
}
|
|
@@ -116,6 +141,8 @@ cmSpRC_t _cmScoreProcFinal( cmSp_t* p )
|
116
|
141
|
{
|
117
|
142
|
cmSpRC_t rc = kOkSpRC;
|
118
|
143
|
|
|
144
|
+ cmCtxFree(&p->ctx);
|
|
145
|
+
|
119
|
146
|
if( cmScoreFinalize(&p->scH) != kOkScRC )
|
120
|
147
|
cmErrMsg(&p->err,kScoreFailSpRC,"Score finalize failed.");
|
121
|
148
|
|
|
@@ -130,10 +157,233 @@ cmSpRC_t _cmScoreProcFinal( cmSp_t* p )
|
130
|
157
|
return rc;
|
131
|
158
|
}
|
132
|
159
|
|
|
160
|
+cmSpRC_t _cmScWriteMeasFile( cmCtx_t* ctx, cmSp_t* sp, const cmChar_t* outFn )
|
|
161
|
+{
|
|
162
|
+ cmFileH_t fH = cmFileNullHandle;
|
|
163
|
+ cmSpRC_t rc = kOkSpRC;
|
|
164
|
+ unsigned i;
|
|
165
|
+
|
|
166
|
+ if( cmFileOpen(&fH,outFn,kWriteFileFl,&ctx->rpt) != kOkFileRC )
|
|
167
|
+ {
|
|
168
|
+ rc = cmErrMsg(&sp->err,kFileFailSpRC,"Unable to create the output file '%s'.",cmStringNullGuard(outFn));
|
|
169
|
+ goto errLabel;
|
|
170
|
+ }
|
|
171
|
+
|
|
172
|
+ cmFilePrintf(fH,"{\n");
|
|
173
|
+
|
|
174
|
+ _cmScMeas_t* mp = sp->list_beg;
|
|
175
|
+ for(; mp!=NULL; mp=mp->link)
|
|
176
|
+ {
|
|
177
|
+ const cmChar_t* typeLabel = NULL;
|
|
178
|
+ switch(mp->setPtr->varId)
|
|
179
|
+ {
|
|
180
|
+ case kEvenVarScId: typeLabel="even"; break;
|
|
181
|
+ case kDynVarScId: typeLabel="dyn"; break;
|
|
182
|
+ case kTempoVarScId:typeLabel="tempo";break;
|
|
183
|
+ default:
|
|
184
|
+ { assert(0); }
|
|
185
|
+ }
|
|
186
|
+
|
|
187
|
+ for(i=0; i<mp->setPtr->sectCnt; ++i)
|
|
188
|
+ {
|
|
189
|
+ cmFilePrintf(fH,"{seq:%i mark:\"%s\" typeId:%i typeLabel:\"%s\" loc:%i evt:%i sect:\"%s\" value:%f cost:%f }\n",
|
|
190
|
+ mp->markPtr->obj.seqId,
|
|
191
|
+ cmStringNullGuard(mp->markPtr->obj.name),
|
|
192
|
+ mp->setPtr->varId,
|
|
193
|
+ typeLabel,
|
|
194
|
+ mp->setPtr->sectArray[i]->locPtr->index,
|
|
195
|
+ mp->setPtr->sectArray[i]->begEvtIndex,
|
|
196
|
+ cmStringNullGuard(mp->setPtr->sectArray[i]->label),
|
|
197
|
+ mp->value,
|
|
198
|
+ mp->cost );
|
|
199
|
+ }
|
|
200
|
+ }
|
|
201
|
+
|
|
202
|
+ cmFilePrintf(fH,"}\n");
|
|
203
|
+
|
|
204
|
+ errLabel:
|
|
205
|
+ if( cmFileClose(&fH) != kOkFileRC )
|
|
206
|
+ cmErrMsg(&sp->err,kFileFailSpRC,"The output file close failed on '%s'.",cmStringNullGuard(outFn));
|
|
207
|
+
|
|
208
|
+ return rc;
|
|
209
|
+}
|
|
210
|
+
|
|
211
|
+void _cmScMatchCb( cmScMatcher* p, void* arg, cmScMatcherResult_t* rp )
|
|
212
|
+{
|
|
213
|
+ cmSp_t* sp = (cmSp_t*)arg;
|
|
214
|
+ cmScMeas* sm = sp->meas;
|
|
215
|
+
|
|
216
|
+ if( cmScMeasExec(sm, rp->mni, rp->locIdx, rp->scEvtIdx, rp->flags, rp->smpIdx, rp->pitch, rp->vel ) == cmOkRC )
|
|
217
|
+ {
|
|
218
|
+ unsigned i;
|
|
219
|
+ for(i=sm->vsi; i<sm->nsi; ++i)
|
|
220
|
+ // ignore set's which did not produce a valid value
|
|
221
|
+ if(sm->set[i].value != DBL_MAX )
|
|
222
|
+ {
|
|
223
|
+ _cmScMeas_t* r = cmMemAllocZ(_cmScMeas_t,1);
|
|
224
|
+ r->markPtr = sp->curMarkPtr;
|
|
225
|
+ r->setPtr = sm->set[i].sp;
|
|
226
|
+ r->value = sm->set[i].value;
|
|
227
|
+ r->cost = sm->set[i].match_cost;
|
|
228
|
+
|
|
229
|
+ if( sp->list_beg == NULL )
|
|
230
|
+ {
|
|
231
|
+ sp->list_beg = r;
|
|
232
|
+ sp->list_end = r;
|
|
233
|
+ }
|
|
234
|
+ else
|
|
235
|
+ {
|
|
236
|
+ sp->list_end->link = r;
|
|
237
|
+ sp->list_end = r;
|
|
238
|
+ }
|
|
239
|
+ }
|
|
240
|
+ }
|
|
241
|
+}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+cmSpRC_t _cmScoreGenAllMeasurements(cmCtx_t* ctx, cmSp_t* sp, const cmChar_t* outFn)
|
|
245
|
+{
|
|
246
|
+ cmSpRC_t rc = kOkSpRC;
|
|
247
|
+ unsigned midiN = 7;
|
|
248
|
+ unsigned scWndN = 10;
|
|
249
|
+ unsigned seqN = cmTimeLineSeqCount(sp->tlH);
|
|
250
|
+ double srate = cmTimeLineSampleRate(sp->tlH);
|
|
251
|
+ unsigned seqId;
|
|
252
|
+
|
|
253
|
+ assert( sp->srate == srate);
|
|
254
|
+
|
|
255
|
+ // allocate the performance eval. object
|
|
256
|
+ sp->meas = cmScMeasAlloc( sp->ctx, NULL, sp->scH, sp->srate, sp->dynArray, sp->dynCnt );
|
|
257
|
+ assert( sp->meas != NULL );
|
|
258
|
+
|
|
259
|
+ // allocate the score matcher
|
|
260
|
+ sp->match = cmScMatcherAlloc(sp->ctx,NULL,sp->srate,sp->scH,scWndN,midiN,_cmScMatchCb,sp);
|
|
261
|
+ assert(sp->match != NULL );
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+ // for each time line sequence
|
|
265
|
+ for(seqId=0; seqId<seqN; ++seqId)
|
|
266
|
+ {
|
|
267
|
+ cmTlObj_t* o0p = NULL;
|
|
268
|
+
|
|
269
|
+ // for each 'marker' in this time line sequence
|
|
270
|
+ while( (o0p = cmTimeLineNextTypeObj(sp->tlH, o0p, seqId, kMarkerTlId)) != NULL )
|
|
271
|
+ {
|
|
272
|
+ // get the 'marker' recd
|
|
273
|
+ cmTlMarker_t* markPtr = cmTimeLineMarkerObjPtr(sp->tlH,o0p);
|
|
274
|
+ assert( markPtr != NULL );
|
|
275
|
+
|
|
276
|
+ // if the marker does not have a valid start bar location
|
|
277
|
+ if( markPtr->bar == 0 )
|
|
278
|
+ continue;
|
|
279
|
+
|
|
280
|
+ // set the marker ptr (which is used in _cmScMatchCb())
|
|
281
|
+ sp->curMarkPtr = markPtr;
|
|
282
|
+
|
|
283
|
+ // get the end-of-marker time as a sample index
|
|
284
|
+ unsigned markEndSmpIdx = markPtr->obj.seqSmpIdx + markPtr->obj.durSmpCnt;
|
|
285
|
+
|
|
286
|
+ // get the score event associated with the marker's bar number.
|
|
287
|
+ const cmScoreEvt_t* evtPtr = cmScoreBarEvt(sp->scH,markPtr->bar);
|
|
288
|
+ assert( evtPtr != NULL );
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+ // get the score location associated with the markers bar score event
|
|
292
|
+ const cmScoreLoc_t* locPtr = cmScoreEvtLoc(sp->scH,evtPtr);
|
|
293
|
+ assert( locPtr != NULL );
|
|
294
|
+
|
|
295
|
+ cmRptPrintf(&ctx->rpt,"Processing loc:%i seq:%i %s %s\n",locPtr->index,seqId,cmStringNullGuard(markPtr->obj.name),cmStringNullGuard(markPtr->text));
|
|
296
|
+
|
|
297
|
+ // reset the performance evaluation object
|
|
298
|
+ if( cmScMeasReset(sp->meas) != cmOkRC )
|
|
299
|
+ {
|
|
300
|
+ cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The score performance evaluation object failed on reset.");
|
|
301
|
+ continue;
|
|
302
|
+ }
|
|
303
|
+
|
|
304
|
+ // reset the score matcher to begin searching at the bar location
|
|
305
|
+ if( cmScMatcherReset(sp->match, locPtr->index ) != cmOkRC )
|
|
306
|
+ {
|
|
307
|
+ cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The score matcher reset failed on location: %i.",locPtr->index);
|
|
308
|
+ continue;
|
|
309
|
+ }
|
|
310
|
+
|
|
311
|
+ cmTlObj_t* o1p = o0p;
|
|
312
|
+
|
|
313
|
+ // as long as more MIDI events are available get the next MIDI msg
|
|
314
|
+ while( (rc == kOkSpRC) && (o1p = cmTimeLineNextTypeObj(sp->tlH, o1p, seqId, kMidiEvtTlId )) != NULL )
|
|
315
|
+ {
|
|
316
|
+ cmTlMidiEvt_t* mep = cmTimeLineMidiEvtObjPtr(sp->tlH,o1p);
|
|
317
|
+ assert(mep != NULL );
|
|
318
|
+
|
|
319
|
+ // if the msg falls after the end of the marker then we are done
|
|
320
|
+ if( mep->obj.seqSmpIdx != cmInvalidIdx && mep->obj.seqSmpIdx > markEndSmpIdx )
|
|
321
|
+ break;
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+ // if the time line MIDI msg a note-on
|
|
325
|
+ if( mep->msg->status == kNoteOnMdId )
|
|
326
|
+ {
|
|
327
|
+ cmRC_t cmRC = cmScMatcherExec(sp->match, mep->obj.seqSmpIdx, mep->msg->status, mep->msg->u.chMsgPtr->d0, mep->msg->u.chMsgPtr->d1, NULL );
|
|
328
|
+
|
|
329
|
+ switch( cmRC )
|
|
330
|
+ {
|
|
331
|
+ case cmOkRC: // continue processing MIDI events
|
|
332
|
+ break;
|
|
333
|
+
|
|
334
|
+ case cmEofRC: // end of the score was encountered
|
|
335
|
+ break;
|
|
336
|
+
|
|
337
|
+ case cmInvalidArgRC: // p->eli was not set correctly
|
|
338
|
+ rc = cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The score matcher failed due to an invalid argument.");
|
|
339
|
+ goto errLabel;
|
|
340
|
+ break;
|
|
341
|
+
|
|
342
|
+ case cmSubSysFailRC: // scan resync failed
|
|
343
|
+ rc = cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The score matcher failed on resync.");
|
|
344
|
+ cmScMatcherPrint(sp->match);
|
|
345
|
+ //goto errLabel;
|
|
346
|
+ break;
|
|
347
|
+
|
|
348
|
+ default:
|
|
349
|
+ { assert(0); }
|
|
350
|
+ }
|
|
351
|
+ }
|
|
352
|
+ }
|
|
353
|
+
|
|
354
|
+ rc = kOkSpRC;
|
|
355
|
+ }
|
|
356
|
+ }
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+ errLabel:
|
|
360
|
+
|
|
361
|
+ if((rc = _cmScWriteMeasFile(ctx, sp, outFn )) != kOkSpRC )
|
|
362
|
+ cmErrMsg(&sp->err,kFileFailSpRC,"The measurement output did not complete without errors.");
|
|
363
|
+
|
|
364
|
+ _cmScMeas_t* mp = sp->list_beg;
|
|
365
|
+ while(mp!=NULL)
|
|
366
|
+ {
|
|
367
|
+ _cmScMeas_t* np = mp->link;
|
|
368
|
+ cmMemFree(mp);
|
|
369
|
+ mp = np;
|
|
370
|
+ }
|
|
371
|
+
|
|
372
|
+ if( cmScMatcherFree(&sp->match) != cmOkRC )
|
|
373
|
+ cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The score matcher release failed.");
|
|
374
|
+
|
|
375
|
+ if( cmScMeasFree(&sp->meas) != cmOkRC )
|
|
376
|
+ cmErrMsg(&sp->err,kScoreMatchFailSpRC,"The performance evaluation object failed.");
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+ return rc;
|
|
380
|
+}
|
|
381
|
+
|
133
|
382
|
unsigned cmScoreProc(cmCtx_t* ctx)
|
134
|
383
|
{
|
135
|
384
|
cmSpRC_t rc = kOkSpRC;
|
136
|
385
|
const cmChar_t* rsrcFn = "/home/kevin/.kc/time_line.js";
|
|
386
|
+ const cmChar_t* outFn = "/home/kevin/temp/meas0.js";
|
137
|
387
|
cmSp_t sp;
|
138
|
388
|
|
139
|
389
|
memset(&sp,0,sizeof(sp));
|
|
@@ -143,7 +393,10 @@ unsigned cmScoreProc(cmCtx_t* ctx)
|
143
|
393
|
if((rc = _cmScoreProcInit(ctx,&sp,rsrcFn)) != kOkSpRC )
|
144
|
394
|
goto errLabel;
|
145
|
395
|
|
|
396
|
+ _cmScoreGenAllMeasurements(ctx,&sp,outFn);
|
146
|
397
|
|
|
398
|
+ //cmScorePrint(sp.scH,&ctx->rpt);
|
|
399
|
+ //cmScorePrintLoc(sp.scH);
|
147
|
400
|
|
148
|
401
|
|
149
|
402
|
errLabel:
|