From 8fd00ac353c54367acd3cf6c7c79540614566bbc Mon Sep 17 00:00:00 2001 From: kevin Date: Sun, 26 Nov 2023 15:27:59 -0500 Subject: [PATCH] cwSfAnalysis.h/cpp, Makefile.am : Initial commit. --- Makefile.am | 4 +- cwSfAnalysis.cpp | 171 +++++++++++++++++++++++++++++++++++++++++++++++ cwSfAnalysis.h | 16 +++++ 3 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 cwSfAnalysis.cpp create mode 100644 cwSfAnalysis.h diff --git a/Makefile.am b/Makefile.am index 43235f1..02ebadd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 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 -libcwSRC += src/libcw/cwSfMatch.cpp src/libcw/cwSfTrack.cpp src/libcw/cwScoreTest.cpp +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/cwSfAnalysis.cpp src/libcw/cwScoreTest.cpp 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 diff --git a/cwSfAnalysis.cpp b/cwSfAnalysis.cpp new file mode 100644 index 0000000..26044e8 --- /dev/null +++ b/cwSfAnalysis.cpp @@ -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; isect_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(anlEvtAllocN); + unsigned anlEvtCnt = 0; + unsigned anlEvtIdx = 0; + const char* sect_label0 = ""; + + // fill anlEvtA[] with the score events + for(unsigned i=0; ioLocId && 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; ioLocId == 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; +} diff --git a/cwSfAnalysis.h b/cwSfAnalysis.h new file mode 100644 index 0000000..08e42df --- /dev/null +++ b/cwSfAnalysis.h @@ -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 ); + + + + } +}