#ifndef cwSfTracker_h #define cwSfTracker_h namespace cw { namespace sftrack { typedef struct result_str { unsigned locIdx; // index into cmScMatch_t.loc[] unsigned scEvtIdx; // score event index unsigned mni; // index of the performed MIDI event associated with this score location unsigned smpIdx; // sample time index of performed MIDI event unsigned muid; // MIDI file event msg unique id (See cmMidiTrackMsg_t.uid) unsigned pitch; // performed pitch unsigned vel; // performed velocity unsigned flags; // smTruePosFl | smFalsePosFl } result_t; struct sftrack_str; typedef void (*callback_func_t)( void* arg, result_t* rp ); typedef struct sftrack_str { callback_func_t cbFunc; void* cbArg; sfmatch::handle_t matchH; unsigned mn; // size of midiBuf[] sfmatch::midi_t* midiBuf; // midiBuf[mn] result_t* res; // res[rn] unsigned rn; // length of res[] (set to 2*score event count) unsigned ri; // next avail res[] recd. double s_opt; // unsigned missCnt; // current count of consecutive trailing non-matches unsigned ili; // index into loc[] to start scan following reset unsigned eli; // index into loc[] of the last positive match. unsigned mni; // current count of MIDI events since the last call to cmScMatcherReset() unsigned mbi; // index of oldest MIDI event in midiBuf[]; stays at 0 when the buffer is full. unsigned begSyncLocIdx; // start of score window, in mp->loc[], of best match in previous scan unsigned initHopCnt; // max window hops during the initial (when the MIDI buffer fills for first time) sync scan unsigned stepCnt; // count of forward/backward score loc's to examine for a match during cmScMatcherStep(). unsigned maxMissCnt; // max. number of consecutive non-matches during step prior to executing a scan. unsigned scanCnt; // current count of times a resync-scan was executed during cmScMatcherStep() bool printFl; } sftrack_t; typedef handle handle_t; rc_t create( handle_t& hRef, double srate, // System sample rate. sfscore::handle_t scH, // Score handle. See cmScore.h. unsigned scWndN, // Length of the scores active search area. ** See Notes. unsigned midiWndN, // Length of the MIDI active note buffer. ** See Notes. callback_func_t cbFunc, // A cmScMatcherCb_t function to be called to notify the recipient of changes in the score matcher status. void* cbArg ); // User argument to 'cbFunc'. // Notes: // The cmScMatcher maintains an internal cmScMatch object which is used to attempt to find the // best match between the current MIDI active note buffer and the current score search area. // 'scWndN' is used to set the cmScMatch 'locN' argument. // 'midiWndN' sets the length of the MIDI FIFO which is used to match to the score with // each recceived MIDI note. // 'midiWndN' must be <= 'scWndN'. rc_t destroy( handle_t& hRef ); // 'scLocIdx' is a score index as used by cmScoreLoc(scH) not into p->mp->loc[]. rc_t reset( handle_t h, unsigned scLocIdx ); // Slide a score window 'hopCnt' times, beginning at 'bli' (an // index into p->mp->loc[]) looking for the best match to p->midiBuf[]. // The score window contain scWndN (p->mp->mcn-1) score locations. // Returns the index into p->mp->loc[] of the start of the best // match score window. The score associated // with this match is stored in s_opt. //unsigned scan( handle_t h, unsigned bli, unsigned hopCnt ); // Step forward/back by p->stepCnt from p->eli. // p->eli must therefore be valid prior to calling this function. // If more than p->maxMissCnt consecutive MIDI events are // missed then automatically run cmScAlignScan(). // Return cmEofRC if the end of the score is encountered. // Return cmSubSysFailRC if an internal scan resync. failed. //rc_t step( handle_t h ); // This function calls cmScMatcherScan() and cmScMatcherStep() internally. // If 'status' is not kNonMidiMdId then the function returns without changing the // state of the object. In other words the matcher only recognizes MIDI note-on messages. // If the MIDI note passed by the call results in a successful match then // p->eli will be updated to the location in p->mp->loc[] of the latest // match, the MIDI note in p->midiBuf[] associated with this match // will be assigned a valid locIdx and scLocIdx values, and *scLocIdxPtr // will be set with the matched scLocIdx of the match. // If this call does not result in a successful match *scLocIdxPtr is set // to cmInvalidIdx. // 'muid' is the unique id associated with this MIDI event under the circumstances // that the event came from a MIDI file. See cmMidiFile.h cmMidiTrackMsg_t.uid. // Return: // cmOkRC - Continue processing MIDI events. // cmEofRC - The end of the score was encountered. // cmInvalidArgRC - scan failed or the object was in an invalid state to attempt a match. // cmSubSysFailRC - a scan resync failed in cmScMatcherStep(). rc_t exec( handle_t h, unsigned smpIdx, unsigned muid, unsigned status, midi::byte_t d0, midi::byte_t d1, unsigned* scLocIdxPtr ); void print( handle_t h ); rc_t test( const object_t* cfg ); } } #endif