From 143c7daa91afa20e7db44ba75e6eb85dded985e1 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 12 Sep 2023 17:59:56 -0400 Subject: [PATCH] cwSfMatch.h/cpp : Updates to better integrate with cwSfScore. Added loc_to_index(). --- cwSfMatch.cpp | 110 ++++++++++++++++++++++++++++++-------------------- cwSfMatch.h | 35 ++++++++-------- 2 files changed, 85 insertions(+), 60 deletions(-) diff --git a/cwSfMatch.cpp b/cwSfMatch.cpp index f4c5288..89bf5b0 100644 --- a/cwSfMatch.cpp +++ b/cwSfMatch.cpp @@ -15,6 +15,7 @@ namespace cw { namespace sfmatch { + sfmatch_t* _handleToPtr( handle_t h ) { return handleToPtr(h); } @@ -47,7 +48,7 @@ namespace cw { unsigned i,n; - const sfscore::loc_t* lp = loc(p->scH,li); + const sfscore::loc_t* lp = loc_base(p->scH) + li; // count the number of note events at location li for(n=0,i=0; ievtCnt; ++i) @@ -408,7 +409,7 @@ namespace cw void _cmScMatchMidiEvtFlags( sfmatch_t* p, const loc_t* lp, unsigned evtIdx, char* s, unsigned sn ) { - const sfscore::loc_t* slp = sfscore::loc(p->scH,lp->scLocIdx); + const sfscore::loc_t* slp = sfscore::loc_base(p->scH) + lp->scLocIdx; assert( evtIdx < slp->evtCnt ); @@ -443,7 +444,7 @@ namespace cw { assert( begLocIdx < sfscore::loc_count(scoreH) ); - const sfscore::loc_t* loc = sfscore::loc(scoreH,i); + const sfscore::loc_t* loc = sfscore::loc_base(scoreH) + i; for(unsigned j=0; jevtCnt; ++j) { @@ -512,7 +513,7 @@ cw::rc_t cw::sfmatch::destroy( handle_t& hRef ) return rc; } -cw::rc_t cw::sfmatch::exec( handle_t h, unsigned locIdx, unsigned locN, const midi_t* midiV, unsigned midiN, double min_cost ) +cw::rc_t cw::sfmatch::exec( handle_t h, unsigned oLocId, unsigned locN, const midi_t* midiV, unsigned midiN, double min_cost ) { rc_t rc; unsigned rn = midiN + 1; @@ -524,7 +525,7 @@ cw::rc_t cw::sfmatch::exec( handle_t h, unsigned locIdx, unsigned locN, const m return rc; // _cmScMatchCalcMtx() returns false if the score window exceeds the length of the score - if(!_cmScMatchCalcMtx(p,locIdx, midiV, rn, cn) ) + if(!_cmScMatchCalcMtx(p,oLocId, midiV, rn, cn) ) return kEofRC; //_cmScMatchPrintMtx(p,rn,cn); @@ -535,7 +536,6 @@ cw::rc_t cw::sfmatch::exec( handle_t h, unsigned locIdx, unsigned locN, const m return rc; } - unsigned cw::sfmatch::sync( handle_t h, unsigned i_opt, midi_t* midiBuf, unsigned midiN, unsigned* missCntPtr ) { sfmatch_t* p = _handleToPtr(h); @@ -550,13 +550,13 @@ unsigned cw::sfmatch::sync( handle_t h, unsigned i_opt, midi_t* midiBuf, unsigne if( cp->code != kSmInsIdx ) { assert( cp->ri > 0 ); - midiBuf[ cp->ri-1 ].locIdx = kInvalidIdx; + midiBuf[ cp->ri-1 ].oLocId = kInvalidIdx; } switch( cp->code ) { case kSmSubIdx: - midiBuf[ cp->ri-1 ].locIdx = i_opt + i; + midiBuf[ cp->ri-1 ].oLocId = i_opt + i; midiBuf[ cp->ri-1 ].scEvtIdx = cp->scEvtIdx; if( cwIsFlag(cp->flags,kSmMatchFl) ) @@ -571,12 +571,12 @@ unsigned cw::sfmatch::sync( handle_t h, unsigned i_opt, midi_t* midiBuf, unsigne // fall through case kSmInsIdx: - cp->locIdx = i_opt + i; + cp->oLocId = i_opt + i; ++i; break; case kSmDelIdx: - cp->locIdx = kInvalidIdx; + cp->oLocId = kInvalidIdx; ++missCnt; break; } @@ -592,11 +592,11 @@ void cw::sfmatch::print_path( handle_t h, unsigned bsi, const midi_t* midiV ) { assert( bsi != kInvalidIdx ); - sfmatch_t* p = _handleToPtr(h); - path_t* cp = p->p_opt; - path_t* pp = cp; - int polyN = 0; - int i; + sfmatch_t* p = _handleToPtr(h); + path_t* cp = p->p_opt; + path_t* pp = cp; + int polyN = 0; + int i; printf("loc: "); @@ -627,9 +627,9 @@ void cw::sfmatch::print_path( handle_t h, unsigned bsi, const midi_t* midiV ) if( pp->code!=kSmDelIdx ) { - int locIdx = bsi + pp->ci - 1; - assert(0 <= locIdx && locIdx <= (int)p->locN); - loc_t* lp = p->loc + locIdx; + int oLocId = bsi + pp->ci - 1; + assert(0 <= oLocId && oLocId <= (int)p->locN); + loc_t* lp = p->loc + oLocId; if( lp->evtCnt >= (unsigned) i ) @@ -646,9 +646,9 @@ void cw::sfmatch::print_path( handle_t h, unsigned bsi, const midi_t* midiV ) printf("%4s%4s ", (pp->code==kSmDelIdx? "-" : " ")," "); /* - int locIdx = bsi + pp->ci - 1; - assert(0 <= locIdx && locIdx <= p->locN); - loc_t* lp = p->loc + locIdx; + int oLocId = bsi + pp->ci - 1; + assert(0 <= oLocId && oLocId <= p->locN); + loc_t* lp = p->loc + oLocId; if( pp->code!=kSmDelIdx && lp->evtCnt >= i ) printf("%4s ",cmMidiToSciPitch(lp->evtV[i-1].pitch,NULL,0)); else @@ -732,10 +732,10 @@ void cw::sfmatch::print_path( handle_t h, unsigned bsi, const midi_t* midiV ) // print the stored location index for(pp=cp; pp!=NULL; pp=pp->next) { - if( pp->locIdx == kInvalidIdx ) + if( pp->oLocId == kInvalidIdx ) printf("%4s%4s "," "," "); else - printf("%4i%4s ",p->loc[pp->locIdx].scLocIdx," "); + printf("%4i%4s ",p->loc[pp->oLocId].scLocIdx," "); } printf("\nbar: "); @@ -743,7 +743,7 @@ void cw::sfmatch::print_path( handle_t h, unsigned bsi, const midi_t* midiV ) // print the stored location index for(pp=cp; pp!=NULL; pp=pp->next) { - if( pp->locIdx==kInvalidIdx || pp->scEvtIdx==kInvalidIdx ) + if( pp->oLocId==kInvalidIdx || pp->scEvtIdx==kInvalidIdx ) printf("%4s%4s "," "," "); else { @@ -778,24 +778,39 @@ void cw::sfmatch::print_path( handle_t h, unsigned bsi, const midi_t* midiV ) } +unsigned cw::sfmatch::loc_to_index( handle_t h, unsigned loc ) +{ + sfmatch_t* p = _handleToPtr(h); + const loc_t* y = std::find_if(p->loc, p->loc+p->locN, [&loc](const loc_t& x){return x.scLocIdx==loc;} ); + unsigned idx = y - p->loc; + return idxlocN ? idx : kInvalidIdx; +} + + cw::rc_t cw::sfmatch::test( const object_t* cfg, sfscore::handle_t scoreH ) { - rc_t rc = kOkRC; - const object_t* perf = nullptr; - const object_t* gen_perf_example = nullptr; - bool gen_perf_enable_fl = false; - unsigned gen_perf_beg_loc_idx = 0; - unsigned gen_perf_loc_cnt = 0; - midi_t* midiA = nullptr; - unsigned maxScWndN = 10; - unsigned maxMidiWndN = 7; + rc_t rc = kOkRC; + const object_t* perf = nullptr; + const object_t* gen_perf_example = nullptr; + bool gen_perf_enable_fl = false; + unsigned gen_perf_beg_loc_idx = 0; + unsigned gen_perf_loc_cnt = 0; + midi_t* midiA = nullptr; + unsigned maxScWndN = 10; + unsigned maxMidiWndN = 7; + unsigned init_score_loc = 0; + unsigned beg_perf_idx = 0; + unsigned perf_cnt = 6; sfmatch::handle_t matchH; // parse the test cfg if((rc = cfg->getv( "maxScWndN", maxScWndN, "maxMidiWndN", maxMidiWndN, "gen_perf_example", gen_perf_example, + "init_score_loc",init_score_loc, + "beg_perf_idx", beg_perf_idx, + "perf_cnt", perf_cnt, "perf", perf)) != kOkRC ) { rc = cwLogError(rc,"sfscore test parse params failed."); @@ -816,8 +831,9 @@ cw::rc_t cw::sfmatch::test( const object_t* cfg, sfscore::handle_t scoreH ) } else { + + // Parse the cfg. perf[] array unsigned midiN = perf->child_count(); - midiA = mem::allocZ(midiN); for(unsigned i=0; im[,] typedef struct path_str { - unsigned code; // kSmXXXIdx - unsigned ri; // matrix row index - unsigned ci; // matrix col index - unsigned flags; // cmSmMatchFl | cmSmTransFl - unsigned locIdx; // p->loc index or cmInvalidIdx - unsigned scEvtIdx; // scScore event index + unsigned code; // kSmXXXIdx + unsigned ri; // matrix row index + unsigned ci; // matrix col index + unsigned flags; // cmSmMatchFl | cmSmTransFl + unsigned oLocId; // p->loc index or cmInvalidIdx + unsigned scEvtIdx; // scScore event index struct path_str* next; // } path_t; @@ -63,10 +63,11 @@ namespace cw { unsigned mni; // unique identifier for this MIDI note - used to recognize when the sfmatcher backtracks. unsigned muid; // MIDI file event msg unique id (See cmMidiTrackMsg_t.uid) - unsigned smpIdx; // time stamp of this event + double sec; // time stamp of this event in seconds + unsigned smpIdx; // time stamp of this event in samples unsigned pitch; // MIDI note pitch unsigned vel; // " " velocity - unsigned locIdx; // location assoc'd with this MIDI evt (kInvalidIdx if not a matching or non-matching 'substitute') + unsigned oLocId; // location assoc'd with this MIDI evt (kInvalidIdx if not a matching or non-matching 'substitute') unsigned scEvtIdx; // sfscore event index assoc'd with this event } midi_t; @@ -94,7 +95,7 @@ namespace cw path_t* p_opt; // p_opt[pn] - current best alignment as a linked list double opt_cost; // last p_opt cost set by exec() } sfmatch_t; - + typedef handle handle_t; // This matcher determines the optimal alignment of a short list of MIDI notes @@ -117,26 +118,25 @@ namespace cw rc_t create( handle_t& hRef, sfscore::handle_t scoreH, unsigned maxScWndN, unsigned maxMidiWndN ); rc_t destroy( handle_t& hRef ); - // Locate the position in p->loc[locIdx:locIdx+locN-1] which bests matches midiV[0:midiN]. + // Locate the position in p->loc[oLocId:oLocId+locN-1] which bests matches midiV[0:midiN]. // The result of this function is to update p_opt[] // The optimal path p_opt[] will only be updated if the edit_cost associated 'midiV[0:midiN]'. // with the best match is less than 'min_cost'. // Set 'min_cost' to DBL_MAX to force p_opt[] to be updated. - // Returns kEofRC if locIdx + locN > p->locN - note that this is not necessarily an error. - rc_t exec( handle_t h, unsigned locIdx, unsigned locN, const midi_t* midiV, unsigned midiN, double min_cost ); + // Returns kEofRC if oLocId + locN > p->locN - note that this is not necessarily an error. + rc_t exec( handle_t h, unsigned oLocId, unsigned locN, const midi_t* midiV, unsigned midiN, double min_cost ); - - // This function updates the midiBuf[] fields 'locIdx' and 'scEvtIdx' after an alignment + // This function updates the midiBuf[] fields 'oLocId' and 'scEvtIdx' after an alignment // has been found via an earlier call to 'exec()'. // // Traverse the least cost path and: // // 1) Returns, esi, the score location index of the last MIDI note // which has a positive match with the score and assign - // the internal score index to cp->locIdx. + // the internal score index to cp->oLocId. // - // 2) Set cmScAlignPath_t.locIdx - index into p->loc[] associated + // 2) Set cmScAlignPath_t.oLocId - index into p->loc[] associated // with each path element that is a 'substitute' or an 'insert'. // // 3) Set *missCnPtr: the count of trailing non-positive matches in midiBuf[]. @@ -151,6 +151,9 @@ namespace cw // midiV - pointer to the first element of the MIDI buffer used to form the path. void print_path( handle_t h, unsigned bsi, const midi_t* midiV ); + // Given a loc value return the index into p->loc[p->locN].of the associated loc. + unsigned loc_to_index( handle_t h, unsigned loc ); + // Returns the index into loc->evtV[] of pitch. inline unsigned match_index( const loc_t* loc, unsigned pitch ) {