cwSfAnalysis.h/cpp, Makefile.am : Initial commit.
This commit is contained in:
parent
3f9f72600c
commit
8fd00ac353
@ -70,8 +70,8 @@ libcwSRC += src/libcw/cwIoPresetSelApp.cpp src/libcw/cwPianoScore.cpp src/lib
|
|||||||
libcwHDR += src/libcw/cwDynRefTbl.h src/libcw/cwScoreParse.h src/libcw/cwSfScore.h
|
libcwHDR += src/libcw/cwDynRefTbl.h src/libcw/cwScoreParse.h src/libcw/cwSfScore.h
|
||||||
libcwSRC += src/libcw/cwDynRefTbl.cpp src/libcw/cwScoreParse.cpp src/libcw/cwSfScore.cpp
|
libcwSRC += src/libcw/cwDynRefTbl.cpp src/libcw/cwScoreParse.cpp src/libcw/cwSfScore.cpp
|
||||||
|
|
||||||
libcwHDR += src/libcw/cwSfMatch.h src/libcw/cwSfTrack.h src/libcw/cwScoreTest.h
|
libcwHDR += src/libcw/cwSfMatch.h src/libcw/cwSfTrack.h src/libcw/cwSfAnalysis.h src/libcw/cwScoreTest.h
|
||||||
libcwSRC += src/libcw/cwSfMatch.cpp src/libcw/cwSfTrack.cpp src/libcw/cwScoreTest.cpp
|
libcwSRC += src/libcw/cwSfMatch.cpp src/libcw/cwSfTrack.cpp src/libcw/cwSfAnalysis.cpp src/libcw/cwScoreTest.cpp
|
||||||
|
|
||||||
libcwHDR += src/libcw/cwScoreFollowerPerf.h src/libcw/cwScoreFollower.h src/libcw/cwPerfMeas.h src/libcw/cwScoreFollowTest.h
|
libcwHDR += src/libcw/cwScoreFollowerPerf.h src/libcw/cwScoreFollower.h src/libcw/cwPerfMeas.h src/libcw/cwScoreFollowTest.h
|
||||||
libcwSRC += src/libcw/cwScoreFollower.cpp src/libcw/cwPerfMeas.cpp src/libcw/cwScoreFollowTest.cpp
|
libcwSRC += src/libcw/cwScoreFollower.cpp src/libcw/cwPerfMeas.cpp src/libcw/cwScoreFollowTest.cpp
|
||||||
|
171
cwSfAnalysis.cpp
Normal file
171
cwSfAnalysis.cpp
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
#include "cwCommon.h"
|
||||||
|
#include "cwLog.h"
|
||||||
|
#include "cwCommonImpl.h"
|
||||||
|
#include "cwMem.h"
|
||||||
|
#include "cwFile.h"
|
||||||
|
#include "cwObject.h"
|
||||||
|
#include "cwMidi.h"
|
||||||
|
|
||||||
|
#include "cwDynRefTbl.h"
|
||||||
|
#include "cwScoreParse.h"
|
||||||
|
#include "cwSfScore.h"
|
||||||
|
#include "cwSfMatch.h"
|
||||||
|
#include "cwSfTrack.h"
|
||||||
|
#include "cwSfAnalysis.h"
|
||||||
|
|
||||||
|
namespace cw
|
||||||
|
{
|
||||||
|
namespace sf_analysis
|
||||||
|
{
|
||||||
|
enum { kSciPitchCharCnt = 7 };
|
||||||
|
|
||||||
|
typedef struct anl_evt_str
|
||||||
|
{
|
||||||
|
unsigned matchCnt; // should be equal to 1, 0 if missed, > 1 if matched multiple time
|
||||||
|
unsigned timeDirErrCnt; // should be 0, incremented every time this event was matched going backwards in time
|
||||||
|
unsigned spuriousCnt; // should be 0, incremented for every nearby spurious note
|
||||||
|
|
||||||
|
unsigned oLocId; // score event location id
|
||||||
|
unsigned barNumb; // bar number of this event
|
||||||
|
uint8_t pitch; // pitch of this event
|
||||||
|
const char* sect_label; //
|
||||||
|
char sciPitch[ kSciPitchCharCnt ]; //
|
||||||
|
} anl_event_t;
|
||||||
|
|
||||||
|
unsigned _locate_anl_evt( unsigned oLocId, uint8_t pitch, const anl_event_t* anlEvtA, unsigned anlEvtN, unsigned anlEvtIdx )
|
||||||
|
{
|
||||||
|
for(unsigned i=0; i<anlEvtN; ++i)
|
||||||
|
if( anlEvtA[i].oLocId == oLocId && anlEvtA[i].pitch == pitch )
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return kInvalidIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _write_as_csv( const anl_event_t* anlEvtA, unsigned anlEvtCnt, const char* fname )
|
||||||
|
{
|
||||||
|
file::handle_t fH;
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
if((rc = open(fH,fname,file::kWriteFl)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"File create failed on '%s'.",cwStringNullGuard(fname));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = printf(fH,"section,bar,oLocId,sciPitch,matchN,timeDirErrN,spuriousN\n")) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"File write failed on title line.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const anl_event_t* e=anlEvtA; e<anlEvtA+anlEvtCnt; ++e)
|
||||||
|
{
|
||||||
|
if((rc = printf(fH,"%s,%i,%i,%s,%i,%i,%i\n",e->sect_label,e->barNumb,e->oLocId,e->sciPitch,e->matchCnt,e->timeDirErrCnt,e->spuriousCnt)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"File write failed on line %i.",(e-anlEvtA)+1);
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errLabel:
|
||||||
|
close(fH);
|
||||||
|
|
||||||
|
if( rc != kOkRC )
|
||||||
|
rc = cwLogError(rc,"The score follow analysis CSV report file creation failed on '%s'.",cwStringNullGuard(fname));
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::sf_analysis::gen_analysis( sfscore::handle_t scH,
|
||||||
|
const sftrack::result_t* resultA,
|
||||||
|
unsigned resultN,
|
||||||
|
unsigned begLoc,
|
||||||
|
unsigned endLoc,
|
||||||
|
const char* fname )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
unsigned anlEvtAllocN = event_count(scH);
|
||||||
|
anl_event_t* anlEvtA = mem::allocZ<anl_event_t>(anlEvtAllocN);
|
||||||
|
unsigned anlEvtCnt = 0;
|
||||||
|
unsigned anlEvtIdx = 0;
|
||||||
|
const char* sect_label0 = "<unknown>";
|
||||||
|
|
||||||
|
// fill anlEvtA[] with the score events
|
||||||
|
for(unsigned i=0; i<anlEvtAllocN; ++i)
|
||||||
|
{
|
||||||
|
const sfscore::event_t* scEvt = event(scH,i);
|
||||||
|
if( begLoc <= scEvt->oLocId && scEvt->oLocId <= endLoc )
|
||||||
|
{
|
||||||
|
anl_event_t* anlEvt = anlEvtA + anlEvtCnt++;
|
||||||
|
|
||||||
|
const sfscore::section_t* sect;
|
||||||
|
const char* sect_label = nullptr;
|
||||||
|
if((sect = event_index_to_section( scH, i )) == nullptr )
|
||||||
|
sect_label = sect_label0;
|
||||||
|
else
|
||||||
|
sect_label = sect->label;
|
||||||
|
|
||||||
|
anlEvt->oLocId = scEvt->oLocId;
|
||||||
|
anlEvt->pitch = scEvt->pitch;
|
||||||
|
anlEvt->barNumb = scEvt->barNumb;
|
||||||
|
anlEvt->sect_label = sect_label;
|
||||||
|
strncpy(anlEvt->sciPitch,scEvt->sciPitch,kSciPitchCharCnt-1);
|
||||||
|
|
||||||
|
sect_label0 = sect_label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( anlEvtCnt == 0)
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidStateRC,"The score appears to be empty.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(unsigned i=0; i<resultN; ++i)
|
||||||
|
{
|
||||||
|
const sftrack::result_t* r = resultA + i;
|
||||||
|
unsigned aei;
|
||||||
|
|
||||||
|
// if this is a spurious event
|
||||||
|
if( r->oLocId == kInvalidIdx )
|
||||||
|
{
|
||||||
|
// ignore spurious events until at least one matched event is found
|
||||||
|
if( anlEvtIdx > 0 )
|
||||||
|
anlEvtA[ anlEvtIdx ].spuriousCnt += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if this event is in range
|
||||||
|
if( begLoc <= r->oLocId && r->oLocId <= endLoc )
|
||||||
|
{
|
||||||
|
// locate the associated score event
|
||||||
|
if((aei = _locate_anl_evt( r->oLocId, r->pitch, anlEvtA, anlEvtCnt, anlEvtIdx )) == kInvalidIdx )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidStateRC,"The score event associated with a matched performance could not be found for event:%i loc:%i.",i,r->oLocId);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
anlEvtA[ aei ].matchCnt += 1;
|
||||||
|
|
||||||
|
anlEvtA[ aei ].timeDirErrCnt += aei < anlEvtIdx;
|
||||||
|
|
||||||
|
anlEvtIdx = aei;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = _write_as_csv( anlEvtA, anlEvtCnt, fname );
|
||||||
|
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if( rc != kOkRC )
|
||||||
|
rc = cwLogError(rc,"Score follow analysis failed.");
|
||||||
|
return rc;
|
||||||
|
}
|
16
cwSfAnalysis.h
Normal file
16
cwSfAnalysis.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
namespace cw
|
||||||
|
{
|
||||||
|
namespace sf_analysis
|
||||||
|
{
|
||||||
|
|
||||||
|
rc_t gen_analysis( sfscore::handle_t scH,
|
||||||
|
const sftrack::result_t* resultA,
|
||||||
|
unsigned resultN,
|
||||||
|
unsigned begLoc,
|
||||||
|
unsigned endLoc,
|
||||||
|
const char* fname );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user