cwSfScore.h/cpp : Added initial performance update functionality.
Changed location identifiers to consistently use oLocId and eLocId. Added many fields to event_t.
This commit is contained in:
parent
b9f497e1ec
commit
16ba4d6a3f
632
cwSfScore.cpp
632
cwSfScore.cpp
@ -47,7 +47,6 @@ namespace cw
|
|||||||
event_t* event;
|
event_t* event;
|
||||||
loc_t* loc;
|
loc_t* loc;
|
||||||
section_t* section;
|
section_t* section;
|
||||||
set_t* setA[ score_parse::kVarCnt ];
|
|
||||||
} rpt_event_t;
|
} rpt_event_t;
|
||||||
|
|
||||||
|
|
||||||
@ -57,7 +56,7 @@ namespace cw
|
|||||||
|
|
||||||
void _destroy_set( set_t* s )
|
void _destroy_set( set_t* s )
|
||||||
{
|
{
|
||||||
mem::release(s->eleArray);
|
mem::release(s->evtArray);
|
||||||
mem::release(s->sectArray);
|
mem::release(s->sectArray);
|
||||||
mem::release(s);
|
mem::release(s);
|
||||||
}
|
}
|
||||||
@ -79,7 +78,7 @@ namespace cw
|
|||||||
|
|
||||||
for(unsigned i=0; i<p->setN; ++i)
|
for(unsigned i=0; i<p->setN; ++i)
|
||||||
{
|
{
|
||||||
mem::release(p->setA[i].eleArray);
|
mem::release(p->setA[i].evtArray);
|
||||||
mem::release(p->setA[i].sectArray);
|
mem::release(p->setA[i].sectArray);
|
||||||
}
|
}
|
||||||
mem::release(p->setA);
|
mem::release(p->setA);
|
||||||
@ -88,6 +87,10 @@ namespace cw
|
|||||||
_destroy_section( p->sectionA + i );
|
_destroy_section( p->sectionA + i );
|
||||||
mem::release(p->sectionA);
|
mem::release(p->sectionA);
|
||||||
|
|
||||||
|
|
||||||
|
for(unsigned i=0; i<p->eventN; ++i)
|
||||||
|
mem::release(p->eventA[i].varA);
|
||||||
|
|
||||||
mem::release(p->eventA);
|
mem::release(p->eventA);
|
||||||
|
|
||||||
if( p->deleteParserH_Fl )
|
if( p->deleteParserH_Fl )
|
||||||
@ -146,27 +149,39 @@ namespace cw
|
|||||||
e->type = pe->opId;
|
e->type = pe->opId;
|
||||||
e->secs = pe->sec;
|
e->secs = pe->sec;
|
||||||
e->index = p->eventN;
|
e->index = p->eventN;
|
||||||
e->locIdx = pe->oloc;
|
e->oLocId = pe->oLocId;
|
||||||
e->pitch = pe->d0;
|
e->pitch = pe->d0;
|
||||||
e->vel = pe->d1;
|
e->vel = pe->d1;
|
||||||
e->flags = 0;
|
e->flags = pe->flags;
|
||||||
e->dynVal = pe->dynLevel;
|
e->dynLevel = pe->dynLevel;
|
||||||
e->frac = _calc_frac(pe->rval, pe->dotCnt);
|
e->frac = _calc_frac(pe->rval, pe->dotCnt);
|
||||||
e->barNumb = pe->barNumb;
|
e->barNumb = pe->barNumb;
|
||||||
e->barNoteIdx = pe->barPitchIdx;
|
e->barNoteIdx = pe->barPitchIdx;
|
||||||
e->csvRowNumb = pe->csvRowNumb;
|
e->csvRowNumb = pe->csvRowNumb;
|
||||||
e->line = pe->csvRowNumb;
|
e->line = pe->csvRowNumb;
|
||||||
e->csvEventId = kInvalidId; // pe->csvId;
|
e->parseEvtIdx = pe->index;
|
||||||
e->hash = pe->hash;
|
e->hash = pe->hash;
|
||||||
|
e->bpm = pe->bpm;
|
||||||
|
e->bpm_rval = pe->bpm_rval;
|
||||||
|
|
||||||
for(unsigned i = score_parse::kMinVarIdx; i<score_parse::kVarCnt; ++i)
|
e->varN = std::count_if( pe->varA, pe->varA + score_parse::kVarCnt, [](const score_parse::event_var_t& x){ return x.flags!=0; });
|
||||||
|
e->varA = mem::allocZ<var_t>(e->varN);
|
||||||
|
|
||||||
|
for(unsigned k = score_parse::kMinVarIdx,j=0; k<score_parse::kVarCnt && j<e->varN; ++k)
|
||||||
{
|
{
|
||||||
e->varA[i] = pe->varA[i].flags;
|
if( pe->varA[k].flags != 0 )
|
||||||
e->flags |= pe->varA[i].flags;
|
{
|
||||||
|
assert( k == pe->varA[k].set->varTypeId );
|
||||||
|
|
||||||
|
e->varA[j].flags = pe->varA[k].flags;
|
||||||
|
e->varA[j].varId = pe->varA[k].set->varTypeId;
|
||||||
|
e->flags |= pe->varA[k].flags;
|
||||||
|
++j;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( e->locIdx > p->locN )
|
if( e->oLocId > p->locN )
|
||||||
p->locN = e->locIdx;
|
p->locN = e->oLocId;
|
||||||
|
|
||||||
p->eventN += 1;
|
p->eventN += 1;
|
||||||
}
|
}
|
||||||
@ -197,14 +212,14 @@ namespace cw
|
|||||||
{
|
{
|
||||||
const event_t* e = p->eventA + i;
|
const event_t* e = p->eventA + i;
|
||||||
|
|
||||||
if( e->locIdx != p->eventA[ebi].locIdx || i==p->eventN-1 )
|
if( e->oLocId != p->eventA[ebi].oLocId || i == p->eventN-1 )
|
||||||
{
|
{
|
||||||
unsigned locIdx = p->eventA[ebi].locIdx;
|
unsigned oLocId = p->eventA[ebi].oLocId;
|
||||||
|
|
||||||
assert( locIdx < p->locN);
|
assert( oLocId < p->locN);
|
||||||
|
|
||||||
loc_t* loc = p->locA + locIdx;
|
loc_t* loc = p->locA + oLocId;
|
||||||
loc->index = p->eventA[ebi].locIdx;
|
loc->index = p->eventA[ebi].oLocId;
|
||||||
loc->secs = p->eventA[ebi].secs;
|
loc->secs = p->eventA[ebi].secs;
|
||||||
loc->barNumb = p->eventA[ebi].barNumb;
|
loc->barNumb = p->eventA[ebi].barNumb;
|
||||||
loc->evtCnt = (i - ebi) + (i == p->eventN-1 ? 1 : 0);
|
loc->evtCnt = (i - ebi) + (i == p->eventN-1 ? 1 : 0);
|
||||||
@ -218,10 +233,7 @@ namespace cw
|
|||||||
|
|
||||||
ebi = i;
|
ebi = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -249,7 +261,20 @@ namespace cw
|
|||||||
if( ps->begEvent != nullptr )
|
if( ps->begEvent != nullptr )
|
||||||
{
|
{
|
||||||
section_t* section = p->sectionA + i;
|
section_t* section = p->sectionA + i;
|
||||||
event_t* begEvt = _hash_to_event(p,ps->begEvent->hash);
|
unsigned beg_evt_idx = ps->begEvent->index;
|
||||||
|
unsigned end_evt_idx = ps->endEvent->index;
|
||||||
|
const score_parse::event_t* eventA = event_array( p->parserH );
|
||||||
|
unsigned eventN = event_count( p->parserH );
|
||||||
|
event_t* begEvt = nullptr;
|
||||||
|
|
||||||
|
// advance to the first onset event
|
||||||
|
for(unsigned i = beg_evt_idx; i<=end_evt_idx && i<eventN; ++i)
|
||||||
|
if( eventA[i].oLocId != kInvalidId )
|
||||||
|
{
|
||||||
|
begEvt = _hash_to_event(p,eventA[i].hash);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if( begEvt == nullptr )
|
if( begEvt == nullptr )
|
||||||
{
|
{
|
||||||
@ -260,11 +285,11 @@ namespace cw
|
|||||||
section->label = mem::duplStr(ps->label);
|
section->label = mem::duplStr(ps->label);
|
||||||
section->index = i;
|
section->index = i;
|
||||||
section->begEvtIndex = begEvt->index;
|
section->begEvtIndex = begEvt->index;
|
||||||
section->locPtr = p->locA + p->eventA[begEvt->index].locIdx;
|
section->locPtr = p->locA + p->eventA[begEvt->index].oLocId;
|
||||||
section->locPtr->begSectPtr = section;
|
section->locPtr->begSectPtr = section;
|
||||||
|
|
||||||
for(unsigned j=0; j<score_parse::kVarCnt; ++j)
|
//for(unsigned j = 0; j<score_parse::kVarCnt; ++j)
|
||||||
section->vars[j] = DBL_MAX;
|
// section->vars[j] = DBL_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
ps = ps->link;
|
ps = ps->link;
|
||||||
@ -303,35 +328,69 @@ namespace cw
|
|||||||
for(unsigned i = 0; i<p->setN; ++i,ps=ps->link)
|
for(unsigned i = 0; i<p->setN; ++i,ps=ps->link)
|
||||||
{
|
{
|
||||||
assert(ps != nullptr);
|
assert(ps != nullptr);
|
||||||
|
|
||||||
section_t* section = nullptr;
|
section_t* section = nullptr;
|
||||||
set_t* set = p->setA + i;
|
set_t* set = p->setA + i;
|
||||||
|
unsigned evtIdx0 = kInvalidIdx;
|
||||||
|
unsigned oLocId0 = kInvalidIdx;
|
||||||
|
|
||||||
set->id = ps->id;
|
set->id = ps->id;
|
||||||
set->varId = ps->varTypeId;
|
set->varId = ps->varTypeId;
|
||||||
|
|
||||||
// fill in the events belonging to this list
|
// fill in the events belonging to this set
|
||||||
set->eleCnt = ps->eventN;
|
set->evtCnt = ps->eventN;
|
||||||
set->eleArray = mem::allocZ<event_t*>(set->eleCnt);
|
set->evtArray = mem::allocZ<event_t*>(set->evtCnt);
|
||||||
for(unsigned j=0; j<set->eleCnt; ++j)
|
for(unsigned j=0; j<set->evtCnt; ++j)
|
||||||
{
|
{
|
||||||
set->eleArray[j] = _hash_to_event(p, ps->eventA[j]->hash );
|
event_t* e = nullptr;
|
||||||
|
unsigned k = 0;
|
||||||
|
|
||||||
if( set->eleArray[j] == nullptr )
|
// locate the jth event
|
||||||
|
if((e = _hash_to_event(p, ps->eventA[j]->hash )) == nullptr )
|
||||||
{
|
{
|
||||||
rc = cwLogError(kInvalidStateRC,"The '%s' set event in measure:%i with hash %x (CSV Row:%i) could not be found.",score_parse::var_index_to_char(ps->varTypeId),ps->eventA[j]->barNumb,ps->eventA[j]->hash,ps->eventA[j]->csvRowNumb);
|
rc = cwLogError(kInvalidStateRC,"The '%s' set event in measure:%i with hash %x (CSV Row:%i) could not be found.",score_parse::var_index_to_char(ps->varTypeId),ps->eventA[j]->barNumb,ps->eventA[j]->hash,ps->eventA[j]->csvRowNumb);
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the set events must be in time order
|
||||||
|
if( evtIdx0!=kInvalidIdx && e->index < evtIdx0 )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidStateRC,"The '%s' set event in measure:%i with hash %x (CSV Row:%i) is out of time order.",score_parse::var_index_to_char(ps->varTypeId),ps->eventA[j]->barNumb,ps->eventA[j]->hash,ps->eventA[j]->csvRowNumb);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
evtIdx0 = e->index;
|
||||||
|
|
||||||
|
// Track the count of locations used by this set.
|
||||||
|
if( oLocId0==kInvalidIdx || e->oLocId != oLocId0 )
|
||||||
|
set->locN += 1;
|
||||||
|
oLocId0 = e->oLocId;
|
||||||
|
|
||||||
|
set->evtArray[j] = e;
|
||||||
|
|
||||||
|
// set the set pointer on this event to point back to this set
|
||||||
|
for(k=0; k<e->varN; ++k)
|
||||||
|
if( e->varA[k].varId == set->varId )
|
||||||
|
{
|
||||||
|
e->varA[k].set = set;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( k == e->varN )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidStateRC,"The event set slots at location '%i' (CSV row:%i) was not found for var type:%i.",e->oLocId,e->csvRowNumb,set->varId);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add this set to the setList for the set's end loc
|
// add this set to the setList for the set's end loc
|
||||||
if( set->eleCnt > 0 )
|
if( set->evtCnt > 0 )
|
||||||
{
|
{
|
||||||
loc_t* end_loc = p->locA + set->eleArray[set->eleCnt-1]->locIdx;
|
loc_t* end_loc = p->locA + set->evtArray[set->evtCnt-1]->oLocId;
|
||||||
set->llink = end_loc->setList;
|
set->llink = end_loc->setList;
|
||||||
end_loc->setList = set;
|
end_loc->setList = set;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the target-section related fields fro this set
|
// set the target-section related fields for this set
|
||||||
if( ps->targetSection != nullptr )
|
if( ps->targetSection != nullptr )
|
||||||
{
|
{
|
||||||
if((section = _label_to_section(p,ps->targetSection->label)) == nullptr )
|
if((section = _label_to_section(p,ps->targetSection->label)) == nullptr )
|
||||||
@ -348,6 +407,16 @@ namespace cw
|
|||||||
section->setArray = mem::resizeZ(section->setArray,section->setCnt);
|
section->setArray = mem::resizeZ(section->setArray,section->setCnt);
|
||||||
section->setArray[ section->setCnt-1 ] = set;
|
section->setArray[ section->setCnt-1 ] = set;
|
||||||
|
|
||||||
|
|
||||||
|
if( set->evtCnt>0 )
|
||||||
|
{
|
||||||
|
// track the location of the last event in the last set that is applied to this section
|
||||||
|
unsigned oLocId = set->evtArray[ set->evtCnt-1 ]->oLocId;
|
||||||
|
|
||||||
|
if( section->measLocPtr == nullptr || oLocId > section->measLocPtr->index )
|
||||||
|
section->measLocPtr = p->locA + oLocId;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,9 +424,327 @@ namespace cw
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc_t _set_tempo( sfscore_t* p )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
const score_parse::event_t* eventA = event_array(p->parserH);
|
||||||
|
unsigned eventN = event_count(p->parserH);
|
||||||
|
|
||||||
|
// Get the min BPM
|
||||||
|
auto min_evt = std::min_element(eventA,eventA+eventN,[](auto& x0, auto& x1){ return x0.bpm<x1.bpm; });
|
||||||
|
|
||||||
|
cwLogInfo("min tempo:%i at CSV row:%i\n",min_evt->bpm,min_evt->csvRowNumb);
|
||||||
|
|
||||||
|
if( min_evt->bpm == 0 )
|
||||||
|
{
|
||||||
|
cwLogError(kInvalidArgRC,"The minimum tempo must be greater than zero.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set event.relTempo
|
||||||
|
std::for_each(p->eventA, p->eventA+p->eventN, [min_evt](auto& x){ x.relTempo=(double)x.bpm / min_evt->bpm; } );
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _validate_dyn_set( sfscore_t* p, const set_t* set )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
for(event_t* const * ee=set->evtArray; ee<set->evtArray+set->evtCnt; ++ee)
|
||||||
|
{
|
||||||
|
assert( ee != nullptr && *ee != nullptr );
|
||||||
|
const event_t* e = *ee;
|
||||||
|
if( e->dynLevel == kInvalidIdx )
|
||||||
|
rc = cwLogError(kInvalidArgRC,"No dynamic level has been assigned to the note (%) at score loc:%i CSV row:%i.",e->oLocId,e->csvRowNumb);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a list of note events calc the standard deviation of the inter-onset time between the notes.
|
||||||
|
rc_t _calc_delta_time_std_dev( unsigned locN, event_t* const* evtA, unsigned evtN, double& stdRef )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
assert( locN > 1 );
|
||||||
|
|
||||||
|
double locSecV[ locN ];
|
||||||
|
unsigned locCntV[ locN ];
|
||||||
|
unsigned evtIdxV[ evtN ];
|
||||||
|
|
||||||
|
vop::fill(locSecV,locN,0.0);
|
||||||
|
vop::fill(locCntV,locN,0);
|
||||||
|
vop::fill(evtIdxV,evtN,0);
|
||||||
|
|
||||||
|
unsigned li = 0;
|
||||||
|
for(unsigned ei=0; ei<evtN; ++ei)
|
||||||
|
{
|
||||||
|
if( ei>0 && evtA[ei]->secs != evtA[ei-1]->secs )
|
||||||
|
++li;
|
||||||
|
|
||||||
|
locSecV[li] += evtA[ei]->secs;
|
||||||
|
locCntV[li] += 1;
|
||||||
|
evtIdxV[ei] = li;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(unsigned li=0; li<locN; ++li)
|
||||||
|
locSecV[li] /= locCntV[li];
|
||||||
|
|
||||||
|
assert( li == locN-1 );
|
||||||
|
|
||||||
|
if( locN < 3 )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidStateRC,"Cannot compute delta time std-dev on sequences with less than 3 elements.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double dsum = 0;
|
||||||
|
double sum = 0;
|
||||||
|
|
||||||
|
for(unsigned i=1; i<locN; ++i)
|
||||||
|
sum += locSecV[i] - locSecV[i-1];
|
||||||
|
|
||||||
|
double mean = sum/(locN-1);
|
||||||
|
|
||||||
|
for(unsigned i=1; i<locN; ++i)
|
||||||
|
{
|
||||||
|
double d = (locSecV[i] - locSecV[i-1]) - mean;
|
||||||
|
dsum += d*d;
|
||||||
|
}
|
||||||
|
|
||||||
|
stdRef = sqrt(dsum/(locN-1));
|
||||||
|
|
||||||
|
}
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _print_even_set( sfscore_t* p, const set_t* set )
|
||||||
|
{
|
||||||
|
|
||||||
|
for(unsigned i=0; i<set->evtCnt; ++i)
|
||||||
|
{
|
||||||
|
const event_t* e = set->evtArray[i];
|
||||||
|
|
||||||
|
double dsec = -1;
|
||||||
|
if( i>0 && e->oLocId != set->evtArray[i-1]->oLocId )
|
||||||
|
dsec = e->secs - set->evtArray[i-1]->secs;
|
||||||
|
|
||||||
|
printf("%3i loc:%5i d:%6.3f f:%f %s\n",
|
||||||
|
e->barNumb,
|
||||||
|
e->oLocId,
|
||||||
|
dsec,
|
||||||
|
e->frac,
|
||||||
|
score_parse::event_array(p->parserH)[ e->parseEvtIdx ].sciPitch );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _validate_even_set( sfscore_t* p, const set_t* set, bool show_warnings_fl )
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
double std = 0;
|
||||||
|
|
||||||
|
if( set->locN < 3 )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidArgRC,"The even set id %i has less than 3 locations.",set->id);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = _calc_delta_time_std_dev(set->locN,set->evtArray,set->evtCnt,std)) != kOkRC )
|
||||||
|
{
|
||||||
|
cwLogError(rc,"Even set score time validation failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( std > 0.05 && show_warnings_fl )
|
||||||
|
{
|
||||||
|
printf("Even set periodcity out of range. set:%3i %3i : std:%6.4f\n",set->id,set->evtCnt,std);
|
||||||
|
_print_even_set(p,set);
|
||||||
|
}
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _calc_score_tempo( const set_t* set )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
// Both of these assertions should have been previously verified
|
||||||
|
// by the score validation process.
|
||||||
|
assert( set->locN >= 2 );
|
||||||
|
assert( set->evtCnt >= 0 );
|
||||||
|
|
||||||
|
bool printFl = false; //set->evtArray[0]->barNumb == 272;
|
||||||
|
|
||||||
|
double locSecV[ set->locN ];
|
||||||
|
unsigned locCntV[ set->locN ];
|
||||||
|
double locFracV[ set->locN ];
|
||||||
|
double bpmV[ set->locN-1 ];
|
||||||
|
double bpm = 0.0;
|
||||||
|
|
||||||
|
vop::fill(locSecV,set->locN,0);
|
||||||
|
vop::fill(locCntV,set->locN,0);
|
||||||
|
vop::fill(locFracV,set->locN,0);
|
||||||
|
|
||||||
|
|
||||||
|
// Calc the oneset time at each location - this involves taking the mean time of all notes that that location.
|
||||||
|
// Notes
|
||||||
|
// 1. For the score this step is not necessary because all notes will fall on exactly the same time.
|
||||||
|
// 2. It might be better to take the median rather than the mean to prevent outlier problems,
|
||||||
|
unsigned cur_loc_idx = set->evtArray[0]->oLocId;
|
||||||
|
unsigned li = 0;
|
||||||
|
for(unsigned i=0; i<set->evtCnt; ++i)
|
||||||
|
{
|
||||||
|
if( set->evtArray[i]->oLocId != cur_loc_idx )
|
||||||
|
{
|
||||||
|
cur_loc_idx = set->evtArray[i]->oLocId;
|
||||||
|
++li;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( li < set->locN);
|
||||||
|
|
||||||
|
locSecV[ li ] += set->evtArray[i]->secs;
|
||||||
|
locCntV[ li ] += 1;
|
||||||
|
|
||||||
|
//if( locFracV[li]!=0 && set->evtArray[i]->frac != locFracV[li] )
|
||||||
|
// cwLogWarning("Frac mismatch.");
|
||||||
|
|
||||||
|
locFracV[ li ] = set->evtArray[i]->bpm_rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert onset time sum to avg.
|
||||||
|
for(unsigned i=0; i<set->locN; ++i)
|
||||||
|
if( locCntV[i] != 0 )
|
||||||
|
locSecV[i] /= locCntV[i];
|
||||||
|
|
||||||
|
// Calc the BPM between each two notes in the sequence.
|
||||||
|
for(unsigned i=1; i<set->locN; ++i)
|
||||||
|
{
|
||||||
|
double d = locSecV[i] - locSecV[i-1];
|
||||||
|
double secs_per_beat = d;
|
||||||
|
bpmV[i-1] = 60.0/(secs_per_beat * locFracV[i-1]);
|
||||||
|
|
||||||
|
// bpm = 60 / (spb*x)
|
||||||
|
// bpm/(60)
|
||||||
|
// 60/(bpm*sbp) = x
|
||||||
|
double fact = 60/(set->evtArray[0]->bpm * secs_per_beat);
|
||||||
|
double est_bpm = 60.0/(secs_per_beat * fact);
|
||||||
|
|
||||||
|
if( printFl )
|
||||||
|
printf("%3i : %f : %i d:%f frac:%f spb:%f fact:%f bpm:%f %f\n",
|
||||||
|
set->id,
|
||||||
|
locSecV[i-1],
|
||||||
|
locCntV[i-1],d,
|
||||||
|
locFracV[i-1],
|
||||||
|
secs_per_beat,
|
||||||
|
fact,
|
||||||
|
est_bpm,
|
||||||
|
bpmV[i-1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// take the avg bpm as the
|
||||||
|
unsigned bpmN = 0;
|
||||||
|
for(unsigned i=0; i<set->locN-1; ++i)
|
||||||
|
if( bpmV[i] > 0 )
|
||||||
|
{
|
||||||
|
bpm += bpmV[i];
|
||||||
|
bpmN += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bpmN > 0 )
|
||||||
|
bpm /= bpmN;
|
||||||
|
|
||||||
|
if( printFl )
|
||||||
|
printf("meas:%i locN:%i BPM:%i est:%f\n",set->evtArray[0]->barNumb,set->locN,set->evtArray[0]->bpm,bpm);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _validate_tempo_set( sfscore_t* p, const set_t* set )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
if( set->locN < 2 )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidArgRC,"The tempo set id %i has less than 2 locations.",set->id);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( set->evtCnt > 0 )
|
||||||
|
{
|
||||||
|
// all events in a tempo set must share the same tempo marking
|
||||||
|
unsigned bpm = set->evtArray[0]->bpm;
|
||||||
|
|
||||||
|
// Note we do not check the tempo of the last event (i.e. i<set->evtCnt-1) because it may
|
||||||
|
// land on a tempo change. We therefore must take the tempo of the first event as the tempo
|
||||||
|
// for all successive notes.
|
||||||
|
|
||||||
|
for(unsigned i=1; i<set->evtCnt-1; ++i)
|
||||||
|
if(set->evtArray[i]->bpm != bpm )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidStateRC,"Tempo mismatch at tempo event loc:%i (CSV row:%i) in set %i",set->evtArray[i]->oLocId, set->evtArray[i]->csvRowNumb, set->id );
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_calc_score_tempo( set );
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc_t _validate_sets( sfscore_t* p, bool show_warnings_fl )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
for(const set_t* set = p->setA; set<p->setA + p->setN; ++set )
|
||||||
|
{
|
||||||
|
rc_t rc0 = kOkRC;
|
||||||
|
|
||||||
|
if( set->evtCnt==0 || set->evtArray[0]==nullptr )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidStateRC, "Set id %i of type %s has no events.",cwStringNullGuard(score_parse::var_index_to_char(set->varId)));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch( set->varId )
|
||||||
|
{
|
||||||
|
case score_parse::kDynVarIdx:
|
||||||
|
rc0 = _validate_dyn_set(p,set);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case score_parse::kEvenVarIdx:
|
||||||
|
rc0 = _validate_even_set(p,set,show_warnings_fl);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case score_parse::kTempoVarIdx:
|
||||||
|
rc0 = _validate_tempo_set(p,set);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rc0 != kOkRC )
|
||||||
|
{
|
||||||
|
cwLogError(rc0,"Validation failed on set id %i of type %s. The set starts at loc:%i (CSV row:%i).",
|
||||||
|
set->id,
|
||||||
|
cwStringNullGuard(score_parse::var_index_to_char(set->varId)),
|
||||||
|
set->evtArray[0]->oLocId,
|
||||||
|
set->evtArray[0]->csvRowNumb);
|
||||||
|
rc = rc0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
rc_t _create( handle_t& hRef,
|
rc_t _create( handle_t& hRef,
|
||||||
score_parse::handle_t spH,
|
score_parse::handle_t spH,
|
||||||
|
bool show_warnings_fl,
|
||||||
bool deleteParserH_Fl )
|
bool deleteParserH_Fl )
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
@ -382,6 +769,11 @@ namespace cw
|
|||||||
if((rc = _create_set_array( p )) != kOkRC )
|
if((rc = _create_set_array( p )) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
|
if((rc = _set_tempo(p)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
if((rc = _validate_sets(p,show_warnings_fl)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
hRef.set(p);
|
hRef.set(p);
|
||||||
|
|
||||||
@ -403,8 +795,8 @@ namespace cw
|
|||||||
const char* sec_str = "S:";
|
const char* sec_str = "S:";
|
||||||
const char* bar_str = "B:";
|
const char* bar_str = "B:";
|
||||||
|
|
||||||
printf("e idx oloc secs op sectn sdx bar bdx scip vel frac\n");
|
printf("e idx oloc secs bpm b_rval rtmpo op sectn sdx bar bdx scip vel frac g\n");
|
||||||
printf("----- ----- ------- --- ------ --- ----- --- ---- --- -----\n");
|
printf("----- ----- ------- --- ------ ----- --- ------ --- ----- --- ---- --- ----- -\n");
|
||||||
|
|
||||||
|
|
||||||
for(rpt_event_t* r=rptA; r<rptA+rptN; ++r)
|
for(rpt_event_t* r=rptA; r<rptA+rptN; ++r)
|
||||||
@ -421,10 +813,13 @@ namespace cw
|
|||||||
bar0 = e->barNumb;
|
bar0 = e->barNumb;
|
||||||
sec0 = section->label;
|
sec0 = section->label;
|
||||||
|
|
||||||
printf("%5i %5i %7.3f %3s %2s%4s %3i %2s%3i %3i %4s %3i %5.3f ",
|
printf("%5i %5i %7.3f %3i %6.4f %5.3f %3s %2s%4s %3i %2s%3i %3i %4s %3i %5.3f %c ",
|
||||||
e->index,
|
e->index,
|
||||||
e->locIdx,
|
e->oLocId,
|
||||||
e->secs,
|
e->secs,
|
||||||
|
e->bpm,
|
||||||
|
e->bpm_rval,
|
||||||
|
e->relTempo,
|
||||||
score_parse::opcode_id_to_label(e->type),
|
score_parse::opcode_id_to_label(e->type),
|
||||||
d_sec_str,
|
d_sec_str,
|
||||||
section==nullptr ? " " : cwStringNullGuard(section->label),
|
section==nullptr ? " " : cwStringNullGuard(section->label),
|
||||||
@ -434,17 +829,22 @@ namespace cw
|
|||||||
e->barNoteIdx,
|
e->barNoteIdx,
|
||||||
sciPitch,
|
sciPitch,
|
||||||
e->vel,
|
e->vel,
|
||||||
e->frac );
|
e->frac,
|
||||||
|
cwIsFlag(e->flags,score_parse::kGraceFl) ? 'g' : ' ');
|
||||||
|
|
||||||
for(unsigned vi=score_parse::kMinVarIdx; vi<score_parse::kVarCnt; ++vi)
|
// for each possible var type
|
||||||
|
for(unsigned vi=0; vi<score_parse::kVarCnt; ++vi)
|
||||||
{
|
{
|
||||||
set_t* set = r->setA[vi];
|
// locate the associated var spec in event.varA[]
|
||||||
if( set == nullptr || set->sectCnt==0 )
|
var_t* var = std::find_if( e->varA, e->varA+e->varN, [vi](const var_t& x){return x.varId==vi;});
|
||||||
|
|
||||||
|
// if this event is not a included in a set of type 'vi'
|
||||||
|
if( var >= e->varA+e->varN )
|
||||||
printf(" ");
|
printf(" ");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char* sect_label = set->sectArray[0]==nullptr ? "****" : set->sectArray[0]->label;
|
const char* sect_label = var->set->sectArray[0]==nullptr ? "****" : var->set->sectArray[0]->label;
|
||||||
printf("%s-%03i-%s ",score_parse::var_flags_to_char(e->varA[vi]), set->id, sect_label);
|
printf("%s-%03i-%s ",score_parse::var_flags_to_char(var->flags), var->set->id, sect_label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,18 +886,6 @@ namespace cw
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i=0; i<p->setN; ++i)
|
|
||||||
{
|
|
||||||
set_t* set = p->setA + i;
|
|
||||||
for(unsigned j=0; j<set->eleCnt; ++j)
|
|
||||||
{
|
|
||||||
event_t* e = set->eleArray[j];
|
|
||||||
rpt_event_t* r = rptA + e->index;
|
|
||||||
assert( r->setA[ set->varId ] == nullptr );
|
|
||||||
r->setA[ set->varId ] = set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rptA;
|
return rptA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,23 +902,23 @@ namespace cw
|
|||||||
mem::release(rptA);
|
mem::release(rptA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::sfscore::create( handle_t& hRef,
|
cw::rc_t cw::sfscore::create( handle_t& hRef,
|
||||||
score_parse::handle_t spH )
|
score_parse::handle_t spH,
|
||||||
|
bool show_warnings_fl)
|
||||||
{
|
{
|
||||||
return _create(hRef,spH,false);
|
return _create(hRef,spH,show_warnings_fl,false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::sfscore::create( handle_t& hRef,
|
cw::rc_t cw::sfscore::create( handle_t& hRef,
|
||||||
const char* fname,
|
const char* fname,
|
||||||
double srate,
|
double srate,
|
||||||
dyn_ref_tbl::handle_t dynRefH)
|
dyn_ref_tbl::handle_t dynRefH,
|
||||||
|
bool show_warnings_fl)
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
|
|
||||||
@ -542,8 +930,7 @@ cw::rc_t cw::sfscore::create( handle_t& hRef,
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = _create(hRef,spH,show_warnings_fl,true);
|
||||||
rc = _create(hRef,spH,true);
|
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
@ -570,6 +957,79 @@ cw::rc_t cw::sfscore::destroy( handle_t& hRef )
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cw::sfscore::clear_all_performance_data( handle_t h )
|
||||||
|
{
|
||||||
|
sfscore_t* p = _handleToPtr(h);
|
||||||
|
std::for_each( p->eventA, p->eventA + p->eventN, [](event_t& e){ e.perfFl=false; e.perfVel=0, e.perfSec=0, e.perfMatchCost=std::numeric_limits<double>::max(); } );
|
||||||
|
std::for_each( p->setA, p->setA + p->setN, [](set_t& s){ s.perfEventCnt=0; s.perfUpdateCnt=false; } );
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::sfscore::set_perf( handle_t h, unsigned event_idx, double secs, uint8_t pitch, uint8_t vel, double cost )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
sfscore_t* p = _handleToPtr(h);
|
||||||
|
event_t* e = p->eventA + event_idx;;
|
||||||
|
|
||||||
|
if( event_idx >= p->eventN )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidIdRC,"The performance event index %i is invalid.",event_idx);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( e->pitch != pitch )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidStateRC,"The performance event pitch %x is not a match.",pitch);
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(unsigned i=0; i<e->varN; ++i)
|
||||||
|
{
|
||||||
|
e->varA[i].set->perfUpdateCnt += 1;
|
||||||
|
|
||||||
|
if( e->perfFl == false )
|
||||||
|
{
|
||||||
|
e->varA[i].set->perfEventCnt += 1;
|
||||||
|
|
||||||
|
if( e->varA[i].set->perfEventCnt > e->varA[i].set->evtCnt )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kInvalidStateRC,"The perf. count of a set (id:%i) exeeded it's event count.", e->varA[i].set->evtCnt );
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e->perfFl = true;
|
||||||
|
e->perfVel = vel;
|
||||||
|
e->perfSec = secs;
|
||||||
|
e->perfDynLevel = dyn_ref_vel_to_level(p->parserH,vel);
|
||||||
|
e->perfMatchCost= cost;
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
if( rc != kOkRC )
|
||||||
|
rc = cwLogError(rc,"The performance score update failed.");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cw::sfscore::are_all_loc_set_events_performed( handle_t h, unsigned locId )
|
||||||
|
{
|
||||||
|
sfscore_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
|
if( locId >= p->locN )
|
||||||
|
{
|
||||||
|
cwLogError(kInvalidIdRC,"An invalid loc id %i was encountered while testing for performed events.",locId);
|
||||||
|
assert(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const loc_t* loc = p->locA + locId;
|
||||||
|
for(unsigned i=0; i<loc->evtCnt; ++i)
|
||||||
|
if( loc->evtArray[i]->varN > 0 && loc->evtArray[i]->perfFl == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double cw::sfscore::sample_rate( handle_t& h )
|
double cw::sfscore::sample_rate( handle_t& h )
|
||||||
{
|
{
|
||||||
@ -577,21 +1037,26 @@ double cw::sfscore::sample_rate( handle_t& h )
|
|||||||
return sample_rate(p->parserH);
|
return sample_rate(p->parserH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned cw::sfscore::event_count( handle_t h )
|
unsigned cw::sfscore::event_count( handle_t h )
|
||||||
{
|
{
|
||||||
sfscore_t* p = _handleToPtr(h);
|
sfscore_t* p = _handleToPtr(h);
|
||||||
return p->eventN;
|
return p->eventN;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::sfscore::event_t* cw::sfscore::event( handle_t h, unsigned idx )
|
const cw::sfscore::event_t* cw::sfscore::event( handle_t h, unsigned idx )
|
||||||
{
|
{
|
||||||
sfscore_t* p = _handleToPtr(h);
|
sfscore_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
|
if( idx > p->eventN )
|
||||||
|
{
|
||||||
|
cwLogError(kInvalidIdRC,"The event index '%i' is not valid.",idx);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return p->eventA + idx;
|
return p->eventA + idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::sfscore::event_t* cw::sfscore::hash_to_event( handle_t h, unsigned hash )
|
const cw::sfscore::event_t* cw::sfscore::hash_to_event( handle_t h, unsigned hash )
|
||||||
{
|
{
|
||||||
sfscore_t* p = _handleToPtr(h);
|
sfscore_t* p = _handleToPtr(h);
|
||||||
for(unsigned i=0; p->eventN; ++i)
|
for(unsigned i=0; p->eventN; ++i)
|
||||||
@ -600,17 +1065,40 @@ cw::sfscore::event_t* cw::sfscore::hash_to_event( handle_t h, unsigned hash )
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned cw::sfscore::loc_count( handle_t h )
|
unsigned cw::sfscore::loc_count( handle_t h )
|
||||||
{
|
{
|
||||||
sfscore_t* p = _handleToPtr(h);
|
sfscore_t* p = _handleToPtr(h);
|
||||||
return p->locN;
|
return p->locN;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::sfscore::loc_t* cw::sfscore::loc( handle_t h, unsigned idx )
|
const cw::sfscore::loc_t* cw::sfscore::loc_base( handle_t h )
|
||||||
{
|
{
|
||||||
sfscore_t* p = _handleToPtr(h);
|
sfscore_t* p = _handleToPtr(h);
|
||||||
return p->locA + idx;
|
return p->locA;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cw::sfscore::set_count( handle_t h )
|
||||||
|
{
|
||||||
|
sfscore_t* p = _handleToPtr(h);
|
||||||
|
return p->setN;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cw::sfscore::set_t* cw::sfscore::set_base( handle_t h )
|
||||||
|
{
|
||||||
|
sfscore_t* p = _handleToPtr(h);
|
||||||
|
return p->setA;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cw::sfscore::section_count( handle_t h )
|
||||||
|
{
|
||||||
|
sfscore_t* p = _handleToPtr(h);
|
||||||
|
return p->sectionN;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cw::sfscore::section_t* cw::sfscore::section_base( handle_t h )
|
||||||
|
{
|
||||||
|
sfscore_t* p = _handleToPtr(h);
|
||||||
|
return p->sectionA;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cw::sfscore::report( handle_t h, const char* out_fname )
|
void cw::sfscore::report( handle_t h, const char* out_fname )
|
||||||
@ -620,9 +1108,3 @@ void cw::sfscore::report( handle_t h, const char* out_fname )
|
|||||||
_report(p);
|
_report(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cw::sfscore::parse_report( handle_t h )
|
|
||||||
{
|
|
||||||
sfscore_t* p = _handleToPtr(h);
|
|
||||||
report(p->parserH);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
100
cwSfScore.h
100
cwSfScore.h
@ -14,35 +14,54 @@ namespace cw
|
|||||||
{
|
{
|
||||||
const char* label; // section label
|
const char* label; // section label
|
||||||
unsigned index; // index of this record in the internal section array
|
unsigned index; // index of this record in the internal section array
|
||||||
|
struct loc_str* measLocPtr; // last location of last set to be applied to this section
|
||||||
struct loc_str* locPtr; // location where this section starts
|
struct loc_str* locPtr; // location where this section starts
|
||||||
unsigned begEvtIndex; // score element index where this section starts
|
unsigned begEvtIndex; // score element index where this section starts
|
||||||
unsigned setCnt; // Count of elements in setArray[]
|
unsigned setCnt; // Count of elements in setArray[]
|
||||||
struct set_str** setArray; // Ptrs to sets which are applied to this section.
|
struct set_str** setArray; // Ptrs to sets which are applied to this section.
|
||||||
double vars[ score_parse::kVarCnt ]; // Set to DBL_MAX by default.
|
|
||||||
|
//double vars[ score_parse::kVarCnt ]; // Set to DBL_MAX by default.
|
||||||
} section_t;
|
} section_t;
|
||||||
|
|
||||||
|
typedef struct var_str
|
||||||
|
{
|
||||||
|
unsigned flags;
|
||||||
|
unsigned varId;
|
||||||
|
struct set_str* set;
|
||||||
|
} var_t;
|
||||||
|
|
||||||
typedef struct event_str
|
typedef struct event_str
|
||||||
{
|
{
|
||||||
unsigned type; // See score_parse ???TId
|
unsigned type; // See score_parse ???TId
|
||||||
double secs; // Time location in seconds
|
double secs; // Time location in seconds
|
||||||
double durSecs; // Duration in seconds
|
double durSecs; // Duration in seconds
|
||||||
unsigned index; // Index of this event in the event array.
|
unsigned index; // Index of this event in the event array.
|
||||||
unsigned locIdx; // Index of the onset location (oloc) containing this event
|
unsigned oLocId; // Index of the onset location (oloc) containing this event
|
||||||
midi::byte_t pitch; // MIDI pitch of this note or the MIDI pedal id of pedal down/up msg (64=sustain 65=sostenuto 66=soft)
|
midi::byte_t pitch; // MIDI pitch of this note or the MIDI pedal id of pedal down/up msg (64=sustain 65=sostenuto 66=soft)
|
||||||
midi::byte_t vel; // MIDI velocity of this note
|
midi::byte_t vel; // MIDI velocity of this note
|
||||||
unsigned flags; // Attribute flags for this event
|
unsigned flags; // Attribute flags for this event
|
||||||
unsigned dynVal; // Dynamcis value pppp to ffff (1 to 11) for this note.
|
unsigned dynLevel; // Dynamcis value pppp to ffff (1 to 11) for this note.
|
||||||
double frac; // Note's time value for tempo and non-grace evenness notes.
|
double frac; // Note's time value for tempo and non-grace evenness notes.
|
||||||
unsigned barNumb; // Bar id of the measure containing this event.
|
unsigned barNumb; // Bar id of the measure containing this event.
|
||||||
unsigned barNoteIdx; // Index of this note in this bar
|
unsigned barNoteIdx; // Index of this note in this bar
|
||||||
unsigned csvRowNumb; // File row number (not index) from which this record originated
|
unsigned csvRowNumb; // File row number (not index) from which this record originated
|
||||||
unsigned perfSmpIdx; // Time this event was performed or cmInvalidIdx if the event was not performed.
|
|
||||||
unsigned perfVel; // Velocity of the performed note or 0 if the note was not performed.
|
|
||||||
unsigned perfDynLvl; // Index into dynamic level ref. array assoc'd with perfVel
|
|
||||||
unsigned line; // Line number of this event in the score file.
|
unsigned line; // Line number of this event in the score file.
|
||||||
unsigned csvEventId; // EventId from CSV 'evt' column.
|
unsigned parseEvtIdx; // Index of event from score_parse event index.
|
||||||
unsigned hash; // unique hash id for this note
|
unsigned hash; // unique hash id for this note
|
||||||
unsigned varA[ score_parse::kVarCnt ];
|
|
||||||
|
var_t* varA; // varA[varN] set's this event belongs to
|
||||||
|
unsigned varN; // Length of varA[]
|
||||||
|
|
||||||
|
unsigned bpm; // beats per minute
|
||||||
|
double bpm_rval;
|
||||||
|
double relTempo; // relative tempo (1=min tempo)
|
||||||
|
|
||||||
|
bool perfFl; // has this event been performed
|
||||||
|
double perfSec; // performance event time
|
||||||
|
uint8_t perfVel; // performance event velocity
|
||||||
|
unsigned perfDynLevel; // performance dynamic level
|
||||||
|
double perfMatchCost; // performance match cost (or DBL_MAX if not valid)
|
||||||
|
|
||||||
} event_t;
|
} event_t;
|
||||||
|
|
||||||
// A 'set' is a collection of events that are grouped in time and all marked with a given attribute.
|
// A 'set' is a collection of events that are grouped in time and all marked with a given attribute.
|
||||||
@ -50,50 +69,29 @@ namespace cw
|
|||||||
typedef struct set_str
|
typedef struct set_str
|
||||||
{
|
{
|
||||||
unsigned id; // Unique id for this set
|
unsigned id; // Unique id for this set
|
||||||
unsigned varId; // See kXXXVarScId flags above
|
unsigned varId; // See score_parse::k???VarIdx
|
||||||
event_t** eleArray; // Events that make up this set in time order
|
event_t** evtArray; // Events that make up this set in time order
|
||||||
unsigned eleCnt; //
|
unsigned evtCnt; //
|
||||||
|
unsigned locN; // count of locations coverted by this set
|
||||||
section_t** sectArray; // Sections this set will be applied to
|
section_t** sectArray; // Sections this set will be applied to
|
||||||
unsigned sectCnt; //
|
unsigned sectCnt; //
|
||||||
unsigned* symArray; // symArray[sectCnt] - symbol name of all variables represented by this set (e.g '1a-e', '1b-e', '2-t', etc)
|
|
||||||
unsigned* costSymArray; // costSymArray[sectCnt] - same as symbols in symArray[] with 'c' prepended to front
|
|
||||||
bool doneFl;
|
|
||||||
double value;
|
|
||||||
struct set_str* llink; // loc_t setList link
|
struct set_str* llink; // loc_t setList link
|
||||||
|
|
||||||
|
unsigned perfEventCnt; // count of events in this set that have been performed (never greater than eleCnt)
|
||||||
|
unsigned perfUpdateCnt; // count of event updates this has received (incr'd every time a event is performed - may be greater than eleCnt)
|
||||||
} set_t;
|
} set_t;
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
kInvalidScMId,
|
|
||||||
kRecdBegScMId,
|
|
||||||
kRecdEndScMId,
|
|
||||||
kFadeScMId,
|
|
||||||
kPlayBegScMId,
|
|
||||||
kPlayEndScMId
|
|
||||||
} markerId_t;
|
|
||||||
|
|
||||||
// score markers
|
|
||||||
typedef struct marker_str
|
|
||||||
{
|
|
||||||
markerId_t markTypeId; // marker type
|
|
||||||
unsigned labelSymId; // marker label
|
|
||||||
struct loc_str* scoreLocPtr; // score location of the marker
|
|
||||||
unsigned csvRowIdx; // score CSV file line assoc'd w/ this marker
|
|
||||||
struct marker_str* link; // loc_t.markList links
|
|
||||||
} marker_t;
|
|
||||||
|
|
||||||
// All events which are simultaneous are collected into a single
|
// All events which are simultaneous are collected into a single
|
||||||
// locc_t record.
|
// locc_t record.
|
||||||
typedef struct loc_str
|
typedef struct loc_str
|
||||||
{
|
{
|
||||||
unsigned index; // index of this location record
|
unsigned index; // oloc id and index of this location record
|
||||||
double secs; // Time of this location
|
double secs; // Time of this location
|
||||||
unsigned evtCnt; // Count of events in evtArray[].
|
unsigned evtCnt; // Count of events in evtArray[].
|
||||||
event_t** evtArray; // Events which occur at this time.
|
event_t** evtArray; // Events which occur at this time.
|
||||||
unsigned barNumb; // Bar number this event is contained by.
|
unsigned barNumb; // Bar number this event is contained by.
|
||||||
set_t* setList; // Set's which end on this time location (linked through set_t.llink)
|
set_t* setList; // Set's which end on this time location (linked through set_t.llink)
|
||||||
section_t* begSectPtr; // NULL if this location does not start a section
|
section_t* begSectPtr; // NULL if this location does not start a section
|
||||||
marker_t* markList; // List of markers assigned to this location
|
|
||||||
} loc_t;
|
} loc_t;
|
||||||
|
|
||||||
typedef dyn_ref_tbl::dyn_ref_t dyn_ref_t;
|
typedef dyn_ref_tbl::dyn_ref_t dyn_ref_t;
|
||||||
@ -101,29 +99,45 @@ namespace cw
|
|||||||
|
|
||||||
// Create the score from a provided score parser
|
// Create the score from a provided score parser
|
||||||
rc_t create( handle_t& h,
|
rc_t create( handle_t& h,
|
||||||
score_parse::handle_t spH );
|
score_parse::handle_t spH,
|
||||||
|
bool show_warnings_fl = false);
|
||||||
|
|
||||||
// Create an internal score parser.
|
// Create an internal score parser.
|
||||||
rc_t create( handle_t& h,
|
rc_t create( handle_t& h,
|
||||||
const char* fname,
|
const char* fname,
|
||||||
double srate,
|
double srate,
|
||||||
dyn_ref_tbl::handle_t dynRefH);
|
dyn_ref_tbl::handle_t dynRefH,
|
||||||
|
bool show_warnings_fl = false);
|
||||||
|
|
||||||
|
|
||||||
rc_t destroy( handle_t& h );
|
rc_t destroy( handle_t& h );
|
||||||
|
|
||||||
|
|
||||||
|
void clear_all_performance_data( handle_t h );
|
||||||
|
rc_t set_perf( handle_t h, unsigned event_idx, double secs, uint8_t pitch, uint8_t vel, double cost );
|
||||||
|
|
||||||
|
// Return true if all events that are assigned to a set performed at the given location.
|
||||||
|
bool are_all_loc_set_events_performed( handle_t h, unsigned locId );
|
||||||
|
|
||||||
|
|
||||||
double sample_rate( handle_t& h );
|
double sample_rate( handle_t& h );
|
||||||
|
|
||||||
unsigned event_count( handle_t h );
|
unsigned event_count( handle_t h );
|
||||||
event_t* event( handle_t h, unsigned idx );
|
const event_t* event( handle_t h, unsigned idx );
|
||||||
event_t* hash_to_event( handle_t h, unsigned hash );
|
|
||||||
|
const event_t* hash_to_event( handle_t h, unsigned hash );
|
||||||
|
|
||||||
unsigned loc_count( handle_t h );
|
unsigned loc_count( handle_t h );
|
||||||
loc_t* loc( handle_t h, unsigned idx );
|
const loc_t* loc_base( handle_t h );
|
||||||
|
|
||||||
|
unsigned set_count( handle_t h );
|
||||||
|
const set_t* set_base( handle_t h );
|
||||||
|
|
||||||
|
unsigned section_count( handle_t h );
|
||||||
|
const section_t* section_base( handle_t h );
|
||||||
|
|
||||||
|
|
||||||
void report( handle_t h, const char* out_fname=nullptr );
|
void report( handle_t h, const char* out_fname=nullptr );
|
||||||
void parse_report( handle_t h );
|
|
||||||
|
|
||||||
// see score_test::test() for testing this object
|
// see score_test::test() for testing this object
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user