2013-05-24 20:52:37 +00:00
# include "cmGlobal.h"
# include "cmFloatTypes.h"
# include "cmRpt.h"
# include "cmErr.h"
# include "cmCtx.h"
# include "cmMem.h"
# include "cmMallocDebug.h"
# include "cmLinkedHeap.h"
# include "cmSymTbl.h"
# include "cmJson.h"
2013-07-09 21:06:01 +00:00
# include "cmFile.h"
2013-12-15 23:14:27 +00:00
# include "cmTime.h"
2013-05-24 20:52:37 +00:00
# include "cmMidi.h"
# include "cmMidiFile.h"
# include "cmAudioFile.h"
# include "cmScore.h"
# include "cmTimeLine.h"
# include "cmScoreProc.h"
2013-07-09 21:06:01 +00:00
# include "cmProcObj.h"
# include "cmProc4.h"
2015-02-09 18:13:12 +00:00
typedef enum
2013-07-09 21:06:01 +00:00
{
2015-02-25 18:43:21 +00:00
kBeginTakeSpId , // tlObjPtr points to a cmTlMarker_t object.
kEndTakeSpId , // tlObjPtr is NULL.
kNoteOnSpId , // tlObjPtr points to a cmTlMidiEvt_t note-on object.
kFailSpId // tlObjPtr points to a cmTlMarker_t object (This takes score tracking failed.)
2015-02-09 18:13:12 +00:00
} cmScoreProcSelId_t ;
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
struct cmSp_str ;
2013-05-24 20:52:37 +00:00
2015-02-19 00:39:14 +00:00
typedef cmSpRC_t ( * cmScoreProcCb_t ) ( void * arg , struct cmSp_str * p , cmScoreProcSelId_t id , cmTlObj_t * tlObjPtr ) ;
2015-02-09 18:13:12 +00:00
typedef struct cmSp_str
2013-05-24 20:52:37 +00:00
{
2015-02-08 16:55:57 +00:00
cmErr_t err ; // score proc object error state
cmCtx * ctx ; // application context
cmScH_t scH ; // score object
cmTlH_t tlH ; // time-line object
cmJsonH_t jsH ; //
unsigned * dynArray ; // dynArray[dynCnt] dynamics reference array
unsigned dynCnt ; //
double srate ; //
cmScMatcher * match ; // score follower
2013-07-09 21:06:01 +00:00
2015-02-25 18:43:21 +00:00
cmScoreProcCb_t procCb ; // score processor callback - called whenever a new 'marker' take or note-on is about to be processed
2015-02-19 00:39:14 +00:00
cmScMatcherCb_t matchCb ; // score follower callback - called whenever the score follower detects a matched event
2015-02-09 18:13:12 +00:00
void * cbArg ; // callback arg. for both matchCb and procCb.
2013-05-24 20:52:37 +00:00
} cmSp_t ;
2013-07-11 19:20:34 +00:00
// read the dynamics reference array from the time-line project file.
2013-05-24 20:52:37 +00:00
cmSpRC_t _cmJsonReadDynArray ( cmJsonH_t jsH , unsigned * * dynArray , unsigned * dynCnt )
{
cmJsonNode_t * np ;
int i ;
if ( cmJsonPathToArray ( jsH , NULL , NULL , " dynRef " , & np ) ! = kOkJsRC )
return kJsonFailSpRC ;
* dynCnt = cmJsonChildCount ( np ) ;
* dynArray = cmMemAllocZ ( unsigned , * dynCnt ) ;
for ( i = 0 ; i < * dynCnt ; + + i )
if ( cmJsonUIntValue ( cmJsonArrayElement ( np , i ) , ( * dynArray ) + i ) ! = kOkJsRC )
return kJsonFailSpRC ;
return kOkSpRC ;
}
2015-02-19 00:39:14 +00:00
cmSpRC_t _cmScoreProcInit (
cmCtx_t * ctx ,
cmSp_t * p ,
const cmChar_t * rsrcFn ,
cmScoreProcCb_t procCb ,
cmScMatcherCb_t matchCb ,
void * cbArg )
2013-05-24 20:52:37 +00:00
{
cmSpRC_t rc = kOkSpRC ;
const cmChar_t * scFn = NULL ;
const cmChar_t * tlFn = NULL ;
2013-08-12 07:05:58 +00:00
const cmChar_t * tlPrefixPath = NULL ;
2013-05-24 20:52:37 +00:00
cmErrSetup ( & p - > err , & ctx - > rpt , " ScoreProc " ) ;
// open the resource file
if ( cmJsonInitializeFromFile ( & p - > jsH , rsrcFn , ctx ) ! = kOkJsRC )
{
rc = cmErrMsg ( & p - > err , kJsonFailSpRC , " Unable to load the main resource file:%s. " , cmStringNullGuard ( rsrcFn ) ) ;
goto errLabel ;
}
// get the time line fn
if ( cmJsonPathToString ( p - > jsH , NULL , NULL , " timeLineFn " , & tlFn ) ! = kOkJsRC )
{
rc = cmErrMsg ( & p - > err , kJsonFailSpRC , " Unable to locate the time line file name in the main resource file:%s " , cmStringNullGuard ( rsrcFn ) ) ;
goto errLabel ;
}
// get the score file name
if ( cmJsonPathToString ( p - > jsH , NULL , NULL , " scoreFn " , & scFn ) ! = kOkJsRC )
{
rc = cmErrMsg ( & p - > err , kJsonFailSpRC , " Unable to locate the score file name in the main resource file:%s " , cmStringNullGuard ( rsrcFn ) ) ;
goto errLabel ;
}
2013-08-12 07:05:58 +00:00
// get the time line data file prefix path
if ( cmJsonPathToString ( p - > jsH , NULL , NULL , " tlPrefixPath " , & tlPrefixPath ) ! = kOkJsRC )
{
rc = cmErrMsg ( & p - > err , kJsonFailSpRC , " Unable to locate the time line data file prefix path in the main resource file:%s " , cmStringNullGuard ( rsrcFn ) ) ;
goto errLabel ;
}
2013-05-24 20:52:37 +00:00
// read the dynamics reference array
if ( ( rc = _cmJsonReadDynArray ( p - > jsH , & p - > dynArray , & p - > dynCnt ) ) ! = kOkSpRC )
{
rc = cmErrMsg ( & p - > err , rc , " Unable to read dynamics reference array resource from the main resource file:%s " , cmStringNullGuard ( rsrcFn ) ) ;
goto errLabel ;
}
2015-02-09 18:13:12 +00:00
// load the time-line file
if ( cmTimeLineInitializeFromFile ( ctx , & p - > tlH , NULL , NULL , tlFn , tlPrefixPath ) ! = kOkTlRC )
{
rc = cmErrMsg ( & p - > err , kTimeLineFailSpRC , " Time line load failed for time line file:%s. " , cmStringNullGuard ( tlFn ) ) ;
goto errLabel ;
}
p - > srate = cmTimeLineSampleRate ( p - > tlH ) ;
2013-05-24 20:52:37 +00:00
// load the score file
if ( cmScoreInitialize ( ctx , & p - > scH , scFn , p - > srate , NULL , 0 , NULL , NULL , cmSymTblNullHandle ) ! = kOkScRC )
{
rc = cmErrMsg ( & p - > err , kScoreFailSpRC , " Score load failed for score file:%s. " , cmStringNullGuard ( scFn ) ) ;
goto errLabel ;
}
2015-02-19 00:39:14 +00:00
p - > ctx = cmCtxAlloc ( NULL , & ctx - > rpt , cmLHeapNullHandle , cmSymTblNullHandle ) ;
2015-02-09 18:13:12 +00:00
p - > matchCb = matchCb ;
p - > procCb = procCb ;
p - > cbArg = cbArg ;
errLabel :
return rc ;
}
2015-02-19 00:39:14 +00:00
// This function iterates through each sequence and advances
// to each 'begin-marker' position.
2015-02-09 18:13:12 +00:00
cmSpRC_t _cmScoreProcProcess ( cmCtx_t * ctx , cmSp_t * sp )
{
cmSpRC_t rc = kOkSpRC ;
unsigned midiN = 7 ;
unsigned scWndN = 10 ;
unsigned seqN = cmTimeLineSeqCount ( sp - > tlH ) ;
double srate = cmTimeLineSampleRate ( sp - > tlH ) ;
unsigned seqId ;
assert ( sp - > srate = = srate ) ;
// allocate the score matcher
sp - > match = cmScMatcherAlloc ( sp - > ctx , NULL , sp - > srate , sp - > scH , scWndN , midiN , sp - > matchCb , sp - > cbArg ) ;
assert ( sp - > match ! = NULL ) ;
// for each time line sequence
for ( seqId = 0 ; seqId < seqN ; + + seqId )
2013-05-24 20:52:37 +00:00
{
2015-02-09 18:13:12 +00:00
cmTlObj_t * o0p = NULL ;
// for each 'marker' in this time line sequence
while ( ( o0p = cmTimeLineNextTypeObj ( sp - > tlH , o0p , seqId , kMarkerTlId ) ) ! = NULL )
{
// get the 'marker' recd
cmTlMarker_t * markPtr = cmTimeLineMarkerObjPtr ( sp - > tlH , o0p ) ;
assert ( markPtr ! = NULL ) ;
// if the marker does not have a valid start bar location
if ( markPtr - > bar = = 0 )
continue ;
// get the end-of-marker time as a sample index
unsigned markEndSmpIdx = markPtr - > obj . seqSmpIdx + markPtr - > obj . durSmpCnt ;
// get the score event associated with the marker's bar number.
const cmScoreEvt_t * evtPtr = cmScoreBarEvt ( sp - > scH , markPtr - > bar ) ;
assert ( evtPtr ! = NULL ) ;
// get the score location associated with the markers bar score event
const cmScoreLoc_t * locPtr = cmScoreEvtLoc ( sp - > scH , evtPtr ) ;
assert ( locPtr ! = NULL ) ;
cmRptPrintf ( & ctx - > rpt , " Processing loc:%i seq:%i %s %s \n " , locPtr - > index , seqId , cmStringNullGuard ( markPtr - > obj . name ) , cmStringNullGuard ( markPtr - > text ) ) ;
2015-02-19 00:39:14 +00:00
// reset the score matcher to begin searching at the bar location
if ( cmScMatcherReset ( sp - > match , locPtr - > index ) ! = cmOkRC )
2015-02-09 18:13:12 +00:00
{
2015-02-19 00:39:14 +00:00
cmErrMsg ( & sp - > err , kScoreMatchFailSpRC , " The score matcher reset failed on location: %i. " , locPtr - > index ) ;
2015-02-09 18:13:12 +00:00
continue ;
}
2015-02-25 18:43:21 +00:00
// inform the score processor that we are about to start a new take
if ( sp - > procCb ( sp - > cbArg , sp , kBeginTakeSpId , o0p ) ! = kOkSpRC )
2015-02-09 18:13:12 +00:00
{
2015-02-19 00:39:14 +00:00
cmErrMsg ( & sp - > err , kProcFailSpRC , " The score process object failed on reset. " ) ;
2015-02-09 18:13:12 +00:00
continue ;
}
2015-02-19 00:39:14 +00:00
cmTlObj_t * o1p = o0p ;
bool errFl = false ;
2015-02-09 18:13:12 +00:00
// as long as more MIDI events are available get the next MIDI msg
while ( ( rc = = kOkSpRC ) & & ( o1p = cmTimeLineNextTypeObj ( sp - > tlH , o1p , seqId , kMidiEvtTlId ) ) ! = NULL )
{
cmTlMidiEvt_t * mep = cmTimeLineMidiEvtObjPtr ( sp - > tlH , o1p ) ;
assert ( mep ! = NULL ) ;
// if the msg falls after the end of the marker then we are done
if ( mep - > obj . seqSmpIdx ! = cmInvalidIdx & & mep - > obj . seqSmpIdx > markEndSmpIdx )
break ;
2015-02-19 00:39:14 +00:00
// if the time line MIDI msg is a note-on
2015-02-09 18:13:12 +00:00
if ( mep - > msg - > status = = kNoteOnMdId )
{
2015-02-19 00:39:14 +00:00
sp - > procCb ( sp - > cbArg , sp , kNoteOnSpId , o1p ) ;
2015-02-09 18:13:12 +00:00
cmRC_t cmRC = cmScMatcherExec ( sp - > match , mep - > obj . seqSmpIdx , mep - > msg - > status , mep - > msg - > u . chMsgPtr - > d0 , mep - > msg - > u . chMsgPtr - > d1 , NULL ) ;
switch ( cmRC )
{
case cmOkRC : // continue processing MIDI events
break ;
case cmEofRC : // end of the score was encountered
break ;
case cmInvalidArgRC : // p->eli was not set correctly
rc = cmErrMsg ( & sp - > err , kScoreMatchFailSpRC , " The score matcher failed due to an invalid argument. " ) ;
2015-02-19 00:39:14 +00:00
errFl = true ;
2015-02-09 18:13:12 +00:00
break ;
case cmSubSysFailRC : // scan resync failed
rc = cmErrMsg ( & sp - > err , kScoreMatchFailSpRC , " The score matcher failed on resync. " ) ;
2015-02-19 00:39:14 +00:00
sp - > procCb ( sp - > cbArg , sp , kFailSpId , o0p ) ;
//cmScMatcherPrint(sp->match);
2015-02-09 18:13:12 +00:00
//goto errLabel;
break ;
default :
{ assert ( 0 ) ; }
}
}
}
2015-02-25 18:43:21 +00:00
// inform the score processor that we done processing a take
if ( sp - > procCb ( sp - > cbArg , sp , kEndTakeSpId , NULL ) ! = kOkSpRC )
2015-02-09 18:13:12 +00:00
cmErrMsg ( & sp - > err , kProcFailSpRC , " The score process object failed on reset. " ) ;
2015-02-25 18:43:21 +00:00
// error flag is used to break out of the loop after the 'end-take' is called
2015-02-19 00:39:14 +00:00
// so that the user defined processes has a chance to clean-up
if ( errFl )
goto errLabel ;
2015-02-09 18:13:12 +00:00
rc = kOkSpRC ;
}
2013-05-24 20:52:37 +00:00
}
2013-07-09 21:06:01 +00:00
2013-05-24 20:52:37 +00:00
errLabel :
2015-02-09 18:13:12 +00:00
if ( cmScMatcherFree ( & sp - > match ) ! = cmOkRC )
cmErrMsg ( & sp - > err , kScoreMatchFailSpRC , " The score matcher release failed. " ) ;
2013-05-24 20:52:37 +00:00
return rc ;
}
cmSpRC_t _cmScoreProcFinal ( cmSp_t * p )
{
cmSpRC_t rc = kOkSpRC ;
2013-07-09 21:06:01 +00:00
cmCtxFree ( & p - > ctx ) ;
2013-05-24 20:52:37 +00:00
if ( cmScoreFinalize ( & p - > scH ) ! = kOkScRC )
cmErrMsg ( & p - > err , kScoreFailSpRC , " Score finalize failed. " ) ;
if ( cmTimeLineFinalize ( & p - > tlH ) ! = kOkTlRC )
cmErrMsg ( & p - > err , kTimeLineFailSpRC , " Time line finalize failed. " ) ;
if ( cmJsonFinalize ( & p - > jsH ) ! = kOkJsRC )
cmErrMsg ( & p - > err , kJsonFailSpRC , " JSON finalize failed. " ) ;
cmMemFree ( p - > dynArray ) ;
return rc ;
}
2015-02-09 18:13:12 +00:00
//==================================================================================================
2013-07-11 19:20:34 +00:00
2015-02-09 18:13:12 +00:00
typedef struct _cmSpMeas_t
{
cmTlMarker_t * markPtr ; // time-line marker in which this 'set' exists
cmScoreSet_t * setPtr ; // score set on which this measurment is based
double value ; // the value of the measurement
double cost ; // the quality of the perf->score match
struct _cmSpMeas_t * link ;
} _cmSpMeas_t ;
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
typedef struct
{
struct cmSp_str * sp ;
cmScMeas * meas ; // performance analyzer
cmTlMarker_t * curMarkPtr ; //
_cmSpMeas_t * list_beg ; //
_cmSpMeas_t * list_end ; //
_cmSpMeas_t * slist_beg ; //
} _cmSpMeasProc_t ;
2013-07-09 21:06:01 +00:00
2013-07-11 19:20:34 +00:00
typedef struct
{
unsigned srcSeqId ;
const cmChar_t * srcMarkNameStr ;
unsigned srcTypeId ;
const cmChar_t * srcTypeLabelStr ;
unsigned dstScLocIdx ;
unsigned dstEvtIdx ;
const cmChar_t * dstSectLabelStr ;
double value ;
double cost ;
2015-02-09 18:13:12 +00:00
} _cmSpMeasSect_t ;
unsigned _cmSpMeasSectCount ( _cmSpMeasProc_t * m )
{
const _cmSpMeas_t * mp = m - > list_beg ;
unsigned n = 0 ;
for ( ; mp ! = NULL ; mp = mp - > link )
n + = mp - > setPtr - > sectCnt ;
return n ;
}
2013-07-11 19:20:34 +00:00
2015-02-09 18:13:12 +00:00
int _cmSpMeasSectCompare ( const void * p0 , const void * p1 )
2013-07-11 19:20:34 +00:00
{
2015-02-09 18:13:12 +00:00
_cmSpMeasSect_t * m0 = ( _cmSpMeasSect_t * ) p0 ;
_cmSpMeasSect_t * m1 = ( _cmSpMeasSect_t * ) p1 ;
2013-07-09 21:06:01 +00:00
2013-07-11 19:20:34 +00:00
return ( int ) m0 - > dstScLocIdx - ( int ) m1 - > dstScLocIdx ;
}
2015-02-09 18:13:12 +00:00
cmSpRC_t _cmScWriteMeasFile ( cmCtx_t * ctx , cmSp_t * sp , _cmSpMeasProc_t * m , const cmChar_t * outFn )
2013-07-11 19:20:34 +00:00
{
cmFileH_t fH = cmFileNullHandle ;
cmSpRC_t rc = kOkSpRC ;
unsigned i , j , k ;
2015-02-09 18:13:12 +00:00
_cmSpMeas_t * mp = m - > list_beg ;
2013-07-11 19:20:34 +00:00
2015-02-09 18:13:12 +00:00
unsigned scnt = _cmSpMeasSectCount ( m ) ;
_cmSpMeasSect_t sarray [ scnt ] ;
2013-07-11 19:20:34 +00:00
for ( i = 0 , k = 0 ; k < scnt & & mp ! = NULL ; + + i , mp = mp - > link )
2013-07-09 21:06:01 +00:00
{
const cmChar_t * typeLabel = NULL ;
switch ( mp - > setPtr - > varId )
{
case kEvenVarScId : typeLabel = " even " ; break ;
case kDynVarScId : typeLabel = " dyn " ; break ;
case kTempoVarScId : typeLabel = " tempo " ; break ;
default :
{ assert ( 0 ) ; }
}
2013-07-11 19:20:34 +00:00
for ( j = 0 ; j < mp - > setPtr - > sectCnt ; + + j , + + k )
{
2015-02-09 18:13:12 +00:00
_cmSpMeasSect_t * r = sarray + k ;
2013-07-11 19:20:34 +00:00
r - > srcSeqId = mp - > markPtr - > obj . seqId ,
r - > srcMarkNameStr = cmStringNullGuard ( mp - > markPtr - > obj . name ) ,
r - > srcTypeId = mp - > setPtr - > varId ,
r - > srcTypeLabelStr = typeLabel ,
r - > dstScLocIdx = mp - > setPtr - > sectArray [ j ] - > locPtr - > index ,
r - > dstEvtIdx = mp - > setPtr - > sectArray [ j ] - > begEvtIndex ,
r - > dstSectLabelStr = cmStringNullGuard ( mp - > setPtr - > sectArray [ j ] - > label ) ,
r - > value = mp - > value ,
r - > cost = mp - > cost ;
}
}
assert ( mp = = NULL & & k = = scnt ) ;
2015-02-09 18:13:12 +00:00
qsort ( sarray , scnt , sizeof ( sarray [ 0 ] ) , _cmSpMeasSectCompare ) ;
2013-07-11 19:20:34 +00:00
if ( cmFileOpen ( & fH , outFn , kWriteFileFl , & ctx - > rpt ) ! = kOkFileRC )
{
rc = cmErrMsg ( & sp - > err , kFileFailSpRC , " Unable to create the output file '%s'. " , cmStringNullGuard ( outFn ) ) ;
goto errLabel ;
}
cmFilePrintf ( fH , " { \n meas : \n [ \n [ \" sec \" \" typeLabel \" \" val \" \" cost \" \" loc \" \" evt \" \" seq \" \" mark \" \" typeId \" ] \n " ) ;
for ( i = 0 ; i < scnt ; + + i )
{
2015-02-09 18:13:12 +00:00
_cmSpMeasSect_t * r = sarray + i ;
2013-07-11 19:20:34 +00:00
cmFilePrintf ( fH , " [ \" %s \" \" %s \" %f %f %i %i %i \" %s \" %i ] \n " ,
r - > dstSectLabelStr ,
r - > srcTypeLabelStr ,
r - > value ,
r - > cost ,
r - > dstScLocIdx ,
r - > dstEvtIdx ,
r - > srcSeqId ,
r - > srcMarkNameStr ,
r - > srcTypeId
) ;
}
/*
mp = sp - > list_beg ;
for ( ; mp ! = NULL ; mp = mp - > link )
{
2013-07-09 21:06:01 +00:00
for ( i = 0 ; i < mp - > setPtr - > sectCnt ; + + i )
{
2013-07-10 00:08:41 +00:00
cmFilePrintf ( fH , " [ %i \" %s \" %i \" %s \" %i %i \" %s \" %f %f ] \n " ,
2013-07-09 21:06:01 +00:00
mp - > markPtr - > obj . seqId ,
cmStringNullGuard ( mp - > markPtr - > obj . name ) ,
mp - > setPtr - > varId ,
typeLabel ,
mp - > setPtr - > sectArray [ i ] - > locPtr - > index ,
mp - > setPtr - > sectArray [ i ] - > begEvtIndex ,
cmStringNullGuard ( mp - > setPtr - > sectArray [ i ] - > label ) ,
mp - > value ,
mp - > cost ) ;
}
}
2013-07-11 19:20:34 +00:00
*/
2013-07-09 21:06:01 +00:00
2013-07-10 00:08:41 +00:00
cmFilePrintf ( fH , " \n ] \n } \n " ) ;
2013-07-09 21:06:01 +00:00
errLabel :
if ( cmFileClose ( & fH ) ! = kOkFileRC )
cmErrMsg ( & sp - > err , kFileFailSpRC , " The output file close failed on '%s'. " , cmStringNullGuard ( outFn ) ) ;
return rc ;
}
2015-02-09 18:13:12 +00:00
// score matcher callback
void _cmSpMatchMeasCb ( cmScMatcher * p , void * arg , cmScMatcherResult_t * rp )
2013-07-09 21:06:01 +00:00
{
2015-02-09 18:13:12 +00:00
_cmSpMeasProc_t * m = ( _cmSpMeasProc_t * ) arg ;
cmScMeas * sm = m - > meas ;
2013-07-09 21:06:01 +00:00
if ( cmScMeasExec ( sm , rp - > mni , rp - > locIdx , rp - > scEvtIdx , rp - > flags , rp - > smpIdx , rp - > pitch , rp - > vel ) = = cmOkRC )
{
unsigned i ;
for ( i = sm - > vsi ; i < sm - > nsi ; + + i )
// ignore set's which did not produce a valid value
if ( sm - > set [ i ] . value ! = DBL_MAX )
{
2015-02-09 18:13:12 +00:00
_cmSpMeas_t * r = cmMemAllocZ ( _cmSpMeas_t , 1 ) ;
r - > markPtr = m - > curMarkPtr ;
2013-07-09 21:06:01 +00:00
r - > setPtr = sm - > set [ i ] . sp ;
r - > value = sm - > set [ i ] . value ;
r - > cost = sm - > set [ i ] . match_cost ;
2015-02-09 18:13:12 +00:00
if ( m - > list_beg = = NULL )
2013-07-09 21:06:01 +00:00
{
2015-02-09 18:13:12 +00:00
m - > list_beg = r ;
m - > list_end = r ;
2013-07-09 21:06:01 +00:00
}
else
{
2015-02-09 18:13:12 +00:00
m - > list_end - > link = r ;
m - > list_end = r ;
2013-07-09 21:06:01 +00:00
}
}
}
}
2015-02-09 18:13:12 +00:00
// measurement proc callback
2015-02-19 00:39:14 +00:00
cmSpRC_t _cmSpProcMeasCb ( void * arg , cmSp_t * sp , cmScoreProcSelId_t id , cmTlObj_t * tlObjPtr )
2013-07-09 21:06:01 +00:00
{
2015-02-09 18:13:12 +00:00
cmSpRC_t rc = kOkSpRC ;
_cmSpMeasProc_t * m = ( _cmSpMeasProc_t * ) arg ;
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
switch ( id )
2013-07-09 21:06:01 +00:00
{
2015-02-25 18:43:21 +00:00
case kBeginTakeSpId :
2013-07-09 21:06:01 +00:00
// reset the performance evaluation object
2015-02-09 18:13:12 +00:00
if ( cmScMeasReset ( m - > meas ) ! = cmOkRC )
rc = cmErrMsg ( & sp - > err , kScoreMatchFailSpRC , " The score performance evaluation object failed on reset. " ) ;
2013-07-09 21:06:01 +00:00
2015-02-19 00:39:14 +00:00
m - > curMarkPtr = cmTimeLineMarkerObjPtr ( sp - > tlH , tlObjPtr ) ;
break ;
case kNoteOnSpId :
2015-02-09 18:13:12 +00:00
break ;
2013-07-09 21:06:01 +00:00
2015-02-25 18:43:21 +00:00
case kEndTakeSpId :
2015-02-09 18:13:12 +00:00
break ;
2015-02-19 00:39:14 +00:00
case kFailSpId :
break ;
2015-02-09 18:13:12 +00:00
}
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
return rc ;
}
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
cmSpRC_t _cmScoreProcGenAllMeasurementsMain ( cmCtx_t * ctx )
{
const cmChar_t * rsrcFn = " /home/kevin/.kc/time_line.js " ;
const cmChar_t * outFn = " /home/kevin/src/cmkc/src/kc/data/meas0.js " ;
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
cmSpRC_t rc = kOkSpRC ;
_cmSpMeasProc_t * m = cmMemAllocZ ( _cmSpMeasProc_t , 1 ) ;
cmSp_t s ;
cmSp_t * sp = & s ;
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
memset ( sp , 0 , sizeof ( s ) ) ;
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
cmRptPrintf ( & ctx - > rpt , " Score Performance Evaluation Start \n " ) ;
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
// initialize the score processor
if ( ( rc = _cmScoreProcInit ( ctx , sp , rsrcFn , _cmSpProcMeasCb , _cmSpMatchMeasCb , m ) ) ! = kOkSpRC )
goto errLabel ;
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
// allocate the performance evaluation measurement object
m - > meas = cmScMeasAlloc ( sp - > ctx , NULL , sp - > scH , sp - > srate , sp - > dynArray , sp - > dynCnt ) ;
m - > sp = sp ;
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
// run the score processor
_cmScoreProcProcess ( ctx , sp ) ;
2013-07-09 21:06:01 +00:00
2015-02-09 18:13:12 +00:00
// write the results of the performance evaluation
if ( ( rc = _cmScWriteMeasFile ( ctx , sp , m , outFn ) ) ! = kOkSpRC )
2013-07-09 21:06:01 +00:00
cmErrMsg ( & sp - > err , kFileFailSpRC , " The measurement output did not complete without errors. " ) ;
2015-02-09 18:13:12 +00:00
// free the measurement linked list
_cmSpMeas_t * mp = m - > list_beg ;
2013-07-09 21:06:01 +00:00
while ( mp ! = NULL )
{
2015-02-09 18:13:12 +00:00
_cmSpMeas_t * np = mp - > link ;
2013-07-09 21:06:01 +00:00
cmMemFree ( mp ) ;
mp = np ;
}
2015-02-09 18:13:12 +00:00
// free the performance evaluation object
if ( cmScMeasFree ( & m - > meas ) ! = cmOkRC )
2013-07-09 21:06:01 +00:00
cmErrMsg ( & sp - > err , kScoreMatchFailSpRC , " The performance evaluation object failed. " ) ;
2015-02-09 18:13:12 +00:00
//cmScorePrint(sp.scH,&ctx->rpt);
//cmScorePrintLoc(sp.scH);
errLabel :
_cmScoreProcFinal ( sp ) ;
cmMemFree ( m ) ;
cmRptPrintf ( & ctx - > rpt , " Score Proc End \n " ) ;
2013-07-09 21:06:01 +00:00
return rc ;
2015-02-09 18:13:12 +00:00
2013-07-09 21:06:01 +00:00
}
2015-02-08 16:55:57 +00:00
//==================================================================================================
2015-02-19 00:39:14 +00:00
typedef struct cmSpAssoc_str
{
unsigned scEvtIdx ; // score event index
unsigned tlUid ; // time-line MIDI note-on object id
struct cmSpAssoc_str * link ;
} cmSpAssoc_t ;
typedef struct cmSpNoteMap_str
{
unsigned tlUid ; // time-line MIDI note-on object id
unsigned mni ; // assocated 'mni' returned in a cmScMatcherResult_t record
struct cmSpNoteMap_str * link ;
} cmSpNoteMap_t ;
2015-02-09 18:13:12 +00:00
typedef struct
{
2015-02-19 00:39:14 +00:00
cmCtx_t * ctx ;
cmSp_t * sp ;
unsigned mni ;
bool failFl ;
cmJsonH_t jsH ;
2015-02-25 18:43:21 +00:00
cmJsonNode_t * takeObj ;
2015-02-19 00:39:14 +00:00
cmJsonNode_t * array ;
cmSpAssoc_t * bap ;
cmSpAssoc_t * eap ;
cmSpNoteMap_t * bmp ;
cmSpNoteMap_t * emp ;
} cmSpAssocProc_t ;
2015-02-08 16:55:57 +00:00
2015-02-19 00:39:14 +00:00
void _cmSpMatchAssocCb ( cmScMatcher * p , void * arg , cmScMatcherResult_t * rp )
2015-02-09 18:13:12 +00:00
{
2015-02-19 00:39:14 +00:00
cmSpAssocProc_t * m = ( cmSpAssocProc_t * ) arg ;
if ( cmJsonCreateFilledObject ( m - > jsH , m - > array ,
" mni " , kIntTId , rp - > mni ,
" scEvtIdx " , kIntTId , rp - > scEvtIdx ,
" flags " , kIntTId , rp - > flags ,
NULL ) = = NULL )
{
cmErrMsg ( & m - > ctx - > err , kJsonFailSpRC , " JSON association record create failed. " ) ;
}
//cmScoreEvt_t* sep = rp->scEvtIdx == -1 ? NULL : cmScoreEvt( m->sp->scH, rp->scEvtIdx );
//printf("%3i loc:%4i pitch=%3i %3i flags=0x%x\n",rp->mni,rp->locIdx,rp->pitch,sep==NULL ? -1 : sep->pitch,rp->flags );
2015-02-09 18:13:12 +00:00
}
2015-02-19 00:39:14 +00:00
cmSpRC_t _cmSpProcAssocCb ( void * arg , cmSp_t * sp , cmScoreProcSelId_t id , cmTlObj_t * tlObjPtr )
2015-02-09 18:13:12 +00:00
{
2015-02-19 00:39:14 +00:00
cmSpRC_t rc = kOkSpRC ;
cmSpAssocProc_t * m = ( cmSpAssocProc_t * ) arg ;
switch ( id )
{
2015-02-25 18:43:21 +00:00
case kBeginTakeSpId :
2015-02-19 00:39:14 +00:00
{
cmTlMarker_t * markPtr = cmTimeLineMarkerObjPtr ( sp - > tlH , tlObjPtr ) ;
assert ( markPtr ! = NULL ) ;
m - > mni = 0 ;
m - > failFl = false ;
// insert a section object
2015-02-25 18:43:21 +00:00
if ( ( m - > takeObj = cmJsonInsertPairObject ( m - > jsH , cmJsonRoot ( m - > jsH ) , " take " ) ) = = NULL )
2015-02-19 00:39:14 +00:00
{
2015-02-25 18:43:21 +00:00
rc = cmErrMsg ( & m - > ctx - > err , kJsonFailSpRC , " Take insert failed on seq:%i '%s' : '%s'. " , tlObjPtr - > seqId , cmStringNullGuard ( tlObjPtr - > text ) , cmStringNullGuard ( markPtr - > text ) ) ;
2015-02-19 00:39:14 +00:00
goto errLabel ;
}
// set the section time-line UID
2015-02-25 18:43:21 +00:00
if ( cmJsonInsertPairInt ( m - > jsH , m - > takeObj , " markerUid " , tlObjPtr - > uid ) ! = kOkJsRC )
2015-02-19 00:39:14 +00:00
{
rc = cmErrMsg ( & m - > ctx - > err , kJsonFailSpRC , " Marker uid field insert failed on seq:%i '%s' : '%s'. " , tlObjPtr - > seqId , cmStringNullGuard ( tlObjPtr - > text ) , cmStringNullGuard ( markPtr - > text ) ) ;
goto errLabel ;
}
// create an array to hold the assoc results
2015-02-25 18:43:21 +00:00
if ( ( m - > array = cmJsonInsertPairArray ( m - > jsH , m - > takeObj , " array " ) ) = = NULL )
2015-02-19 00:39:14 +00:00
{
rc = cmErrMsg ( & m - > ctx - > err , kJsonFailSpRC , " Marker array field insert failed on seq:%i '%s' : '%s'. " , tlObjPtr - > seqId , cmStringNullGuard ( tlObjPtr - > text ) , cmStringNullGuard ( markPtr - > text ) ) ;
goto errLabel ;
}
}
break ;
2015-02-25 18:43:21 +00:00
case kEndTakeSpId :
2015-02-19 00:39:14 +00:00
{
while ( m - > bmp ! = NULL )
{
cmSpNoteMap_t * nmp = m - > bmp - > link ;
cmMemFree ( m - > bmp ) ;
m - > bmp = nmp ;
}
m - > bmp = NULL ;
m - > emp = NULL ;
2015-02-09 18:13:12 +00:00
2015-02-25 18:43:21 +00:00
if ( cmJsonInsertPairInt ( m - > jsH , m - > takeObj , " failFl " , m - > failFl ) ! = kOkJsRC )
2015-02-19 00:39:14 +00:00
{
rc = cmErrMsg ( & m - > ctx - > err , kJsonFailSpRC , " JSON fail flag insert failed. " ) ;
goto errLabel ;
}
}
break ;
case kNoteOnSpId :
{
// create a cmSpNoteMap_t record ...
cmSpNoteMap_t * map = cmMemAllocZ ( cmSpNoteMap_t , 1 ) ;
map - > tlUid = tlObjPtr - > uid ;
map - > mni = m - > mni ;
// .. and insert it in the note-map list
if ( m - > emp = = NULL )
{
m - > bmp = map ;
m - > emp = map ;
}
else
{
m - > emp - > link = map ;
m - > emp = map ;
}
m - > mni + = 1 ;
}
break ;
case kFailSpId :
m - > failFl = true ;
break ;
}
errLabel :
return rc ;
2015-02-09 18:13:12 +00:00
}
2015-02-19 00:39:14 +00:00
cmSpRC_t _cmScoreProcGenAssocMain ( cmCtx_t * ctx )
2013-05-24 20:52:37 +00:00
{
2015-02-19 00:39:14 +00:00
const cmChar_t * rsrcFn = " /home/kevin/.kc/time_line.js " ;
const cmChar_t * outFn = " /home/kevin/src/cmkc/src/kc/data/assoc0.js " ;
cmSpRC_t rc = kOkSpRC ;
cmSpAssocProc_t * m = cmMemAllocZ ( cmSpAssocProc_t , 1 ) ;
cmSp_t s ;
cmSp_t * sp = & s ;
2015-02-09 18:13:12 +00:00
memset ( sp , 0 , sizeof ( s ) ) ;
2013-05-24 20:52:37 +00:00
2015-02-19 00:39:14 +00:00
m - > ctx = ctx ;
cmRptPrintf ( & ctx - > rpt , " Score Association Start \n " ) ;
// create a JSON object to hold the results
if ( cmJsonInitialize ( & m - > jsH , ctx ) ! = kOkJsRC )
{
cmErrMsg ( & m - > ctx - > err , kJsonFailSpRC , " Score association JSON output object create failed. " ) ;
goto errLabel ;
}
// create the JSON root object
if ( cmJsonCreateObject ( m - > jsH , NULL ) = = NULL )
{
cmErrMsg ( & m - > ctx - > err , kJsonFailSpRC , " Create JSON root object. " ) ;
goto errLabel ;
}
2013-05-24 20:52:37 +00:00
2015-02-09 18:13:12 +00:00
// initialize the score processor
2015-02-19 00:39:14 +00:00
if ( ( rc = _cmScoreProcInit ( ctx , sp , rsrcFn , _cmSpProcAssocCb , _cmSpMatchAssocCb , m ) ) ! = kOkSpRC )
2013-05-24 20:52:37 +00:00
goto errLabel ;
2015-02-09 18:13:12 +00:00
m - > sp = sp ;
2015-02-19 00:39:14 +00:00
// store the time-line and score file name
if ( cmJsonInsertPairs ( m - > jsH , cmJsonRoot ( m - > jsH ) ,
" tlFn " , kStringTId , cmTimeLineFileName ( sp - > tlH ) ,
" scoreFn " , kStringTId , cmScoreFileName ( sp - > scH ) ,
NULL ) ! = kOkJsRC )
{
cmErrMsg ( & m - > ctx - > err , kJsonFailSpRC , " File name JSON field insertion failed. " ) ;
goto errLabel ;
}
2015-02-09 18:13:12 +00:00
// run the score processor
_cmScoreProcProcess ( ctx , sp ) ;
2015-02-19 00:39:14 +00:00
cmRptPrintf ( & ctx - > rpt , " Writing results to '%s'. " , outFn ) ;
2013-05-24 20:52:37 +00:00
2015-02-19 00:39:14 +00:00
// write the results to a JSON file
if ( cmJsonWrite ( m - > jsH , NULL , outFn ) ! = kOkJsRC )
{
cmErrMsg ( & m - > ctx - > err , kJsonFailSpRC , " Score association output file write failed. " ) ;
goto errLabel ;
}
2013-05-24 20:52:37 +00:00
errLabel :
2015-02-19 00:39:14 +00:00
if ( cmJsonFinalize ( & m - > jsH ) ! = kOkJsRC )
{
cmErrMsg ( & m - > ctx - > err , kJsonFailSpRC , " JSON finalize failed. " ) ;
}
2015-02-09 18:13:12 +00:00
_cmScoreProcFinal ( sp ) ;
cmMemFree ( m ) ;
2013-05-24 20:52:37 +00:00
cmRptPrintf ( & ctx - > rpt , " Score Proc End \n " ) ;
return rc ;
}
2015-02-09 18:13:12 +00:00
//==================================================================================================
cmSpRC_t cmScoreProc ( cmCtx_t * ctx )
{
cmSpRC_t rc = kOkSpRC ;
2015-02-19 00:39:14 +00:00
//_cmScoreProcGenAllMeasurementsMain(ctx);
_cmScoreProcGenAssocMain ( ctx ) ;
2015-02-09 18:13:12 +00:00
return rc ;
}