2024-11-17 21:19:15 +00:00
# include "cwCommon.h"
# include "cwLog.h"
# include "cwCommonImpl.h"
# include "cwTest.h"
# include "cwMem.h"
# include "cwText.h"
# include "cwObject.h"
# include "cwVectOps.h"
# include "cwMtx.h"
# include "cwDspTypes.h" // srate_t, sample_t, coeff_t, ...
# include "cwTime.h"
# include "cwMidiDecls.h"
# include "cwMidi.h"
# include "cwMidiFile.h"
# include "cwFlowDecl.h"
# include "cwFlow.h"
# include "cwFlowValue.h"
# include "cwFlowTypes.h"
# include "cwFlowNet.h"
# include "cwFlowProc.h"
# include "cwDynRefTbl.h"
# include "cwScoreParse.h"
# include "cwSfScore.h"
# include "cwSfTrack.h"
# include "cwPerfMeas.h"
# include "cwScoreFollowerPerf.h"
# include "cwScoreFollower.h"
# include "cwPianoScore.h"
# include "cwFlowPerf.h"
namespace cw
{
namespace flow
{
//------------------------------------------------------------------------------------------------------------------
//
// Score Player
//
namespace score_player
{
enum {
2024-11-18 16:49:03 +00:00
kScoreFNamePId ,
kVelTblFnamePId ,
kVelTblLabelPId ,
2024-11-17 21:19:15 +00:00
kDoneFlPId ,
kOutPId ,
kLocPId
} ;
typedef struct
{
unsigned sample_idx ;
unsigned loc ;
unsigned meas ;
2024-11-18 16:49:03 +00:00
unsigned d1 ; // inital d1 value before velocity mapping was applied
2024-11-17 21:19:15 +00:00
midi : : ch_msg_t * midi ; // index of associated msg in chMsgA
} msg_t ;
2024-11-18 16:49:03 +00:00
typedef struct vel_tbl_str
{
unsigned * tblA ;
unsigned tblN ;
char * label ;
struct vel_tbl_str * link ;
} vel_tbl_t ;
2024-11-17 21:19:15 +00:00
typedef struct
{
unsigned msgAllocN ;
unsigned msgN ;
msg_t * msgA ; // msgA[ msgN ]
midi : : ch_msg_t * chMsgA ; // chMsgA[ msgN ]
2024-11-18 16:49:03 +00:00
vel_tbl_t * velTblL ; // List of vel. tables.
vel_tbl_t * activeVelTbl ; // Currently active vel. table or null if no vel. tbl is active.
2024-11-17 21:19:15 +00:00
unsigned sample_idx ;
unsigned msg_idx ;
} inst_t ;
2024-11-18 16:49:03 +00:00
rc_t _load_score ( proc_t * proc , inst_t * p , const char * score_fname )
2024-11-17 21:19:15 +00:00
{
rc_t rc = kOkRC ;
2024-11-18 16:49:03 +00:00
perf_score : : handle_t perfScoreH ;
const perf_score : : event_t * score_evt = nullptr ;
char * fname = nullptr ;
2024-11-17 21:19:15 +00:00
2024-11-18 16:49:03 +00:00
if ( score_fname = = nullptr | | textLength ( score_fname ) = = 0 )
2024-11-17 21:19:15 +00:00
{
rc = cwLogError ( kInvalidArgRC , " The score filename is blank. " ) ;
goto errLabel ;
}
2024-11-18 16:49:03 +00:00
if ( ( fname = proc_expand_filename ( proc , score_fname ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The score filename (%s) is invalid. " , score_fname ) ;
goto errLabel ;
}
2024-11-17 21:19:15 +00:00
if ( ( rc = perf_score : : create ( perfScoreH , fname ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Score create failed on '%s'. " , fname ) ;
goto errLabel ;
}
if ( ( p - > msgAllocN = perf_score : : event_count ( perfScoreH ) ) = = 0 )
{
rc = cwLogWarning ( " The score '%s' is empty. " , fname ) ;
goto errLabel ;
}
if ( ( score_evt = perf_score : : base_event ( perfScoreH ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The score '%s' could not be accessed. " , fname ) ;
goto errLabel ;
}
p - > msgA = mem : : allocZ < msg_t > ( p - > msgAllocN ) ;
p - > chMsgA = mem : : allocZ < midi : : ch_msg_t > ( p - > msgAllocN ) ;
2024-11-18 16:49:03 +00:00
for ( ; p - > msgN < p - > msgAllocN & & score_evt ! = nullptr ; score_evt = score_evt - > link )
2024-11-17 21:19:15 +00:00
{
if ( score_evt - > status ! = 0 )
{
2024-11-18 16:49:03 +00:00
msg_t * m = p - > msgA + p - > msgN ;
2024-11-17 21:19:15 +00:00
midi : : ch_msg_t * mm = p - > chMsgA + p - > msgN ;
m - > sample_idx = ( unsigned ) ( proc - > ctx - > sample_rate * score_evt - > sec ) ;
2024-11-18 16:49:03 +00:00
m - > loc = score_evt - > loc ;
m - > meas = score_evt - > meas ;
m - > midi = mm ;
2024-11-17 21:19:15 +00:00
time : : fracSecondsToSpec ( mm - > timeStamp , score_evt - > sec ) ;
mm - > devIdx = kInvalidIdx ;
mm - > portIdx = kInvalidIdx ;
mm - > uid = score_evt - > uid ;
mm - > ch = score_evt - > status & 0x0f ;
mm - > status = score_evt - > status & 0xf0 ;
mm - > d0 = score_evt - > d0 ;
mm - > d1 = score_evt - > d1 ;
2024-11-18 16:49:03 +00:00
m - > d1 = score_evt - > d1 ;
2024-11-17 21:19:15 +00:00
p - > msgN + = 1 ;
}
2024-11-18 16:49:03 +00:00
}
errLabel :
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " Score load failed on '%s'. " , cwStringNullGuard ( fname ) ) ;
perf_score : : destroy ( perfScoreH ) ;
mem : : release ( fname ) ;
return rc ;
}
rc_t _load_vel_table_file ( proc_t * proc , inst_t * p , const char * vel_tbl_fname )
{
rc_t rc = kOkRC ;
object_t * cfg = nullptr ;
const object_t * tblL = nullptr ;
unsigned tblN = 0 ;
char * fname = nullptr ;
if ( vel_tbl_fname = = nullptr | | textLength ( vel_tbl_fname ) = = 0 )
{
rc = cwLogError ( kInvalidArgRC , " The velocity table filename is blank. " ) ;
goto errLabel ;
}
if ( ( fname = proc_expand_filename ( proc , vel_tbl_fname ) ) = = nullptr )
{
rc = cwLogError ( kOpFailRC , " The velocity table filename (%s) is invalid. " , vel_tbl_fname ) ;
goto errLabel ;
2024-11-17 21:19:15 +00:00
}
2024-11-18 16:49:03 +00:00
if ( ( rc = objectFromFile ( fname , cfg ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Velocity table file parse failed. " ) ;
goto errLabel ;
}
if ( ( rc = cfg - > getv ( " tables " , tblL ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Velocity table file has no 'tables' field. " ) ;
goto errLabel ;
}
tblN = tblL - > child_count ( ) ;
for ( unsigned i = 0 ; i < tblN ; + + i )
{
const object_t * tbl = tblL - > child_ele ( i ) ;
const object_t * velListCfg = nullptr ;
vel_tbl_t * vt = nullptr ;
const char * label = nullptr ;
if ( ( rc = tbl - > getv ( " table " , velListCfg ,
" name " , label ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Velocity table at index %i failed. " , i ) ;
goto errLabel ;
}
vt = mem : : allocZ < vel_tbl_t > ( ) ;
vt - > link = p - > velTblL ;
p - > velTblL = vt ;
vt - > tblN = velListCfg - > child_count ( ) ;
vt - > label = mem : : duplStr ( label ) ;
// if the table is empty
if ( vt - > tblN = = 0 )
{
rc = cwLogError ( rc , " The velocity table named '%s' appears to be blank. " , cwStringNullGuard ( label ) ) ;
continue ;
}
vt - > tblA = mem : : allocZ < unsigned > ( vt - > tblN ) ;
for ( unsigned j = 0 ; j < vt - > tblN ; + + j )
{
const object_t * intCfg ;
if ( ( intCfg = velListCfg - > child_ele ( j ) ) = = nullptr )
{
rc = cwLogError ( rc , " Access to the integer value at index %i failed on vel. table '%s'. " , j , cwStringNullGuard ( label ) ) ;
goto errLabel ;
}
if ( ( rc = intCfg - > value ( vt - > tblA [ j ] ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Parse failed on integer value at index %i in vel. table '%s'. " , j , cwStringNullGuard ( label ) ) ;
goto errLabel ;
}
}
}
2024-11-17 21:19:15 +00:00
2024-11-18 16:49:03 +00:00
2024-11-17 21:19:15 +00:00
errLabel :
2024-11-18 16:49:03 +00:00
if ( rc ! = kOkRC )
rc = cwLogError ( rc , " Score velocity table file load failed on '%s'. " , cwStringNullGuard ( vel_tbl_fname ) ) ;
if ( cfg ! = nullptr )
cfg - > free ( ) ;
mem : : release ( fname ) ;
2024-11-17 21:19:15 +00:00
return rc ;
}
2024-11-18 16:49:03 +00:00
rc_t _activate_vel_table ( proc_t * proc , inst_t * p , const char * vel_tbl_label )
{
for ( vel_tbl_t * vt = p - > velTblL ; vt ! = nullptr ; vt = vt - > link )
if ( textIsEqual ( vt - > label , vel_tbl_label ) )
{
p - > activeVelTbl = vt ;
return kOkRC ;
}
cwLogWarning ( " The requested velocity table '%s' was not found on the score instance '%s:%i'. " , vel_tbl_label , proc - > label , proc - > label_sfx_id ) ;
return kOkRC ;
}
rc_t _apply_vel_table ( inst_t * p )
{
rc_t rc = kOkRC ;
if ( p - > activeVelTbl = = nullptr )
{
cwLogWarning ( " A velocity table has not been selected. " ) ;
goto errLabel ;
}
for ( unsigned i = 0 ; i < p - > msgN ; + + i )
{
midi : : ch_msg_t * m = p - > msgA [ i ] . midi ;
if ( midi : : isNoteOn ( m - > status , m - > d1 ) )
{
if ( p - > msgA [ i ] . d1 > = p - > activeVelTbl - > tblN )
{
rc = cwLogError ( kInvalidArgRC , " The pre-mapped velocity value %i is outside of the range (%i) of the velocity table '%s'. " , p - > msgA [ i ] . d1 , p - > activeVelTbl - > tblN , cwStringNullGuard ( p - > activeVelTbl - > label ) ) ;
goto errLabel ;
}
m - > d1 = p - > activeVelTbl - > tblA [ p - > msgA [ i ] . d1 ] ;
}
}
errLabel :
return rc ;
}
2024-11-17 21:19:15 +00:00
rc_t _create ( proc_t * proc , inst_t * p )
{
rc_t rc = kOkRC ;
const char * score_fname = nullptr ;
2024-11-18 16:49:03 +00:00
const char * vel_tbl_fname = nullptr ;
const char * vel_tbl_label = nullptr ;
2024-11-17 21:19:15 +00:00
2024-11-18 16:49:03 +00:00
if ( ( rc = var_register_and_get ( proc , kAnyChIdx ,
kScoreFNamePId , " fname " , kBaseSfxId , score_fname ,
kVelTblFnamePId , " vel_tbl_fname " , kBaseSfxId , vel_tbl_fname ,
kVelTblLabelPId , " vel_tbl_label " , kBaseSfxId , vel_tbl_label ) ) ! = kOkRC )
2024-11-17 21:19:15 +00:00
{
goto errLabel ;
}
if ( ( rc = var_register ( proc , kAnyChIdx ,
kLocPId , " loc " , kBaseSfxId ,
kDoneFlPId , " done_fl " , kBaseSfxId ) ) ! = kOkRC )
{
goto errLabel ;
}
2024-11-18 16:49:03 +00:00
// load the score
if ( ( rc = _load_score ( proc , p , score_fname ) ) ! = kOkRC )
{
goto errLabel ;
}
// load p->velTblL from the vel table file
if ( ( rc = _load_vel_table_file ( proc , p , vel_tbl_fname ) ) ! = kOkRC )
{
goto errLabel ;
}
// activate the selected velocity table
if ( ( rc = _activate_vel_table ( proc , p , vel_tbl_label ) ) ! = kOkRC )
{
goto errLabel ;
}
// apply the selected velocity table
if ( p - > activeVelTbl ! = nullptr )
{
if ( ( rc = _apply_vel_table ( p ) ) ! = kOkRC )
{
goto errLabel ;
}
}
2024-11-17 21:19:15 +00:00
// create one output MIDI buffer
rc = var_register_and_set ( proc , " out " , kBaseSfxId , kOutPId , kAnyChIdx , nullptr , 0 ) ;
errLabel :
return rc ;
}
rc_t _destroy ( proc_t * proc , inst_t * p )
{
rc_t rc = kOkRC ;
2024-11-18 16:49:03 +00:00
for ( vel_tbl_t * vt = p - > velTblL ; vt ! = nullptr ; vt = vt - > link )
{
vel_tbl_t * vt0 = vt - > link ;
mem : : release ( vt - > tblA ) ;
mem : : release ( vt ) ;
vt = vt0 ;
}
2024-11-17 21:19:15 +00:00
return rc ;
}
rc_t _value ( proc_t * proc , inst_t * p , variable_t * var )
{
rc_t rc = kOkRC ;
return rc ;
}
rc_t _exec ( proc_t * proc , inst_t * p )
{
rc_t rc = kOkRC ;
mbuf_t * mbuf = nullptr ;
bool done_fl = false ;
p - > sample_idx + = proc - > ctx - > framesPerCycle ;
// get the output variable
if ( ( rc = var_get ( proc , kOutPId , kAnyChIdx , mbuf ) ) ! = kOkRC )
rc = cwLogError ( kInvalidStateRC , " The MIDI file instance '%s' does not have a valid MIDI output buffer. " , proc - > label ) ;
else
{
mbuf - > msgA = nullptr ;
mbuf - > msgN = 0 ;
while ( p - > msg_idx < p - > msgN & & p - > sample_idx > = p - > msgA [ p - > msg_idx ] . sample_idx )
{
if ( mbuf - > msgA = = nullptr )
2024-11-18 16:49:03 +00:00
{
// Note we only set a pointer to the first msg in p->chMsgA[]
// successive messages will be consecutively after it.
2024-11-17 21:19:15 +00:00
mbuf - > msgA = p - > msgA [ p - > msg_idx ] . midi ;
2024-11-18 16:49:03 +00:00
}
2024-11-17 21:19:15 +00:00
mbuf - > msgN + = 1 ;
p - > msg_idx + = 1 ;
done_fl = p - > msg_idx = = p - > msgN ;
}
2024-11-18 16:49:03 +00:00
if ( done_fl )
2024-11-17 21:19:15 +00:00
var_set ( proc , kDoneFlPId , kAnyChIdx , true ) ;
}
return rc ;
}
rc_t _report ( proc_t * proc , inst_t * p )
{ return kOkRC ; }
class_members_t members = {
. create = std_create < inst_t > ,
. destroy = std_destroy < inst_t > ,
. value = std_value < inst_t > ,
. exec = std_exec < inst_t > ,
. report = std_report < inst_t >
} ;
} // score_player
//------------------------------------------------------------------------------------------------------------------
//
// Midi To Msg
//
namespace midi_to_msg
{
enum {
kInPId ,
kFieldsPId ,
kBufCntPId ,
kOutPId
} ;
typedef struct
{
recd_array_t * recd_array ;
unsigned allocRecdN ;
unsigned midiFieldIdx ;
} inst_t ;
rc_t _create_recd_array ( inst_t * p , const char * fields_string )
{
rc_t rc = kOkRC ;
const char * prefix_string = " midi " ;
unsigned sn = textLength ( prefix_string ) + textLength ( fields_string ) ;
char s [ sn + 1 ] ;
strcpy ( s , prefix_string ) ;
strcat ( s , fields_string ) ;
s [ sn ] = 0 ;
recd_type_t * recd_type = nullptr ;
if ( ( rc = recd_type_create ( recd_type , nullptr , s ) ) ! = kOkRC )
{
rc = cwLogError ( kOpFailRC , " recd type failed on field strings:'%s'. " , cwStringNullGuard ( s ) ) ;
goto errLabel ;
}
// Allocate a recd_buf large enough to hold the max. number of messages arriving on a single call to exec().
if ( ( rc = recd_array_create ( p - > recd_array , recd_type , p - > allocRecdN ) ) ! = kOkRC )
{
rc = cwLogError ( kOpFailRC , " recd_array create of size %i failed. " , p - > allocRecdN ) ;
goto errLabel ;
}
errLabel :
return rc ;
}
rc_t _create ( proc_t * proc , inst_t * p )
{
rc_t rc = kOkRC ;
const char * fields_string = nullptr ;
if ( ( rc = var_register ( proc , kAnyChIdx , kInPId , " in " , kBaseSfxId ) ) ! = kOkRC )
{
goto errLabel ;
}
if ( ( rc = var_register_and_get ( proc , kAnyChIdx ,
kBufCntPId , " buf_cnt " , kBaseSfxId , p - > allocRecdN ,
kFieldsPId , " fields " , kBaseSfxId , fields_string ) ) ! = kOkRC )
{
goto errLabel ;
}
if ( ( rc = _create_recd_array ( p , fields_string ) ) ! = kOkRC )
{
goto errLabel ;
}
// create one output msg buffer
if ( ( rc = var_register_and_set ( proc , " out " , kBaseSfxId , kOutPId , kAnyChIdx , p - > recd_array - > type , nullptr , 0 ) ) ! = kOkRC )
{
goto errLabel ;
}
if ( ( p - > midiFieldIdx = recd_type_field_index ( p - > recd_array - > type , " midi " ) ) ! = kOkRC )
{
rc = cwLogError ( kInvalidArgRC , " The 'midi' record field was not found. " ) ;
goto errLabel ;
}
errLabel :
return rc ;
}
rc_t _destroy ( proc_t * proc , inst_t * p )
{
rc_t rc = kOkRC ;
recd_array_destroy ( p - > recd_array ) ;
return rc ;
}
rc_t _value ( proc_t * proc , inst_t * p , variable_t * var )
{
rc_t rc = kOkRC ;
return rc ;
}
rc_t _exec ( proc_t * proc , inst_t * p )
{
rc_t rc = kOkRC ;
rbuf_t * out_rbuf = nullptr ;
mbuf_t * in_mbuf = nullptr ;
// get the output record buffer
if ( ( rc = var_get ( proc , kOutPId , kAnyChIdx , out_rbuf ) ) ! = kOkRC )
{
rc = cwLogError ( kInvalidStateRC , " The output recd buf variable access failed. " ) ;
goto errLabel ;
}
// get the input MIDI buffer
if ( ( rc = var_get ( proc , kInPId , kAnyChIdx , in_mbuf ) ) ! = kOkRC )
{
rc = cwLogError ( kInvalidStateRC , " The input MIDI buf variable access failed. " ) ;
goto errLabel ;
}
// copy a pointer to each input MIDI record to the 'midi' field of the assoc'd recd
for ( unsigned i = 0 ; i < in_mbuf - > msgN ; + + i )
{
//recd_t* r = p->recd_array->recdA + i;
//recd_set( p->recd_array->type, r, p->midiFieldIdx, in_mbuf->msgA + i );
}
// the rbuf is just a proxy to the first 'in_mbuf->msgN' records in the p->recd_array.
rbuf_setup ( out_rbuf , p - > recd_array - > type , p - > recd_array - > recdA , in_mbuf - > msgN ) ;
errLabel :
return rc ;
}
rc_t _report ( proc_t * proc , inst_t * p )
{ return kOkRC ; }
class_members_t members = {
. create = std_create < inst_t > ,
. destroy = std_destroy < inst_t > ,
. value = std_value < inst_t > ,
. exec = std_exec < inst_t > ,
. report = std_report < inst_t >
} ;
} // midi_to_msg
//------------------------------------------------------------------------------------------------------------------
//
// Score Follower
//
namespace score_follower
{
enum
{
kInPId ,
kDynTblFnamePId ,
kFnamePId ,
kScoreWndCntPId ,
kMidiWndCntPId ,
kPrintFlPId ,
kBacktrackFlPId ,
kLocPId ,
kOutPId ,
} ;
typedef struct
{
cw : : dyn_ref_tbl : : handle_t dynRefH ;
cw : : score_parse : : handle_t scParseH ;
cw : : sfscore : : handle_t scoreH ;
cw : : score_follower : : handle_t sfH ;
unsigned midi_field_idx ;
unsigned loc_field_idx ;
} inst_t ;
rc_t _create ( proc_t * proc , inst_t * p )
{
rc_t rc = kOkRC ;
rbuf_t * in_rbuf = nullptr ;
const char * score_fname = nullptr ;
const char * dyn_tbl_fname = nullptr ;
bool printParseWarningsFl = true ;
cw : : score_follower : : args_t args ;
if ( ( rc = var_register_and_get ( proc , kAnyChIdx ,
kInPId , " in " , kBaseSfxId , in_rbuf ,
kFnamePId , " fname " , kBaseSfxId , score_fname ,
kDynTblFnamePId , " dyn_ref_fname " , kBaseSfxId , dyn_tbl_fname ,
kScoreWndCntPId , " score_wnd " , kBaseSfxId , args . scoreWndLocN ,
kMidiWndCntPId , " midi_wnd " , kBaseSfxId , args . midiWndLocN ,
kPrintFlPId , " print_fl " , kBaseSfxId , args . trackPrintFl ,
kBacktrackFlPId , " back_track_fl " , kBaseSfxId , args . trackResultsBacktrackFl ) ) ! = kOkRC )
{
goto errLabel ;
}
// get the input record 'midi' field index
if ( ( p - > midi_field_idx = recd_type_field_index ( in_rbuf - > type , " midi " ) ) = = kInvalidIdx )
{
rc = cwLogError ( rc , " The input record type on '%s:%i' does not have a 'midi' field. " , cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id ) ;
goto errLabel ;
}
// get the input record 'loc' field index
if ( ( p - > loc_field_idx = recd_type_field_index ( in_rbuf - > type , " loc " ) ) = = kInvalidIdx )
{
rc = cwLogError ( rc , " The input record type on '%s:%i' does not have a 'loc' field. " , cwStringNullGuard ( proc - > label ) , proc - > label_sfx_id ) ;
goto errLabel ;
}
// parse the dynamics reference array
if ( ( rc = dyn_ref_tbl : : create ( p - > dynRefH , dyn_tbl_fname ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The reference dynamics array parse failed. " ) ;
goto errLabel ;
}
// parse the score
if ( ( rc = create ( p - > scParseH , score_fname , proc - > ctx - > sample_rate , p - > dynRefH , printParseWarningsFl ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Score parse failed. " ) ;
goto errLabel ;
}
// create the SF score
if ( ( rc = create ( p - > scoreH , p - > scParseH , printParseWarningsFl ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " SF Score create failed. " ) ;
goto errLabel ;
}
args . enableFl = true ;
args . scoreH = p - > scoreH ;
// create the score follower
if ( ( rc = create ( p - > sfH , args ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Score follower create failed. " ) ;
goto errLabel ;
}
errLabel :
return rc ;
}
rc_t _destroy ( proc_t * proc , inst_t * p )
{
rc_t rc = kOkRC ;
destroy ( p - > sfH ) ;
destroy ( p - > scoreH ) ;
destroy ( p - > scParseH ) ;
destroy ( p - > dynRefH ) ;
return rc ;
}
rc_t _value ( proc_t * proc , inst_t * p , variable_t * var )
{
rc_t rc = kOkRC ;
return rc ;
}
rc_t _exec ( proc_t * proc , inst_t * p )
{
rc_t rc = kOkRC ;
unsigned sample_idx = proc - > ctx - > cycleIndex * proc - > ctx - > framesPerCycle ;
double sec = ( ( double ) sample_idx ) / proc - > ctx - > sample_rate ;
rbuf_t * rbuf = nullptr ;
unsigned result_recd_idx = kInvalidIdx ;
if ( ( rc = var_get ( proc , kInPId , kAnyChIdx , rbuf ) ) = = kOkRC )
goto errLabel ;
// for each incoming record
for ( unsigned i = 0 ; i < rbuf - > recdN ; + + i )
{
bool match_fl = false ;
midi : : ch_msg_t * m = nullptr ;
if ( ( rc = recd_get ( rbuf - > type , rbuf - > recdA + i , p - > midi_field_idx , m ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " The 'midi' field read failed. " ) ;
goto errLabel ;
}
if ( ( rc = exec ( p - > sfH , sec , sample_idx , m - > uid , m - > status , m - > d0 , m - > d1 , match_fl ) ) ! = kOkRC )
{
rc = cwLogError ( rc , " Score follower exec failed. " ) ;
goto errLabel ;
}
if ( match_fl )
result_recd_idx = i ;
}
if ( result_recd_idx ! = kInvalidIdx )
{
unsigned resultIdxN = 0 ;
const unsigned * resultIdxA = current_result_index_array ( p - > sfH , resultIdxN ) ;
const sftrack : : result_t * resultA = cw : : score_follower : : track_result ( p - > sfH ) ;
for ( unsigned i = 0 ; i < resultIdxN ; + + i )
{
const sftrack : : result_t * r = resultA + resultIdxA [ i ] ;
const sfscore : : event_t * e = event ( p - > scoreH , r - > scEvtIdx ) ;
// store the performance data in the score
set_perf ( p - > scoreH , r - > scEvtIdx , r - > sec , r - > pitch , r - > vel , r - > cost ) ;
if ( i + 1 = = resultIdxN )
{
//recd_set( rbuf->type, rbuf->recdA + result_recd_idx, p->loc_field_idx, e->oLocId );
var_set ( proc , kLocPId , kAnyChIdx , e - > oLocId ) ;
}
}
var_set ( proc , kOutPId , kAnyChIdx , rbuf ) ;
}
errLabel :
return rc ;
}
rc_t _report ( proc_t * proc , inst_t * p )
{ return kOkRC ; }
class_members_t members = {
. create = std_create < inst_t > ,
. destroy = std_destroy < inst_t > ,
. value = std_value < inst_t > ,
. exec = std_exec < inst_t > ,
. report = std_report < inst_t >
} ;
} // score_follower
} // flow
} //cw