cwSfMatch.h/cpp : Updates to better integrate with cwSfScore.
Added loc_to_index().
This commit is contained in:
parent
16ba4d6a3f
commit
143c7daa91
@ -15,6 +15,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
namespace sfmatch
|
namespace sfmatch
|
||||||
{
|
{
|
||||||
|
|
||||||
sfmatch_t* _handleToPtr( handle_t h )
|
sfmatch_t* _handleToPtr( handle_t h )
|
||||||
{ return handleToPtr<handle_t,sfmatch_t>(h); }
|
{ return handleToPtr<handle_t,sfmatch_t>(h); }
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
unsigned i,n;
|
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
|
// count the number of note events at location li
|
||||||
for(n=0,i=0; i<lp->evtCnt; ++i)
|
for(n=0,i=0; i<lp->evtCnt; ++i)
|
||||||
@ -408,7 +409,7 @@ namespace cw
|
|||||||
|
|
||||||
void _cmScMatchMidiEvtFlags( sfmatch_t* p, const loc_t* lp, unsigned evtIdx, char* s, unsigned sn )
|
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 );
|
assert( evtIdx < slp->evtCnt );
|
||||||
|
|
||||||
@ -443,7 +444,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
assert( begLocIdx < sfscore::loc_count(scoreH) );
|
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; j<loc->evtCnt; ++j)
|
for(unsigned j=0; j<loc->evtCnt; ++j)
|
||||||
{
|
{
|
||||||
@ -512,7 +513,7 @@ cw::rc_t cw::sfmatch::destroy( handle_t& hRef )
|
|||||||
return rc;
|
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;
|
rc_t rc;
|
||||||
unsigned rn = midiN + 1;
|
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;
|
return rc;
|
||||||
|
|
||||||
// _cmScMatchCalcMtx() returns false if the score window exceeds the length of the score
|
// _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;
|
return kEofRC;
|
||||||
|
|
||||||
//_cmScMatchPrintMtx(p,rn,cn);
|
//_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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned cw::sfmatch::sync( handle_t h, unsigned i_opt, midi_t* midiBuf, unsigned midiN, unsigned* missCntPtr )
|
unsigned cw::sfmatch::sync( handle_t h, unsigned i_opt, midi_t* midiBuf, unsigned midiN, unsigned* missCntPtr )
|
||||||
{
|
{
|
||||||
sfmatch_t* p = _handleToPtr(h);
|
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 )
|
if( cp->code != kSmInsIdx )
|
||||||
{
|
{
|
||||||
assert( cp->ri > 0 );
|
assert( cp->ri > 0 );
|
||||||
midiBuf[ cp->ri-1 ].locIdx = kInvalidIdx;
|
midiBuf[ cp->ri-1 ].oLocId = kInvalidIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( cp->code )
|
switch( cp->code )
|
||||||
{
|
{
|
||||||
case kSmSubIdx:
|
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;
|
midiBuf[ cp->ri-1 ].scEvtIdx = cp->scEvtIdx;
|
||||||
|
|
||||||
if( cwIsFlag(cp->flags,kSmMatchFl) )
|
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
|
// fall through
|
||||||
|
|
||||||
case kSmInsIdx:
|
case kSmInsIdx:
|
||||||
cp->locIdx = i_opt + i;
|
cp->oLocId = i_opt + i;
|
||||||
++i;
|
++i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kSmDelIdx:
|
case kSmDelIdx:
|
||||||
cp->locIdx = kInvalidIdx;
|
cp->oLocId = kInvalidIdx;
|
||||||
++missCnt;
|
++missCnt;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -627,9 +627,9 @@ void cw::sfmatch::print_path( handle_t h, unsigned bsi, const midi_t* midiV )
|
|||||||
|
|
||||||
if( pp->code!=kSmDelIdx )
|
if( pp->code!=kSmDelIdx )
|
||||||
{
|
{
|
||||||
int locIdx = bsi + pp->ci - 1;
|
int oLocId = bsi + pp->ci - 1;
|
||||||
assert(0 <= locIdx && locIdx <= (int)p->locN);
|
assert(0 <= oLocId && oLocId <= (int)p->locN);
|
||||||
loc_t* lp = p->loc + locIdx;
|
loc_t* lp = p->loc + oLocId;
|
||||||
|
|
||||||
if( lp->evtCnt >= (unsigned)
|
if( lp->evtCnt >= (unsigned)
|
||||||
i )
|
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? "-" : " ")," ");
|
printf("%4s%4s ", (pp->code==kSmDelIdx? "-" : " ")," ");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
int locIdx = bsi + pp->ci - 1;
|
int oLocId = bsi + pp->ci - 1;
|
||||||
assert(0 <= locIdx && locIdx <= p->locN);
|
assert(0 <= oLocId && oLocId <= p->locN);
|
||||||
loc_t* lp = p->loc + locIdx;
|
loc_t* lp = p->loc + oLocId;
|
||||||
if( pp->code!=kSmDelIdx && lp->evtCnt >= i )
|
if( pp->code!=kSmDelIdx && lp->evtCnt >= i )
|
||||||
printf("%4s ",cmMidiToSciPitch(lp->evtV[i-1].pitch,NULL,0));
|
printf("%4s ",cmMidiToSciPitch(lp->evtV[i-1].pitch,NULL,0));
|
||||||
else
|
else
|
||||||
@ -732,10 +732,10 @@ void cw::sfmatch::print_path( handle_t h, unsigned bsi, const midi_t* midiV )
|
|||||||
// print the stored location index
|
// print the stored location index
|
||||||
for(pp=cp; pp!=NULL; pp=pp->next)
|
for(pp=cp; pp!=NULL; pp=pp->next)
|
||||||
{
|
{
|
||||||
if( pp->locIdx == kInvalidIdx )
|
if( pp->oLocId == kInvalidIdx )
|
||||||
printf("%4s%4s "," "," ");
|
printf("%4s%4s "," "," ");
|
||||||
else
|
else
|
||||||
printf("%4i%4s ",p->loc[pp->locIdx].scLocIdx," ");
|
printf("%4i%4s ",p->loc[pp->oLocId].scLocIdx," ");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\nbar: ");
|
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
|
// print the stored location index
|
||||||
for(pp=cp; pp!=NULL; pp=pp->next)
|
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 "," "," ");
|
printf("%4s%4s "," "," ");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -778,6 +778,15 @@ 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 idx<p->locN ? idx : kInvalidIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::sfmatch::test( const object_t* cfg, sfscore::handle_t scoreH )
|
cw::rc_t cw::sfmatch::test( const object_t* cfg, sfscore::handle_t scoreH )
|
||||||
{
|
{
|
||||||
@ -790,12 +799,18 @@ cw::rc_t cw::sfmatch::test( const object_t* cfg, sfscore::handle_t scoreH )
|
|||||||
midi_t* midiA = nullptr;
|
midi_t* midiA = nullptr;
|
||||||
unsigned maxScWndN = 10;
|
unsigned maxScWndN = 10;
|
||||||
unsigned maxMidiWndN = 7;
|
unsigned maxMidiWndN = 7;
|
||||||
|
unsigned init_score_loc = 0;
|
||||||
|
unsigned beg_perf_idx = 0;
|
||||||
|
unsigned perf_cnt = 6;
|
||||||
sfmatch::handle_t matchH;
|
sfmatch::handle_t matchH;
|
||||||
|
|
||||||
// parse the test cfg
|
// parse the test cfg
|
||||||
if((rc = cfg->getv( "maxScWndN", maxScWndN,
|
if((rc = cfg->getv( "maxScWndN", maxScWndN,
|
||||||
"maxMidiWndN", maxMidiWndN,
|
"maxMidiWndN", maxMidiWndN,
|
||||||
"gen_perf_example", gen_perf_example,
|
"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 )
|
"perf", perf)) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"sfscore test parse params failed.");
|
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
|
else
|
||||||
{
|
{
|
||||||
unsigned midiN = perf->child_count();
|
|
||||||
|
|
||||||
|
// Parse the cfg. perf[] array
|
||||||
|
unsigned midiN = perf->child_count();
|
||||||
midiA = mem::allocZ<midi_t>(midiN);
|
midiA = mem::allocZ<midi_t>(midiN);
|
||||||
|
|
||||||
for(unsigned i=0; i<midiN; ++i)
|
for(unsigned i=0; i<midiN; ++i)
|
||||||
@ -834,33 +850,39 @@ cw::rc_t cw::sfmatch::test( const object_t* cfg, sfscore::handle_t scoreH )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the cwMatch
|
||||||
if((rc = create(matchH, scoreH, maxScWndN, maxMidiWndN )) != kOkRC )
|
if((rc = create(matchH, scoreH, maxScWndN, maxMidiWndN )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"Score matcher create failed.");
|
rc = cwLogError(rc,"Score matcher create failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned locIdx = 0;
|
// Set the matcher to the first location to begin matching against
|
||||||
|
unsigned oLocId = loc_to_index(matchH,init_score_loc);
|
||||||
unsigned locN = maxScWndN;
|
unsigned locN = maxScWndN;
|
||||||
unsigned perf_idx = 3;
|
|
||||||
unsigned perf_cnt = 4;
|
|
||||||
|
|
||||||
if((rc = exec(matchH, locIdx, locN, midiA + perf_idx, perf_cnt, DBL_MAX )) != kOkRC )
|
// Count of MIDI events to track.
|
||||||
|
perf_cnt = std::min(maxMidiWndN,perf_cnt);
|
||||||
|
|
||||||
|
// Align MIDI notes to the score
|
||||||
|
if((rc = exec(matchH, oLocId, locN, midiA + beg_perf_idx, perf_cnt, DBL_MAX )) != kOkRC )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"score match failed.");
|
rc = cwLogError(rc,"score match failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the cwMatch to reflect the alignment found during the exec.
|
||||||
unsigned eli = kInvalidIdx;
|
unsigned eli = kInvalidIdx;
|
||||||
unsigned missCnt = 0;
|
unsigned missCnt = 0;
|
||||||
unsigned i_opt = locIdx;
|
unsigned i_opt = oLocId;
|
||||||
if(( eli = cw::sfmatch::sync( matchH, i_opt, midiA + perf_idx, perf_cnt, &missCnt )) == kInvalidIdx )
|
if(( eli = cw::sfmatch::sync( matchH, i_opt, midiA + beg_perf_idx, perf_cnt, &missCnt )) == kInvalidIdx )
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"score match sync failed.");
|
rc = cwLogError(rc,"score match sync failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned bsi = locIdx;
|
// Print the state alignment.
|
||||||
|
unsigned bsi = oLocId;
|
||||||
print_path( matchH, bsi, midiA );
|
print_path( matchH, bsi, midiA );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
23
cwSfMatch.h
23
cwSfMatch.h
@ -39,7 +39,7 @@ namespace cw
|
|||||||
unsigned ri; // matrix row index
|
unsigned ri; // matrix row index
|
||||||
unsigned ci; // matrix col index
|
unsigned ci; // matrix col index
|
||||||
unsigned flags; // cmSmMatchFl | cmSmTransFl
|
unsigned flags; // cmSmMatchFl | cmSmTransFl
|
||||||
unsigned locIdx; // p->loc index or cmInvalidIdx
|
unsigned oLocId; // p->loc index or cmInvalidIdx
|
||||||
unsigned scEvtIdx; // scScore event index
|
unsigned scEvtIdx; // scScore event index
|
||||||
struct path_str* next; //
|
struct path_str* next; //
|
||||||
} path_t;
|
} path_t;
|
||||||
@ -63,10 +63,11 @@ namespace cw
|
|||||||
{
|
{
|
||||||
unsigned mni; // unique identifier for this MIDI note - used to recognize when the sfmatcher backtracks.
|
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 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 pitch; // MIDI note pitch
|
||||||
unsigned vel; // " " velocity
|
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
|
unsigned scEvtIdx; // sfscore event index assoc'd with this event
|
||||||
} midi_t;
|
} midi_t;
|
||||||
|
|
||||||
@ -117,26 +118,25 @@ namespace cw
|
|||||||
rc_t create( handle_t& hRef, sfscore::handle_t scoreH, unsigned maxScWndN, unsigned maxMidiWndN );
|
rc_t create( handle_t& hRef, sfscore::handle_t scoreH, unsigned maxScWndN, unsigned maxMidiWndN );
|
||||||
rc_t destroy( handle_t& hRef );
|
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 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]'.
|
// 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'.
|
// with the best match is less than 'min_cost'.
|
||||||
// Set 'min_cost' to DBL_MAX to force p_opt[] to be updated.
|
// 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.
|
// Returns kEofRC if oLocId + 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 );
|
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 'oLocId' and 'scEvtIdx' after an alignment
|
||||||
// This function updates the midiBuf[] fields 'locIdx' and 'scEvtIdx' after an alignment
|
|
||||||
// has been found via an earlier call to 'exec()'.
|
// has been found via an earlier call to 'exec()'.
|
||||||
//
|
//
|
||||||
// Traverse the least cost path and:
|
// Traverse the least cost path and:
|
||||||
//
|
//
|
||||||
// 1) Returns, esi, the score location index of the last MIDI note
|
// 1) Returns, esi, the score location index of the last MIDI note
|
||||||
// which has a positive match with the score and assign
|
// 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'.
|
// with each path element that is a 'substitute' or an 'insert'.
|
||||||
//
|
//
|
||||||
// 3) Set *missCnPtr: the count of trailing non-positive matches in midiBuf[].
|
// 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.
|
// 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 );
|
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.
|
// Returns the index into loc->evtV[] of pitch.
|
||||||
inline unsigned match_index( const loc_t* loc, unsigned pitch )
|
inline unsigned match_index( const loc_t* loc, unsigned pitch )
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user