cwCmInterface.h/cpp, cwScoreFollower.h/cpp, Makefile.am : Initial score_follow development
This commit is contained in:
parent
59647d4e58
commit
7312e91421
@ -67,8 +67,8 @@ libcwSRC += src/libcw/cwIoMidiRecordPlay.cpp src/libcw/cwIoAudioRecordPlay.cpp
|
|||||||
libcwHDR += src/libcw/cwIoPresetSelApp.h src/libcw/cwPianoScore.h src/libcw/cwPresetSel.h
|
libcwHDR += src/libcw/cwIoPresetSelApp.h src/libcw/cwPianoScore.h src/libcw/cwPresetSel.h
|
||||||
libcwSRC += src/libcw/cwIoPresetSelApp.cpp src/libcw/cwPianoScore.cpp src/libcw/cwPresetSel.cpp
|
libcwSRC += src/libcw/cwIoPresetSelApp.cpp src/libcw/cwPianoScore.cpp src/libcw/cwPresetSel.cpp
|
||||||
|
|
||||||
# libcwHDR += src/libcw/cwCmInterface.h src/libcw/cwScoreFollower.h
|
libcwHDR += src/libcw/cwCmInterface.h src/libcw/cwScoreFollower.h
|
||||||
# libcwSRC += src/libcw/cwCmInterface.cpp src/libcw/cwScoreFollower.cpp
|
libcwSRC += src/libcw/cwCmInterface.cpp src/libcw/cwScoreFollower.cpp
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
#include "cwCommon.h"
|
#include "cwCommon.h"
|
||||||
#include "cwLog.h"
|
#include "cwLog.h"
|
||||||
#include "cwCommonImpl.h"
|
#include "cwCommonImpl.h"
|
||||||
@ -18,8 +19,11 @@
|
|||||||
#include "cmScore.h"
|
#include "cmScore.h"
|
||||||
#include "cmText.h"
|
#include "cmText.h"
|
||||||
#include "cmFileSys.h"
|
#include "cmFileSys.h"
|
||||||
|
#include "cmProcObj.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
|
||||||
void _cm_print_info( void* arg, const char* text )
|
void _cm_print_info( void* arg, const char* text )
|
||||||
{
|
{
|
||||||
cwLogInfo(text);
|
cwLogInfo(text);
|
||||||
@ -35,11 +39,18 @@ namespace cw
|
|||||||
{
|
{
|
||||||
namespace cm
|
namespace cm
|
||||||
{
|
{
|
||||||
typedef struct cm_str
|
|
||||||
{
|
extern "C" {
|
||||||
::cmCtx_t ctx;
|
typedef struct cm_str
|
||||||
} cm_t;
|
{
|
||||||
|
cmCtx_t ctx;
|
||||||
|
cmSymTblH_t symTblH;
|
||||||
|
cmLHeapH_t lhH;
|
||||||
|
cmProcCtx* procCtx;
|
||||||
|
|
||||||
|
} cm_t;
|
||||||
|
}
|
||||||
|
|
||||||
cm_t* _handleToPtr( handle_t h )
|
cm_t* _handleToPtr( handle_t h )
|
||||||
{ return handleToPtr<handle_t,cm_t>(h); }
|
{ return handleToPtr<handle_t,cm_t>(h); }
|
||||||
|
|
||||||
@ -52,10 +63,43 @@ namespace cw
|
|||||||
cmMdReport( kIgnoreNormalMmFl );
|
cmMdReport( kIgnoreNormalMmFl );
|
||||||
cmMdFinalize();
|
cmMdFinalize();
|
||||||
|
|
||||||
|
cmLHeapDestroy(&p->lhH);
|
||||||
|
cmSymTblDestroy(&p->symTblH);
|
||||||
|
cmProcCtxFree(&p->procCtx);
|
||||||
|
|
||||||
mem::release(p);
|
mem::release(p);
|
||||||
}
|
}
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc_t _create_proc_ctx( cm_t* p, cmCtx_t* ctx )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
// create the linked heap
|
||||||
|
if(cmLHeapIsValid( p->lhH = cmLHeapCreate(1024,ctx)) == false)
|
||||||
|
{
|
||||||
|
rc = cwLogError(kOpFailRC,"The cm linked heap allocation failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// intialize the symbol table
|
||||||
|
if( cmSymTblIsValid( p->symTblH = cmSymTblCreate(cmSymTblNullHandle,1,ctx)) == false )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kOpFailRC,"The cm linked heap allocation failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the proc context
|
||||||
|
if( (p->procCtx = cmProcCtxAlloc(NULL,&ctx->rpt,p->lhH,p->symTblH)) == NULL )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kOpFailRC,"The cm proc context allocation failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +126,14 @@ cw::rc_t cw::cm::create( handle_t& hRef )
|
|||||||
|
|
||||||
cmTsInitialize( &p->ctx );
|
cmTsInitialize( &p->ctx );
|
||||||
|
|
||||||
|
if((rc = _create_proc_ctx(p, &p->ctx )) == kOkRC )
|
||||||
|
hRef.set(p);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_destroy(p);
|
||||||
|
rc = cwLogError(rc,"cm Interface context create failed.");
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,9 +154,17 @@ cw::rc_t cw::cm::destroy( handle_t& hRef )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::cmCtx_t* cw::cm::context( handle_t h )
|
extern "C" {
|
||||||
{
|
struct cmCtx_str* cw::cm::context( handle_t h )
|
||||||
cm_t* p = _handleToPtr(h);
|
{
|
||||||
return &p->ctx;
|
cm_t* p = _handleToPtr(h);
|
||||||
|
return &p->ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmProcCtx_str* cw::cm::proc_context( handle_t h )
|
||||||
|
{
|
||||||
|
cm_t* p = _handleToPtr(h);
|
||||||
|
return p->procCtx;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,24 @@
|
|||||||
#ifndef cwCmInterface_h
|
#ifndef cwCmInterface_h
|
||||||
#define cwCmInterface_h
|
#define cwCmInterface_h
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
struct cmCtx_str;
|
||||||
|
struct cmProcCtx_str;
|
||||||
|
}
|
||||||
|
|
||||||
namespace cw
|
namespace cw
|
||||||
{
|
{
|
||||||
namespace cm {
|
namespace cm {
|
||||||
|
|
||||||
extern "C" { struct cmCtx_str; }
|
|
||||||
|
|
||||||
typedef handle< struct cm_str > handle_t;
|
typedef handle< struct cm_str > handle_t;
|
||||||
|
|
||||||
rc_t create( handle_t& hRef );
|
rc_t create( handle_t& hRef );
|
||||||
rc_t destroy( handle_t& hRef );
|
rc_t destroy( handle_t& hRef );
|
||||||
::cmCtx_t* context( handle_t h );
|
|
||||||
|
|
||||||
|
extern "C" struct cmCtx_str* context( handle_t h );
|
||||||
|
extern "C" struct cmProcCtx_str* proc_context( handle_t h );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
#include "cwText.h"
|
#include "cwText.h"
|
||||||
#include "cwObject.h"
|
#include "cwObject.h"
|
||||||
#include "cwMidi.h"
|
#include "cwMidi.h"
|
||||||
|
#include "cwFileSys.h"
|
||||||
|
#include "cwMidi.h"
|
||||||
|
#include "cwMidiFile.h"
|
||||||
|
#include "cwCmInterface.h"
|
||||||
#include "cwScoreFollower.h"
|
#include "cwScoreFollower.h"
|
||||||
|
|
||||||
#include "cmGlobal.h"
|
#include "cmGlobal.h"
|
||||||
@ -12,10 +16,18 @@
|
|||||||
#include "cmRpt.h"
|
#include "cmRpt.h"
|
||||||
#include "cmErr.h"
|
#include "cmErr.h"
|
||||||
#include "cmCtx.h"
|
#include "cmCtx.h"
|
||||||
|
#include "cmMem.h"
|
||||||
|
#include "cmSymTbl.h"
|
||||||
|
#include "cmLinkedHeap.h"
|
||||||
#include "cmTime.h"
|
#include "cmTime.h"
|
||||||
#include "cmMidi.h"
|
#include "cmMidi.h"
|
||||||
#include "cmSymTbl.h"
|
#include "cmSymTbl.h"
|
||||||
|
#include "cmMidiFile.h"
|
||||||
|
#include "cmAudioFile.h"
|
||||||
#include "cmScore.h"
|
#include "cmScore.h"
|
||||||
|
#include "cmTimeLine.h"
|
||||||
|
#include "cmProcObj.h"
|
||||||
|
#include "cmProc4.h"
|
||||||
|
|
||||||
namespace cw
|
namespace cw
|
||||||
{
|
{
|
||||||
@ -24,11 +36,15 @@ namespace cw
|
|||||||
|
|
||||||
typedef struct score_follower_str
|
typedef struct score_follower_str
|
||||||
{
|
{
|
||||||
unsigned search_area_locN;
|
double srate;
|
||||||
unsigned key_wnd_locN;
|
unsigned search_area_locN;
|
||||||
char* score_csv_fname;
|
unsigned key_wnd_locN;
|
||||||
|
char* score_csv_fname;
|
||||||
|
cmScH_t cmScoreH;
|
||||||
|
cmScMatcher* matcher;
|
||||||
|
unsigned* match_idA;
|
||||||
|
unsigned match_id_allocN;
|
||||||
|
unsigned match_id_curN;
|
||||||
} score_follower_t;
|
} score_follower_t;
|
||||||
|
|
||||||
score_follower_t* _handleToPtr( handle_t h )
|
score_follower_t* _handleToPtr( handle_t h )
|
||||||
@ -49,7 +65,7 @@ namespace cw
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((app->score_csv_fname = filesys::expandPath( score_csv_fname )) == nullptr )
|
if((p->score_csv_fname = filesys::expandPath( score_csv_fname )) == nullptr )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kOpFailRC,"Score follower score file expansion failed.");
|
rc = cwLogError(kOpFailRC,"Score follower score file expansion failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
@ -58,37 +74,106 @@ namespace cw
|
|||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned _get_max_cw_loc_value( score_follower_t* p )
|
||||||
|
{
|
||||||
|
unsigned cmEvtN = cmScoreEvtCount( p->cmScoreH );
|
||||||
|
unsigned maxCwLoc = 0;
|
||||||
|
for(unsigned i=0; i<cmEvtN; ++i)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxCwLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _createCwLocToCmLocMap( score_follower_t* p )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
rc_t _destroy( score_follower_t* p)
|
rc_t _destroy( score_follower_t* p)
|
||||||
{
|
{
|
||||||
mem::release(p->score_csv_fname);
|
mem::release(p->score_csv_fname);
|
||||||
mem::release(p);
|
mem::release(p);
|
||||||
|
cmScMatcherFree(&p->matcher);
|
||||||
|
cmScoreFinalize(&p->cmScoreH);
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void _score_follower_cb( struct cmScMatcher_str* smp, void* arg, cmScMatcherResult_t* r )
|
||||||
|
{
|
||||||
|
score_follower_t* p = (score_follower_t*)arg;
|
||||||
|
cmScoreEvt_t* cse;
|
||||||
|
|
||||||
|
// get a pointer to the matched event
|
||||||
|
if((cse = cmScoreEvt( p->cmScoreH, r->scEvtIdx )) == nullptr )
|
||||||
|
{
|
||||||
|
cwLogError(kInvalidStateRC,"cm Score event index (%i) reported by the score follower is invalid.",r->scEvtIdx );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( p->match_id_curN >= p->match_id_allocN )
|
||||||
|
{
|
||||||
|
cwLogError(kInvalidStateRC,"The score follower match id array is full.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the csvEventId corresponds to the cwPianoScore location
|
||||||
|
p->match_idA[ p->match_id_curN++ ] = cse->csvEventId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::score_follower::create( handle_t& hRef, const object_t* cfg, double srate )
|
cw::rc_t cw::score_follower::create( handle_t& hRef, const object_t* cfg, cm::handle_t cmCtxH, double srate )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
score_follower_t* p = nullptr;
|
cmCtx_t* cmCtx = context(cmCtxH);
|
||||||
|
cmProcCtx* cmProcCtx = proc_context(cmCtxH);
|
||||||
|
cmSymTblH_t cmSymTblH = cmSTATIC_NULL_HANDLE;
|
||||||
|
cmScRC_t scoreRC = cmOkRC;
|
||||||
|
|
||||||
if((rc = destroy(hRef)) != kOkRC )
|
if((rc = destroy(hRef)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
p = mem::allocZ<score_follower_t>();
|
score_follower_t* p = mem::allocZ<score_follower_t>();
|
||||||
|
|
||||||
if((rc = _parse_cfg(p,cfg)) != kOkRC )
|
if((rc = _parse_cfg(p,cfg)) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
cmScRC_t cmScoreInitialize( cmCtx_t* ctx, cmScH_t* hp, const cmChar_t* fn, double srate, const unsigned* dynRefArray, unsigned dynRefCnt, cmScCb_t cbFunc, void* cbArg, cmSymTblH_t stH );
|
if((scoreRC = cmScoreInitialize( cmCtx, &p->cmScoreH, p->score_csv_fname, srate, nullptr, 0, nullptr, nullptr, cmSymTblH )) != cmOkRC )
|
||||||
|
{
|
||||||
//cmRC_t cmScMatcherInit( cmScMatcher* p, double srate, cmScH_t scH, unsigned scWndN, unsigned midiWndN, cmScMatcherCb_t cbFunc, void* cbArg );
|
cwLogError(kOpFailRC,"The score could not be initialized from '%s'. cmRC:%i.",p->score_csv_fname);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if((p->matcher = cmScMatcherAlloc( cmProcCtx, // Program context.
|
||||||
|
nullptr, // Existing cmScMatcher to reallocate or NULL to allocate a new cmScMatcher.
|
||||||
|
srate, // System sample rate.
|
||||||
|
p->cmScoreH, // Score handle. See cmScore.h.
|
||||||
|
p->search_area_locN, // Length of the scores active search area. ** See Notes.
|
||||||
|
p->key_wnd_locN, // Length of the MIDI active note buffer. ** See Notes.
|
||||||
|
_score_follower_cb, // A cmScMatcherCb_t function to be called to notify the recipient of changes in the score matcher status.
|
||||||
|
p )) == nullptr ) // User argument to 'cbFunc'.
|
||||||
|
{
|
||||||
|
cwLogError(kOpFailRC,"The score follower allocation failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
p->srate = srate;
|
||||||
|
p->match_id_allocN = 128;
|
||||||
|
p->match_idA = mem::allocZ<unsigned>(p->match_id_allocN);
|
||||||
|
|
||||||
hRef.set(p);
|
hRef.set(p);
|
||||||
|
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
if( rc != kOkRC )
|
if( rc != kOkRC )
|
||||||
{
|
{
|
||||||
@ -119,12 +204,217 @@ cw::rc_t cw::score_follower::destroy( handle_t& hRef )
|
|||||||
cw::rc_t cw::score_follower::reset( handle_t h, unsigned loc )
|
cw::rc_t cw::score_follower::reset( handle_t h, unsigned loc )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
//score_follower_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
|
|
||||||
|
// cmRC_t cmScMatcherReset( cmScMatcher* p, unsigned scLocIdx );
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::score_follower::exec( handle_t h, unsigned smpIdx, unsigned muid, unsigned status, uint8_t d0, uint8_t d1, unsigned* scLocIdxPtr )
|
cw::rc_t cw::score_follower::exec( handle_t h, unsigned smpIdx, unsigned muid, unsigned status, uint8_t d0, uint8_t d1, bool& newMatchFlRef )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
cmRC_t cmRC = cmOkRC;
|
||||||
|
score_follower_t* p = _handleToPtr(h);
|
||||||
|
unsigned scLocIdx = cmInvalidIdx;
|
||||||
|
unsigned pre_match_id_curN = p->match_id_curN;
|
||||||
|
|
||||||
|
newMatchFlRef = false;
|
||||||
|
|
||||||
|
if((cmRC = cmScMatcherExec( p->matcher, smpIdx, muid, status, d0, d1, &scLocIdx )) != cmOkRC )
|
||||||
|
{
|
||||||
|
switch( cmRC )
|
||||||
|
{
|
||||||
|
case cmOkRC:
|
||||||
|
newMatchFlRef = p->match_id_curN != pre_match_id_curN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cmEofRC:
|
||||||
|
rc = cwLogInfo("Score match complete.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cmInvalidArgRC:
|
||||||
|
rc = cwLogError(kInvalidStateRC,"Score follower state is invalid.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cmSubSysFailRC:
|
||||||
|
rc = cwLogError(kOpFailRC,"The score follower failed during a resync attempt.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
rc = cwLogError(kOpFailRC,"The score follower failed with an unknown error. cmRC:%i",cmRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned* cw::score_follower::current_match_id_array( handle_t h, unsigned& cur_match_id_array_cnt_ref )
|
||||||
|
{
|
||||||
|
score_follower_t* p = _handleToPtr(h);
|
||||||
|
cur_match_id_array_cnt_ref = p->match_id_curN;
|
||||||
|
return p->match_idA;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cw::score_follower::clear_match_id_array( handle_t h )
|
||||||
|
{
|
||||||
|
score_follower_t* p = _handleToPtr(h);
|
||||||
|
p->match_id_curN = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace cw {
|
||||||
|
namespace score_follower {
|
||||||
|
|
||||||
|
typedef struct test_str
|
||||||
|
{
|
||||||
|
char* midi_fname;
|
||||||
|
char* out_dir;
|
||||||
|
double srate;
|
||||||
|
const object_t* cfg;
|
||||||
|
midi::file::handle_t mfH;
|
||||||
|
|
||||||
|
} test_t;
|
||||||
|
|
||||||
|
|
||||||
|
rc_t _test_destroy( test_t* p )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
mem::release(p->midi_fname);
|
||||||
|
mem::release(p->out_dir);
|
||||||
|
|
||||||
|
midi::file::close(p->mfH);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _test_parse_cfg( test_t* p, const object_t* cfg )
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
const char* midi_fname = nullptr;
|
||||||
|
const char* out_dir = nullptr;
|
||||||
|
|
||||||
|
// read the test cfg.
|
||||||
|
if((rc = cfg->getv("midi_fname", midi_fname,
|
||||||
|
"srate", p->srate,
|
||||||
|
"cfg", p->cfg,
|
||||||
|
"out_dir", out_dir )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Score follower test cfg. parse failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expand the MIDI filename
|
||||||
|
if((p->midi_fname = filesys::expandPath( midi_fname )) == nullptr )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kOpFailRC,"The MIDI file path expansion failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expand the output directory
|
||||||
|
if((p->out_dir = filesys::expandPath( out_dir)) == nullptr )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kOpFailRC,"The output directory path expansion failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the output directory
|
||||||
|
if( !filesys::isDir(p->out_dir))
|
||||||
|
{
|
||||||
|
if((rc = filesys::makeDir(p->out_dir)) != kOkRC )
|
||||||
|
{
|
||||||
|
cwLogError(kOpFailRC,"The output directory '%s' could not be created.", cwStringNullGuard(p->out_dir));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if(rc != kOkRC )
|
||||||
|
{
|
||||||
|
_test_destroy(p);
|
||||||
|
rc = cwLogError(rc,"Score follower test parse cfg. failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::score_follower::test( const object_t* cfg )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
test_t t = {0};
|
||||||
|
|
||||||
|
cm::handle_t cmCtxH;
|
||||||
|
handle_t sfH;
|
||||||
|
unsigned msgN = 0;
|
||||||
|
const midi::file::trackMsg_t** msgA = nullptr;
|
||||||
|
|
||||||
|
// parse the test cfg
|
||||||
|
if((rc = _test_parse_cfg( &t, cfg )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// create a cm context record
|
||||||
|
if((rc = cm::create(cmCtxH)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// create the score follower
|
||||||
|
if((rc = create( sfH, t.cfg, cmCtxH, t.srate )) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
// open the midi file
|
||||||
|
if((rc = midi::file::open( t.mfH, t.midi_fname )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"MIDI file open failed on '%s'.",cwStringNullGuard(t.midi_fname));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a pointer to a time sorted list of MIDI messages in the file
|
||||||
|
if(((msgN = msgCount( t.mfH )) == 0) || ((msgA = midi::file::msgArray( t.mfH )) == nullptr) )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"MIDI file msg array is empty or corrupt.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(unsigned i=0; i<msgN; ++i)
|
||||||
|
{
|
||||||
|
const midi::file::trackMsg_t* m = msgA[i];
|
||||||
|
|
||||||
|
if( midi::file::isNoteOn( m ) )
|
||||||
|
{
|
||||||
|
unsigned long smpIdx = (unsigned long)(t.srate * m->amicro/1e6);
|
||||||
|
bool newMatchFl = false;
|
||||||
|
if((rc = exec(sfH, smpIdx, m->uid, m->status, m->u.chMsgPtr->d0, m->u.chMsgPtr->d1, newMatchFl )) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"score follower exec failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( newMatchFl )
|
||||||
|
{
|
||||||
|
unsigned matchIdN = 0;
|
||||||
|
unsigned* matchIdA = current_match_id_array(sfH, matchIdN );
|
||||||
|
|
||||||
|
for(unsigned i=0; i<matchIdN; ++i)
|
||||||
|
cwLogInfo("Match:%i",matchIdA[i]);
|
||||||
|
|
||||||
|
clear_match_id_array( sfH );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
destroy(sfH);
|
||||||
|
cm::destroy(cmCtxH);
|
||||||
|
_test_destroy(&t);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
@ -7,13 +7,22 @@ namespace cw
|
|||||||
{
|
{
|
||||||
typedef handle< struct score_follower_str > handle_t;
|
typedef handle< struct score_follower_str > handle_t;
|
||||||
|
|
||||||
rc_t create( handle_t& hRef, const object_t* cfg, double srate );
|
rc_t create( handle_t& hRef, const object_t* cfg, cm::handle_t cmCtxH, double srate );
|
||||||
|
|
||||||
rc_t destroy( handle_t& hRef );
|
rc_t destroy( handle_t& hRef );
|
||||||
|
|
||||||
rc_t reset( handle_t h, unsigned loc );
|
rc_t reset( handle_t h, unsigned loc );
|
||||||
|
|
||||||
rc_t exec( handle_t h, unsigned smpIdx, unsigned muid, unsigned status, uint8_t d0, uint8_t d1, unsigned* scLocIdxPtr );
|
// If 'new_match_fl_ref' is returned as true then there are new match id's in the current_match_id_array[]
|
||||||
|
rc_t exec( handle_t h, unsigned smpIdx, unsigned muid, unsigned status, uint8_t d0, uint8_t d1, bool& new_match_fl_ref );
|
||||||
|
|
||||||
|
// Get a pointer to the event id's associated with the latest set of matches.
|
||||||
|
unsigned* current_match_id_array( handle_t h, unsigned& cur_match_id_array_cnt_ref );
|
||||||
|
|
||||||
|
// Clear the match id array. This should be done to empty the current_match_id_array()
|
||||||
|
void clear_match_id_array( handle_t h );
|
||||||
|
|
||||||
|
rc_t test( const object_t* cfg );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user