diff --git a/cwScoreFollower.cpp b/cwScoreFollower.cpp index 436ba91..5424995 100644 --- a/cwScoreFollower.cpp +++ b/cwScoreFollower.cpp @@ -9,6 +9,7 @@ #include "cwMidi.h" #include "cwMidiFile.h" #include "cwCmInterface.h" +#include "cwScoreFollowerPerf.h" #include "cwScoreFollower.h" #include "cwMidiState.h" @@ -405,10 +406,8 @@ cw::rc_t cw::score_follower::exec( handle_t h, double sec, unsigned smpIdx, uns } return rc; - } - const unsigned* cw::score_follower::current_match_id_array( handle_t h, unsigned& cur_match_id_array_cnt_ref ) { score_follower_t* p = _handleToPtr(h); @@ -458,9 +457,59 @@ bool cw::score_follower::is_loc_in_range( handle_t h, unsigned loc ) unsigned cw::score_follower::has_stored_performance( handle_t h ) { score_follower_t* p = _handleToPtr(h); - return p->perf_idx > 0; + return p->perf_idx > 0 && p->matcher->ri > 0; } +cw::rc_t cw::score_follower::sync_perf_to_score( handle_t h ) +{ + rc_t rc = kOkRC; + score_follower_t* p = _handleToPtr(h); + + if( !has_stored_performance(h) ) + { + rc = cwLogError(kInvalidStateRC,"No performance to sync."); + goto errLabel; + } + + for(unsigned i=0; imatcher->ri; ++i) + { + unsigned perf_idx = p->matcher->res[i].muid; + + // the matcher result 'muid' is the perf. array index of the matching perf. record + if( perf_idx >= p->perf_idx ) + { + rc = cwLogError(kInvalidStateRC,"Inconsistent match to perf. map: index mismatch."); + goto errLabel; + } + + // verify the pitch of the matching records + if( p->perfA[ perf_idx ].pitch != p->matcher->res[i].pitch ) + { + rc = cwLogError(kInvalidStateRC,"Inconsistent match to perf. map: pitch mismatch %i != %i.",p->perfA[ perf_idx ].pitch ,p->matcher->res[i].pitch); + goto errLabel; + } + + assert( p->matcher->res[i].scEvtIdx == kInvalidIdx || p->matcher->res[i].scEvtIdx < p->cmLocToCwLocN ); + + if( p->matcher->res[i].scEvtIdx != kInvalidIdx ) + p->perfA[ perf_idx ].loc = p->cmLocToCwLocA[ p->matcher->res[i].scEvtIdx ]; + } + + errLabel: + return rc; +} + +unsigned cw::score_follower::perf_count( handle_t h ) +{ + score_follower_t* p = _handleToPtr(h); + return p->perfN; +} + +const cw::score_follower::ssf_note_on_t* cw::score_follower::perf_base( handle_t h ) +{ + score_follower_t* p = _handleToPtr(h); + return p->perfA; +} cw::rc_t cw::score_follower::write_svg_file( handle_t h, const char* out_fname, bool show_muid_fl ) { diff --git a/cwScoreFollower.h b/cwScoreFollower.h index 7555367..1a7e8b6 100644 --- a/cwScoreFollower.h +++ b/cwScoreFollower.h @@ -5,7 +5,6 @@ namespace cw { namespace score_follower { - typedef handle< struct score_follower_str > handle_t; rc_t create( handle_t& hRef, const object_t* cfg, cm::handle_t cmCtxH, double srate ); @@ -24,12 +23,21 @@ namespace cw // Clear the match id array. This should be done to empty the current_match_id_array() void clear_match_id_array( handle_t h ); - + // Get the min and max cw loc values for the current score. rc_t cw_loc_range( handle_t h, unsigned& minLocRef, unsigned& maxLocRef ); bool is_loc_in_range( handle_t h, unsigned loc ); - + unsigned has_stored_performance( handle_t h ); + // Set the 'loc' field on the stored performance from the stored score following info. + rc_t sync_perf_to_score( handle_t h ); + + // Return the count of stored performance records in the performance array. + unsigned perf_count( handle_t h ); + + // Return the base of the stored performance array. + const score_follower::ssf_note_on_t* perf_base( handle_t h ); + // Write an SVG file containing a graphic view of the score following results since the last call to reset(). // Set show_muid_fl to true to display the 'muid' of the performed notes in the // SVG rendering, otherwise the performed note sequence (order of arrival) id is shown.