Merge branch 'master' of gitea.larke.org:kevin/libcw
This commit is contained in:
commit
4ab72761e7
@ -13,10 +13,10 @@ namespace cw
|
|||||||
{
|
{
|
||||||
typedef struct dyn_ref_tbl_str
|
typedef struct dyn_ref_tbl_str
|
||||||
{
|
{
|
||||||
dyn_ref_t* dynRefA;
|
dyn_ref_t* dynRefA; // dynRefA[ dynRefN ] one entry per dyn. level
|
||||||
unsigned dynRefN;
|
unsigned dynRefN; //
|
||||||
unsigned* levelLookupA;
|
unsigned* levelLookupA; // levelLoopA[ levelLookupN ] - one entry per velocity value (0-127)
|
||||||
unsigned levelLookupN;
|
unsigned levelLookupN; // levelLooupN = kMidiVelCnt
|
||||||
|
|
||||||
} dyn_ref_tbl_t;
|
} dyn_ref_tbl_t;
|
||||||
|
|
||||||
@ -31,6 +31,7 @@ namespace cw
|
|||||||
|
|
||||||
std::for_each(p->dynRefA, p->dynRefA+p->dynRefN, relse );
|
std::for_each(p->dynRefA, p->dynRefA+p->dynRefN, relse );
|
||||||
mem::release(p->dynRefA);
|
mem::release(p->dynRefA);
|
||||||
|
mem::release(p->levelLookupA);
|
||||||
mem::release(p);
|
mem::release(p);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -39,13 +40,15 @@ namespace cw
|
|||||||
{
|
{
|
||||||
|
|
||||||
for(midi::byte_t vel=0; vel<midi::kMidiVelCnt; ++vel)
|
for(midi::byte_t vel=0; vel<midi::kMidiVelCnt; ++vel)
|
||||||
for(unsigned i=0; i<p->levelLookupN; ++i)
|
for(unsigned i=0; i<p->dynRefN; ++i)
|
||||||
if( p->dynRefA[i].velocity >= vel )
|
if( p->dynRefA[i].velocity >= vel )
|
||||||
{
|
{
|
||||||
midi::byte_t d0 = p->dynRefA[i].velocity - vel;
|
midi::byte_t d0 = p->dynRefA[i].velocity - vel;
|
||||||
midi::byte_t d1 = i>0 ? (vel - p->dynRefA[i-1].velocity) : d0;
|
midi::byte_t d1 = i>0 ? (vel - p->dynRefA[i-1].velocity) : d0;
|
||||||
unsigned j = d0 <= d1 ? i : i-1;
|
unsigned j = d0 <= d1 ? i : i-1;
|
||||||
|
|
||||||
|
assert( vel <= p->levelLookupN );
|
||||||
|
|
||||||
p->levelLookupA[vel] = p->dynRefA[j].level;
|
p->levelLookupA[vel] = p->dynRefA[j].level;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -746,10 +746,10 @@ cw::object_t* cw::newObject( const char* v, object_t* parent)
|
|||||||
{ return _objCreateValueNode<const char*>( parent, v ); }
|
{ return _objCreateValueNode<const char*>( parent, v ); }
|
||||||
|
|
||||||
cw::object_t* cw::newDictObject( object_t* parent )
|
cw::object_t* cw::newDictObject( object_t* parent )
|
||||||
{ return _objAllocate( kDictTId, parent); }
|
{ return _objAppendRightMostNode(parent, _objAllocate( kDictTId, parent) ); }
|
||||||
|
|
||||||
cw::object_t* cw::newListObject( object_t* parent )
|
cw::object_t* cw::newListObject( object_t* parent )
|
||||||
{ return _objAllocate( kListTId, parent ); }
|
{ return _objAppendRightMostNode(parent, _objAllocate( kListTId, parent) ); }
|
||||||
|
|
||||||
cw::object_t* cw::newPairObject( const char* label, object_t* value, object_t* parent)
|
cw::object_t* cw::newPairObject( const char* label, object_t* value, object_t* parent)
|
||||||
{
|
{
|
||||||
|
37
cwObject.h
37
cwObject.h
@ -88,6 +88,9 @@ namespace cw
|
|||||||
} objType_t;
|
} objType_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct object_str* newPairObject( const char* label, struct object_str* v, struct object_str* parent );
|
||||||
|
struct object_str* newListObject( struct object_str* parent );
|
||||||
|
|
||||||
typedef struct object_str
|
typedef struct object_str
|
||||||
{
|
{
|
||||||
objType_t* type = nullptr;
|
objType_t* type = nullptr;
|
||||||
@ -246,6 +249,40 @@ namespace cw
|
|||||||
{ return newPairObject(label, v, this); }
|
{ return newPairObject(label, v, this); }
|
||||||
|
|
||||||
|
|
||||||
|
rc_t _putv() { return kOkRC; }
|
||||||
|
|
||||||
|
// getv("label0",v0,"label1",v1, ... )
|
||||||
|
template< typename T0, typename T1, typename... ARGS >
|
||||||
|
rc_t _putv( T0 label, const T1& val, ARGS&&... args )
|
||||||
|
{
|
||||||
|
|
||||||
|
insert_pair(label,val);
|
||||||
|
|
||||||
|
_putv(std::forward<ARGS>(args)...); // ... recurse to find next label/value pair
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// getv("label0",v0,"label1",v1, ... )
|
||||||
|
template< typename T0, typename T1, typename... ARGS >
|
||||||
|
rc_t putv( T0 label, const T1& val, ARGS&&... args )
|
||||||
|
{ return _putv(label,val,args...); }
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
struct object_str* put_numeric_list( const char* label, const T* v, unsigned vN )
|
||||||
|
{
|
||||||
|
struct object_str* pair = newPairObject(label,newListObject(nullptr),this)->parent;
|
||||||
|
struct object_str* list = pair->pair_value();
|
||||||
|
for(unsigned i=0; i<vN; ++i)
|
||||||
|
newObject(v[i],list);
|
||||||
|
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template< typename T>
|
template< typename T>
|
||||||
rc_t set( const char* label, const T& value )
|
rc_t set( const char* label, const T& value )
|
||||||
{
|
{
|
||||||
|
454
cwPerfMeas.cpp
454
cwPerfMeas.cpp
@ -3,6 +3,7 @@
|
|||||||
#include "cwCommonImpl.h"
|
#include "cwCommonImpl.h"
|
||||||
#include "cwMem.h"
|
#include "cwMem.h"
|
||||||
#include "cwText.h"
|
#include "cwText.h"
|
||||||
|
#include "cwFile.h"
|
||||||
#include "cwObject.h"
|
#include "cwObject.h"
|
||||||
#include "cwMidi.h"
|
#include "cwMidi.h"
|
||||||
#include "cwDynRefTbl.h"
|
#include "cwDynRefTbl.h"
|
||||||
@ -35,30 +36,49 @@ namespace cw
|
|||||||
struct calc_str;
|
struct calc_str;
|
||||||
|
|
||||||
typedef struct section_str
|
typedef struct section_str
|
||||||
{
|
{
|
||||||
|
|
||||||
const struct section_str* prev_section; // section prior to this section
|
const struct section_str* prev_section; // section prior to this section
|
||||||
const sfscore::section_t* section; // score section this section_t represents
|
const sfscore::section_t* section; // score section this section_t represents
|
||||||
struct calc_str* calc; // calc record for this section
|
struct calc_str* calc; // calc record for this section
|
||||||
bool triggeredFl; // This section has already been triggered
|
bool triggeredFl; // This section has already been triggered
|
||||||
} section_t;
|
} section_t;
|
||||||
|
|
||||||
|
typedef struct meas_info_str
|
||||||
|
{
|
||||||
|
unsigned missEvtN; // count of skipped events
|
||||||
|
unsigned missLocN; // count of missed locations
|
||||||
|
unsigned transposeLocN; // count of transposed locations
|
||||||
|
unsigned interpLocN; // count of interpolated locations
|
||||||
|
|
||||||
|
unsigned vN; // vN=locN for even,tempo vN=evtN for dyn
|
||||||
|
|
||||||
|
double* locSecV; // locSecV[vN]
|
||||||
|
unsigned* locSecNV; // locSecNV[vN] count of performed and interpolated notes (interpolated notes will have a False in the associated statusV[] location)
|
||||||
|
double* dSecV; // dSecV[vN]
|
||||||
|
bool* statusV; // statusV[vN] - true if this location was performed by at least one note
|
||||||
|
struct meas_info_str* link;
|
||||||
|
} meas_info_t;
|
||||||
|
|
||||||
|
struct loc_str;
|
||||||
|
|
||||||
typedef struct set_str
|
typedef struct set_str
|
||||||
{
|
{
|
||||||
const sfscore::set_t* set; // score set this set_t represents
|
struct loc_str* loc; // end location for this set
|
||||||
|
const sfscore::set_t* set; // score set this set_t represents
|
||||||
|
meas_info_t* meas_info; //
|
||||||
unsigned lastPerfUpdateCnt;
|
unsigned lastPerfUpdateCnt;
|
||||||
double value; // The value associated with this set. DBL_MAX on initialization
|
double value; // The value associated with this set. DBL_MAX on initialization
|
||||||
struct calc_str* calc; // calc record to which this set belongs
|
struct calc_str* calc; // calc record to which this set belongs
|
||||||
struct set_str* alink; // perf_meas_t* links
|
struct set_str* alink; // perf_meas_t* links
|
||||||
struct set_str* slink; // loc_t.setL links
|
struct set_str* slink; // loc_t.setL links
|
||||||
struct set_str* clink; // calc_t.setL links
|
struct set_str* clink; // calc_t.setL links
|
||||||
} set_t;
|
} set_t;
|
||||||
|
|
||||||
// The 'calc_t' record hold pointers to all the sets assigned to a given section.
|
// The 'calc_t' record hold pointers to all the sets assigned to a given section.
|
||||||
// The record is different from a section record because it has a location assignment
|
// The record is different from a section record because it has a location assignment
|
||||||
// prior to the section which it is represents. This allows all the sets for
|
// prior to the section which it is represents. This allows all the sets for
|
||||||
// a given section to be evaluated prior to the section being triggered.
|
// a given section to be evaluated prior to the section being triggered.
|
||||||
// The 'calc' record is assigned to the location of the last event in it's latest set.
|
// The 'calc' record is assigned to the location of the last event in it's last set.
|
||||||
typedef struct calc_str
|
typedef struct calc_str
|
||||||
{
|
{
|
||||||
set_t* setL; // list of sets that this calc is applied to (links via set_t.clink)
|
set_t* setL; // list of sets that this calc is applied to (links via set_t.clink)
|
||||||
@ -66,7 +86,7 @@ namespace cw
|
|||||||
double value[ kValCnt ]; // Aggregate var values for this section
|
double value[ kValCnt ]; // Aggregate var values for this section
|
||||||
} calc_t;
|
} calc_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct loc_str
|
||||||
{
|
{
|
||||||
unsigned locId; // oloc location id and the index of this record into p->locA[]
|
unsigned locId; // oloc location id and the index of this record into p->locA[]
|
||||||
section_t* section; // section that begins on this location
|
section_t* section; // section that begins on this location
|
||||||
@ -104,6 +124,22 @@ namespace cw
|
|||||||
|
|
||||||
return locId;
|
return locId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _destroy_meas_info_records( set_t* set )
|
||||||
|
{
|
||||||
|
meas_info_t* m = set->meas_info;
|
||||||
|
while( m!=nullptr )
|
||||||
|
{
|
||||||
|
meas_info_t* m0 = m->link;
|
||||||
|
mem::release(m->locSecV);
|
||||||
|
mem::release(m->locSecNV);
|
||||||
|
mem::release(m->dSecV);
|
||||||
|
mem::release(m->statusV);
|
||||||
|
mem::release(m);
|
||||||
|
m = m0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
rc_t _destroy( perf_meas_t* p )
|
rc_t _destroy( perf_meas_t* p )
|
||||||
{
|
{
|
||||||
@ -115,6 +151,9 @@ namespace cw
|
|||||||
while(s!=nullptr)
|
while(s!=nullptr)
|
||||||
{
|
{
|
||||||
set_t* s0 = s->slink;
|
set_t* s0 = s->slink;
|
||||||
|
|
||||||
|
_destroy_meas_info_records(s);
|
||||||
|
|
||||||
mem::release(s);
|
mem::release(s);
|
||||||
s = s0;
|
s = s0;
|
||||||
}
|
}
|
||||||
@ -137,6 +176,29 @@ namespace cw
|
|||||||
cwLogError(kInvalidIdRC,"The setId '%i' is not valid.", setId );
|
cwLogError(kInvalidIdRC,"The setId '%i' is not valid.", setId );
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meas_info_t* _create_meas_info_record( set_t* set )
|
||||||
|
{
|
||||||
|
meas_info_t* m = mem::allocZ<meas_info_t>();
|
||||||
|
m->vN = set->set->varId==score_parse::kDynVarIdx ? set->set->evtCnt : set->set->locN;
|
||||||
|
m->locSecV = mem::allocZ<double>( m->vN );
|
||||||
|
m->locSecNV = mem::allocZ<unsigned>( m->vN );
|
||||||
|
m->dSecV = mem::allocZ<double>( m->vN );
|
||||||
|
m->statusV = mem::allocZ<bool>( m->vN );
|
||||||
|
|
||||||
|
if( set->meas_info == nullptr )
|
||||||
|
set->meas_info = m;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meas_info_t* m0 = set->meas_info;
|
||||||
|
while( m0->link != nullptr )
|
||||||
|
m0 = m0->link;
|
||||||
|
|
||||||
|
m0->link = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
calc_t* _create_calc_record( perf_meas_t* p, sfscore::section_t* section )
|
calc_t* _create_calc_record( perf_meas_t* p, sfscore::section_t* section )
|
||||||
{
|
{
|
||||||
@ -259,24 +321,28 @@ namespace cw
|
|||||||
const sfscore::event_t* e = set->set->evtArray[i];
|
const sfscore::event_t* e = set->set->evtArray[i];
|
||||||
if( e->perfFl )
|
if( e->perfFl )
|
||||||
{
|
{
|
||||||
double d = e->dynLevel>e->perfDynLevel ? e->dynLevel - e->perfDynLevel : e->perfDynLevel - e->dynLevel;
|
sum += e->dynLevel>e->perfDynLevel ? e->dynLevel - e->perfDynLevel : e->perfDynLevel - e->dynLevel;
|
||||||
sum += d * d;
|
|
||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set->value = n==0 ? 0 : sqrt(sum/n);
|
set->value = n==0 ? 0 : sum/n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calc chord onset time as the avg. onset over of all notes in the chord.
|
// Calc chord onset time as the avg. onset over of all notes in the chord.
|
||||||
rc_t _calc_loc_sec( const sfscore::set_t* set, double* locV, unsigned* locNV, unsigned& evtSkipN_Ref )
|
rc_t _calc_loc_sec( set_t* pm_set )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
evtSkipN_Ref = 0;
|
const sfscore::set_t* set = pm_set->set;
|
||||||
|
meas_info_t* m = pm_set->meas_info;
|
||||||
|
|
||||||
vop::zero(locV, set->locN);
|
m->missEvtN = 0;
|
||||||
vop::zero(locNV, set->locN);
|
|
||||||
|
assert( set->locN == m->vN );
|
||||||
|
|
||||||
|
vop::zero(m->locSecV, set->locN);
|
||||||
|
vop::zero(m->locSecNV, set->locN);
|
||||||
|
|
||||||
// Get the time for each location by taking the mean
|
// Get the time for each location by taking the mean
|
||||||
// of all events on the same location.
|
// of all events on the same location.
|
||||||
@ -287,7 +353,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
if( !set->evtArray[i]->perfFl )
|
if( !set->evtArray[i]->perfFl )
|
||||||
{
|
{
|
||||||
++evtSkipN_Ref;
|
++m->missEvtN;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -303,94 +369,105 @@ namespace cw
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
locV[ li] += set->evtArray[i]->perfSec;
|
m->locSecV[ li] += set->evtArray[i]->perfSec;
|
||||||
locNV[li] += 1;
|
m->locSecNV[li] += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calc. mean.
|
// Calc. mean.
|
||||||
for(unsigned i=0; i<set->locN; ++i)
|
for(unsigned i=0; i<set->locN; ++i)
|
||||||
if( locNV[i] > 0 )
|
if( m->locSecNV[i] > 0 )
|
||||||
locV[i] /= locNV[i];
|
m->locSecV[i] /= m->locSecNV[i];
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _interpolate_time_of_missing_notes( perf_meas_t* p, const sfscore::set_t* set, double* locV, unsigned* locNV, bool* statusV, unsigned& bi_ref, unsigned& ei_ref, unsigned& insertN_ref )
|
void _interpolate_time_of_missing_notes( perf_meas_t* p, set_t* pm_set, unsigned& bi_ref, unsigned& ei_ref )
|
||||||
{
|
{
|
||||||
bi_ref = kInvalidIdx;
|
bi_ref = kInvalidIdx;
|
||||||
ei_ref = kInvalidIdx;
|
ei_ref = kInvalidIdx;
|
||||||
insertN_ref = 0;
|
|
||||||
|
|
||||||
|
const sfscore::set_t* set = pm_set->set;
|
||||||
|
meas_info_t* m = pm_set->meas_info;
|
||||||
unsigned missN = 0;
|
unsigned missN = 0;
|
||||||
unsigned ei = kInvalidIdx;
|
unsigned ei = kInvalidIdx;
|
||||||
unsigned bi = kInvalidIdx;
|
unsigned bi = kInvalidIdx;
|
||||||
|
|
||||||
|
assert( set->locN == m->vN );
|
||||||
|
|
||||||
vop::fill(statusV, set->locN, false);
|
vop::fill(m->statusV, set->locN, false);
|
||||||
|
|
||||||
// for each location
|
// for each location
|
||||||
for(unsigned i=0; i<set->locN; ++i)
|
for(unsigned i=0; i<set->locN; ++i)
|
||||||
{
|
{
|
||||||
// if this location was missed or out of time order
|
// if this location was missed
|
||||||
if( locNV[i] == 0 || (ei != kInvalidIdx && (locV[i]-locV[ei])<0) )
|
if( m->locSecNV[i] == 0 )
|
||||||
{
|
{
|
||||||
missN += 1;
|
missN += 1;
|
||||||
|
m->missLocN += 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// if there are unplayed notes between this note
|
|
||||||
// and the last played note at 'ei' then
|
|
||||||
// fill in the missing note times by splitting
|
|
||||||
// the gap time evenly - note that this will
|
|
||||||
// bias the evenness std to be lower than it
|
|
||||||
// should be.
|
|
||||||
if( missN > 0 && ei!=kInvalidIdx )
|
|
||||||
{
|
|
||||||
double dsec = (locV[i] - locV[ei])/(missN+1);
|
|
||||||
for(unsigned j=ei+1; j<i; ++j)
|
|
||||||
{
|
|
||||||
locV[j] = locV[j-1] + dsec;
|
|
||||||
insertN_ref += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( bi == kInvalidIdx )
|
// if this location was not in time order
|
||||||
bi = i;
|
if( ei != kInvalidIdx && (m->locSecV[i]-m->locSecV[ei])<0 )
|
||||||
|
{
|
||||||
|
missN += 1;
|
||||||
|
m->transposeLocN += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if there are unplayed notes between this note
|
||||||
|
// and the last played note at 'ei' then
|
||||||
|
// fill in the missing note times by splitting
|
||||||
|
// the gap time evenly - note that this will
|
||||||
|
// bias the evenness std to be lower than it
|
||||||
|
// should be.
|
||||||
|
if( missN > 0 && ei!=kInvalidIdx )
|
||||||
|
{
|
||||||
|
double dsec = (m->locSecV[i] - m->locSecV[ei])/(missN+1);
|
||||||
|
for(unsigned j=ei+1; j<i; ++j)
|
||||||
|
{
|
||||||
|
m->locSecV[j] = m->locSecV[j-1] + dsec;
|
||||||
|
m->interpLocN += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bi == kInvalidIdx )
|
||||||
|
bi = i;
|
||||||
|
|
||||||
statusV[i] = true;
|
m->statusV[i] = true;
|
||||||
missN = 0;
|
missN = 0;
|
||||||
ei = i; // ei=last valid location in locV[]
|
ei = i; // ei=last valid location in m->locSecV[]
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bi_ref = bi;
|
bi_ref = bi;
|
||||||
ei_ref = ei;
|
ei_ref = ei;
|
||||||
|
|
||||||
|
//vop::print( m->locSecV, set->locN, "%f ", "locSecV:" );
|
||||||
|
//vop::print( m->locSecNV, set->locN, "%i ", "locSecN:" );
|
||||||
|
//vop::print( m->statusV, set->locN, "%i ", "ok:");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _eval_one_even_set(perf_meas_t* p, set_t* pm_set )
|
rc_t _eval_one_even_set(perf_meas_t* p, set_t* pm_set )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
const sfscore::set_t* set = pm_set->set;
|
||||||
const sfscore::set_t* set = pm_set->set;
|
unsigned bi = kInvalidIdx;
|
||||||
|
unsigned ei = kInvalidIdx;
|
||||||
double locV[ set->locN ];
|
meas_info_t* m = pm_set->meas_info;
|
||||||
unsigned locNV[ set->locN ];
|
|
||||||
double stdV[ set->locN ];
|
|
||||||
bool statusV[ set->locN ];
|
|
||||||
|
|
||||||
unsigned bi = kInvalidIdx;
|
|
||||||
unsigned ei = kInvalidIdx;
|
|
||||||
unsigned insertN = 0;
|
|
||||||
unsigned evtSkipN = 0;
|
|
||||||
unsigned locSkipN = 0;
|
|
||||||
|
|
||||||
if((rc = _calc_loc_sec(set,locV,locNV,evtSkipN)) != kOkRC )
|
assert( set->locN == m->vN );
|
||||||
|
|
||||||
|
if((rc = _calc_loc_sec(pm_set)) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
_interpolate_time_of_missing_notes(p, set, locV, locNV, statusV, bi, ei, insertN );
|
_interpolate_time_of_missing_notes(p, pm_set, bi, ei );
|
||||||
|
|
||||||
vop::zero(stdV, set->locN);
|
vop::zero(m->dSecV, set->locN);
|
||||||
|
|
||||||
// Calc the std. deviation of the note delta times
|
// Calc the std. deviation of the note delta times
|
||||||
// of all notes [bi:ei]. Note that if the notes
|
// of all notes [bi:ei]. Note that if the notes
|
||||||
@ -404,17 +481,13 @@ namespace cw
|
|||||||
// calc the delta time for each time in locV[]
|
// calc the delta time for each time in locV[]
|
||||||
unsigned stdN = 0;
|
unsigned stdN = 0;
|
||||||
for(unsigned i=bi+1; i<=ei; ++i)
|
for(unsigned i=bi+1; i<=ei; ++i)
|
||||||
stdV[stdN++] = locV[i] - locV[i-1];
|
m->dSecV[stdN++] = m->locSecV[i] - m->locSecV[i-1];
|
||||||
|
|
||||||
|
|
||||||
printf("Skipped evt:%i Skipped locs:%i Insert:%i bi:%i ei:%i final N:%i\n",evtSkipN,locSkipN,insertN,bi,ei,stdN);
|
//printf("Even: skipped evt:%i skipped locs:%i interp:%i bi:%i ei:%i final N:%i\n",m->missEvtN,m->missLocN,m->interpLocN,bi,ei,stdN);
|
||||||
vop::print( locV, set->locN, "%f ", "locV:" );
|
//vop::print( m->dSecV, stdN, "%f ", "std:" );
|
||||||
vop::print( locNV, set->locN, "%i ", "locN:" );
|
|
||||||
vop::print( stdV, stdN, "%f ", "std:" );
|
|
||||||
vop::print( statusV, set->locN, "%i ", "ok:");
|
|
||||||
|
|
||||||
|
|
||||||
pm_set->value = vop::std(stdV, stdN );
|
pm_set->value = vop::std(m->dSecV, stdN );
|
||||||
}
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
@ -422,9 +495,42 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _eval_one_tempo_set(perf_meas_t* p, set_t* set )
|
rc_t _eval_one_tempo_set(perf_meas_t* p, set_t* pm_set )
|
||||||
{
|
{
|
||||||
set->value = 3.0;
|
rc_t rc = kOkRC;
|
||||||
|
const sfscore::set_t* set = pm_set->set;
|
||||||
|
meas_info_t* m = pm_set->meas_info;
|
||||||
|
unsigned bi = kInvalidIdx;
|
||||||
|
unsigned ei = kInvalidIdx;
|
||||||
|
|
||||||
|
assert( set->locN == m->vN );
|
||||||
|
|
||||||
|
if((rc = _calc_loc_sec(pm_set)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
|
_interpolate_time_of_missing_notes(p, pm_set, bi, ei );
|
||||||
|
|
||||||
|
vop::zero(m->dSecV, set->locN);
|
||||||
|
|
||||||
|
if( (ei - bi)+1 > 2 )
|
||||||
|
{
|
||||||
|
// calc the delta time for each time in locV[]
|
||||||
|
unsigned dsecN = 0;
|
||||||
|
for(unsigned i=bi+1; i<=ei; ++i)
|
||||||
|
m->dSecV[dsecN++] = m->locSecV[i] - m->locSecV[i-1];
|
||||||
|
|
||||||
|
//printf("Tempo: skipped evt:%i skipped locs:%i interp:%i bi:%i ei:%i final N:%i\n",m->missEvtN,m->missLocN,m->interpLocN,bi,ei,dsecN);
|
||||||
|
//vop::print( m->dSecV, dsecN, "%f ", "dsecV:" );
|
||||||
|
|
||||||
|
double sec_per_beat = vop::mean(m->dSecV, dsecN );
|
||||||
|
double bpm = 60.0/sec_per_beat;
|
||||||
|
|
||||||
|
|
||||||
|
pm_set->value = bpm;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _aggregate_dynamic_meas_set_values( perf_meas_t* p, calc_t* calc )
|
void _aggregate_dynamic_meas_set_values( perf_meas_t* p, calc_t* calc )
|
||||||
@ -442,7 +548,7 @@ namespace cw
|
|||||||
calc->value[ kTempoValIdx ] = _calc_set_list_mean( calc->setL, score_parse::kTempoVarIdx );
|
calc->value[ kTempoValIdx ] = _calc_set_list_mean( calc->setL, score_parse::kTempoVarIdx );
|
||||||
}
|
}
|
||||||
|
|
||||||
void _eval_cost_calc( perf_meas_t* p, calc_t* calc )
|
void _aggregate_cost_meas_set_values( perf_meas_t* p, calc_t* calc )
|
||||||
{
|
{
|
||||||
if( calc->section->prev_section != nullptr )
|
if( calc->section->prev_section != nullptr )
|
||||||
{
|
{
|
||||||
@ -462,7 +568,7 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
calc->value[ kMatchCostValIdx ] = sum / n;
|
calc->value[ kMatchCostValIdx ] = n==0 ? 0 : sum / n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,6 +641,7 @@ namespace cw
|
|||||||
_aggregate_dynamic_meas_set_values(p,calc);
|
_aggregate_dynamic_meas_set_values(p,calc);
|
||||||
_aggregate_even_meas_set_values(p,calc);
|
_aggregate_even_meas_set_values(p,calc);
|
||||||
_aggregate_tempo_meas_set_values(p,calc);
|
_aggregate_tempo_meas_set_values(p,calc);
|
||||||
|
_aggregate_cost_meas_set_values(p,calc);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -586,6 +693,42 @@ namespace cw
|
|||||||
errLabel:
|
errLabel:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
rc_t _write_result_vector(file::handle_t fH, section_t* section, set_t* set, const char* opLabel, const char* fmt, const T* vect, unsigned locN)
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
|
||||||
|
if((rc = file::printf(fH,"%s,%i,%s,%s,%i,",
|
||||||
|
section->section->label,
|
||||||
|
set==nullptr ? -1 : set->set->id,
|
||||||
|
set==nullptr ? "" : score_parse::var_index_to_char(set->set->varId),
|
||||||
|
opLabel,
|
||||||
|
locN)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf. measure vector header write failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const T* v=vect; v<vect+locN; ++v)
|
||||||
|
if((rc = file::printf(fH,fmt,*v)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf. measure vector write failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = file::printf(fH,"\n")) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf. measure vector EOL failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
double dbl_max_to_neg_one( double x )
|
||||||
|
{ return x==std::numeric_limits<double>::max() ? -1.0 : x; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -620,11 +763,14 @@ cw::rc_t cw::perf_meas::create( handle_t& hRef, sfscore::handle_t scoreH )
|
|||||||
{
|
{
|
||||||
// ... link the sets onto this location record
|
// ... link the sets onto this location record
|
||||||
set_t* set = mem::allocZ<set_t>();
|
set_t* set = mem::allocZ<set_t>();
|
||||||
set->set = s;
|
set->loc = p->locA + i;
|
||||||
|
set->set = s;
|
||||||
set->slink = p->locA[i].setL;
|
set->slink = p->locA[i].setL;
|
||||||
p->locA[i].setL = set;
|
p->locA[i].setL = set;
|
||||||
set->alink = p->setL;
|
set->alink = p->setL;
|
||||||
p->setL = set;
|
p->setL = set;
|
||||||
|
|
||||||
|
_create_meas_info_record(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this location is the start of a new section
|
// if this location is the start of a new section
|
||||||
@ -802,4 +948,150 @@ void cw::perf_meas::report( handle_t h )
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cw::rc_t cw::perf_meas::write_result_json( handle_t h,
|
||||||
|
const char* player_name,
|
||||||
|
const char* perf_date,
|
||||||
|
unsigned perf_take_numb,
|
||||||
|
const char* out_fname )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
perf_meas_t* p = _handleToPtr(h);
|
||||||
|
object_t* root = newDictObject();
|
||||||
|
object_t* sectionL = root->insert_pair("sectionL",newListObject());
|
||||||
|
|
||||||
|
for(loc_t* loc=p->locA; loc<p->locA+p->locN; ++loc)
|
||||||
|
if( loc->section != nullptr && loc->section->calc != nullptr )
|
||||||
|
{
|
||||||
|
object_t* sect = newDictObject(sectionL);
|
||||||
|
const double* valueV = loc->section->calc->value;
|
||||||
|
object_t* setL = newListObject();
|
||||||
|
|
||||||
|
sect->putv("label",loc->section->section->label,
|
||||||
|
"player_name",player_name,
|
||||||
|
"perf_date",perf_date,
|
||||||
|
"perf_take_numb",perf_take_numb,
|
||||||
|
"locId",loc->locId,
|
||||||
|
"dyn",dbl_max_to_neg_one(valueV[kDynValIdx]),
|
||||||
|
"even",dbl_max_to_neg_one(valueV[kEvenValIdx]),
|
||||||
|
"tempo",dbl_max_to_neg_one(valueV[kTempoValIdx]),
|
||||||
|
"cost",dbl_max_to_neg_one(valueV[kMatchCostValIdx]),
|
||||||
|
"setL",setL);
|
||||||
|
|
||||||
|
for(set_t* set=loc->section->calc->setL; set!=nullptr; set=set->clink)
|
||||||
|
{
|
||||||
|
object_t* set_o = newDictObject(setL);
|
||||||
|
|
||||||
|
set_o->putv("type",score_parse::var_index_to_char(set->set->varId),
|
||||||
|
"setId",set->set->id,
|
||||||
|
"locId",set->loc->locId,
|
||||||
|
"value",dbl_max_to_neg_one(set->value),
|
||||||
|
"missEvtN",set->meas_info->missEvtN,
|
||||||
|
"missLocN",set->meas_info->missLocN,
|
||||||
|
"transposeLocN",set->meas_info->transposeLocN,
|
||||||
|
"interpLocN",set->meas_info->interpLocN);
|
||||||
|
|
||||||
|
set_o->put_numeric_list("locSecV", set->meas_info->locSecV, set->meas_info->vN );
|
||||||
|
set_o->put_numeric_list("locSecNV", set->meas_info->locSecNV, set->meas_info->vN );
|
||||||
|
set_o->put_numeric_list("dSecV", set->meas_info->dSecV, set->meas_info->vN );
|
||||||
|
set_o->put_numeric_list("statusV", set->meas_info->statusV, set->meas_info->vN );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = objectToFile(out_fname,root)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf. measurement JSON file write failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
root->free();
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::perf_meas::write_result_csv( handle_t h, const char* out_fname )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
perf_meas_t* p = _handleToPtr(h);
|
||||||
|
file::handle_t fH;
|
||||||
|
|
||||||
|
if((rc = file::open(fH,out_fname, file::kWriteFl)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf. measure result file create failed on '%s'.",cwStringNullGuard(out_fname));
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = file::printf(fH,"section,set,type,op,value,missEvtN,missLocN,transposeLocN,interpLocN\n")) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf. measure title write failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(loc_t* loc=p->locA; loc<p->locA+p->locN; ++loc)
|
||||||
|
if( loc->section != nullptr && loc->section->calc != nullptr )
|
||||||
|
{
|
||||||
|
if((rc = _write_result_vector(fH,loc->section,nullptr,"section","%f,",loc->section->calc->value,kValCnt)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf. measure file write result section header failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(set_t* set=loc->section->calc->setL; set!=nullptr; set=set->clink)
|
||||||
|
{
|
||||||
|
|
||||||
|
if((rc = file::printf(fH,"%s,%i,%s,summary,%f,%i,%i,%i,%i\n",
|
||||||
|
loc->section->section->label,
|
||||||
|
set->set->id,
|
||||||
|
score_parse::var_index_to_char(set->set->varId),
|
||||||
|
set->value != std::numeric_limits<double>::max() ? set->value : 0,
|
||||||
|
set->meas_info->missEvtN,
|
||||||
|
set->meas_info->missLocN,
|
||||||
|
set->meas_info->transposeLocN,
|
||||||
|
set->meas_info->interpLocN)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf. measure file write result failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = _write_result_vector(fH,loc->section,set,"locSecV","%f,",set->meas_info->locSecV,set->set->locN)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf.measure locSecV[] write result failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = _write_result_vector(fH,loc->section,set,"locSecNV","%i,",set->meas_info->locSecNV,set->set->locN)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf.measure locSecNV[] write result failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = _write_result_vector(fH,loc->section,set,"dSecV","%f,", set->meas_info->dSecV,set->set->locN)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf.measure dSecV[] write result failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = _write_result_vector(fH,loc->section,set,"statusV","%i,",set->meas_info->statusV,set->set->locN)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf.measure status[] write result failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((rc = file::close(fH)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf. meas. file close failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
errLabel:
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,7 +33,9 @@ namespace cw
|
|||||||
|
|
||||||
void report( handle_t h );
|
void report( handle_t h );
|
||||||
|
|
||||||
|
rc_t write_result_csv( handle_t h, const char* out_fname );
|
||||||
|
|
||||||
|
rc_t write_result_json( handle_t h, const char* player_name, const char* perf_date, unsigned perf_take_numb, const char* out_fname );
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,9 @@ namespace cw
|
|||||||
bool meas_setup_report_fl;
|
bool meas_setup_report_fl;
|
||||||
|
|
||||||
char* out_dir;
|
char* out_dir;
|
||||||
|
|
||||||
|
bool write_perf_meas_json_fl;
|
||||||
|
const char* out_perf_meas_json_fname;
|
||||||
|
|
||||||
bool write_svg_file_fl;
|
bool write_svg_file_fl;
|
||||||
const char* out_svg_fname;
|
const char* out_svg_fname;
|
||||||
@ -93,6 +96,10 @@ namespace cw
|
|||||||
"meas_setup_report_fl", p->meas_setup_report_fl,
|
"meas_setup_report_fl", p->meas_setup_report_fl,
|
||||||
|
|
||||||
"out_dir", out_dir,
|
"out_dir", out_dir,
|
||||||
|
|
||||||
|
"write_perf_meas_json_fl", p->write_perf_meas_json_fl,
|
||||||
|
"out_perf_meas_json_fname", p->out_perf_meas_json_fname,
|
||||||
|
|
||||||
"write_svg_file_fl", p->write_svg_file_fl,
|
"write_svg_file_fl", p->write_svg_file_fl,
|
||||||
"out_svg_fname", p->out_svg_fname,
|
"out_svg_fname", p->out_svg_fname,
|
||||||
|
|
||||||
@ -133,17 +140,20 @@ namespace cw
|
|||||||
perf_meas::handle_t perfMeasH,
|
perf_meas::handle_t perfMeasH,
|
||||||
unsigned perf_idx )
|
unsigned perf_idx )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
bool pre_test_fl = p->pre_test_fl;
|
bool pre_test_fl = p->pre_test_fl;
|
||||||
bool enable_fl = true;
|
bool enable_fl = true;
|
||||||
const char* perf_label = nullptr;
|
const char* perf_label = nullptr;
|
||||||
const char* midi_fname = nullptr;
|
const char* player_name = nullptr;
|
||||||
char* out_dir = nullptr;
|
const char* perf_date = nullptr;
|
||||||
char* fname = nullptr;
|
unsigned perf_take_numb = kInvalidId;
|
||||||
unsigned start_loc = 0;
|
const char* midi_fname = nullptr;
|
||||||
const object_t* perf = nullptr;
|
char* out_dir = nullptr;
|
||||||
unsigned msgN = 0;
|
char* fname = nullptr;
|
||||||
const midi::file::trackMsg_t** msgA = nullptr;
|
unsigned start_loc = 0;
|
||||||
|
const object_t* perf = nullptr;
|
||||||
|
unsigned msgN = 0;
|
||||||
|
const midi::file::trackMsg_t** msgA = nullptr;
|
||||||
midi::file::handle_t mfH;
|
midi::file::handle_t mfH;
|
||||||
|
|
||||||
// get the perf. record
|
// get the perf. record
|
||||||
@ -156,6 +166,9 @@ namespace cw
|
|||||||
// parse the performance record
|
// parse the performance record
|
||||||
if((rc = perf->getv("label",perf_label,
|
if((rc = perf->getv("label",perf_label,
|
||||||
"enable_fl",enable_fl,
|
"enable_fl",enable_fl,
|
||||||
|
"player",player_name,
|
||||||
|
"perf_date",perf_date,
|
||||||
|
"take",perf_take_numb,
|
||||||
"start_loc", start_loc,
|
"start_loc", start_loc,
|
||||||
"midi_fname", midi_fname)) != kOkRC )
|
"midi_fname", midi_fname)) != kOkRC )
|
||||||
{
|
{
|
||||||
@ -236,7 +249,7 @@ namespace cw
|
|||||||
pre_test_fl = false;
|
pre_test_fl = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%f %li %5i %3x %3i %3i\n",sec, smpIdx, m->uid, m->status, m->u.chMsgPtr->d0, m->u.chMsgPtr->d1);
|
//printf("%f %li %5i %3x %3i %3i\n",sec, smpIdx, m->uid, m->status, m->u.chMsgPtr->d0, m->u.chMsgPtr->d1);
|
||||||
|
|
||||||
// send the note-on to the score follower
|
// send the note-on to the score follower
|
||||||
if((rc = exec(sfH, sec, smpIdx, m->uid, m->status, m->u.chMsgPtr->d0, m->u.chMsgPtr->d1, newMatchFl )) != kOkRC )
|
if((rc = exec(sfH, sec, smpIdx, m->uid, m->status, m->u.chMsgPtr->d0, m->u.chMsgPtr->d1, newMatchFl )) != kOkRC )
|
||||||
@ -293,6 +306,27 @@ namespace cw
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( p->write_perf_meas_json_fl )
|
||||||
|
{
|
||||||
|
// create the JSON output filename
|
||||||
|
if((fname = filesys::makeFn(out_dir,p->out_perf_meas_json_fname,nullptr,nullptr)) == nullptr )
|
||||||
|
{
|
||||||
|
cwLogError(kOpFailRC,"The output perf. meas. filename formation failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
cwLogInfo("Writing JSON score-follow perf. meas. result to:%s",cwStringNullGuard(fname));
|
||||||
|
|
||||||
|
if((rc = write_result_json(perfMeasH,player_name,perf_date,perf_take_numb,fname)) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(rc,"Perf. meas. report file create failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem::release(fname);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// write the score following result SVG
|
// write the score following result SVG
|
||||||
if( p->write_svg_file_fl )
|
if( p->write_svg_file_fl )
|
||||||
|
@ -635,7 +635,7 @@ namespace cw
|
|||||||
set_t* cur_set = nullptr;
|
set_t* cur_set = nullptr;
|
||||||
unsigned setId = 0;
|
unsigned setId = 0;
|
||||||
unsigned setNoteIdx = 0;
|
unsigned setNoteIdx = 0;
|
||||||
unsigned endLoc = kInvalidIdx;
|
unsigned endLocId = kInvalidIdx;
|
||||||
|
|
||||||
for(unsigned vi=0; vi<kVarCnt; ++vi)
|
for(unsigned vi=0; vi<kVarCnt; ++vi)
|
||||||
for(unsigned ei=0; ei<p->eventN; ++ei)
|
for(unsigned ei=0; ei<p->eventN; ++ei)
|
||||||
@ -647,15 +647,16 @@ namespace cw
|
|||||||
// then the set is complete
|
// then the set is complete
|
||||||
// (this handles the case where there are multiple events
|
// (this handles the case where there are multiple events
|
||||||
// on the same end set location)
|
// on the same end set location)
|
||||||
if( endLoc != kInvalidIdx && (e->eLocId > endLoc || ei==p->eventN-1) )
|
if( endLocId != kInvalidIdx && (e->eLocId > endLocId || ei==p->eventN-1) )
|
||||||
{
|
{
|
||||||
cur_set->eventA = mem::allocZ<event_t*>(cur_set->eventN);
|
cur_set->eventA = mem::allocZ<event_t*>(cur_set->eventN);
|
||||||
setId += 1;
|
setId += 1;
|
||||||
setNoteIdx = 0;
|
setNoteIdx = 0;
|
||||||
cur_set = nullptr;
|
cur_set = nullptr;
|
||||||
endLoc = kInvalidIdx;
|
endLocId = kInvalidIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if this event
|
||||||
if( e->varA[vi].flags != 0 )
|
if( e->varA[vi].flags != 0 )
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -667,11 +668,11 @@ namespace cw
|
|||||||
cur_set->eventN += 1;
|
cur_set->eventN += 1;
|
||||||
|
|
||||||
if( cwIsFlag(e->varA[vi].flags,kSetEndVarFl) )
|
if( cwIsFlag(e->varA[vi].flags,kSetEndVarFl) )
|
||||||
endLoc = e->eLocId;
|
endLocId = e->eLocId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fill_sets( score_parse_t* p )
|
void _fill_sets( score_parse_t* p )
|
||||||
{
|
{
|
||||||
for(unsigned ei=0; ei<p->eventN; ++ei)
|
for(unsigned ei=0; ei<p->eventN; ++ei)
|
||||||
@ -687,6 +688,44 @@ namespace cw
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned _set_count( score_parse_t* p )
|
||||||
|
{
|
||||||
|
unsigned n = 0;
|
||||||
|
for(set_t* s = p->begSetL; s!=nullptr; s=s->link)
|
||||||
|
++n;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _order_set_ids_by_time( score_parse_t* p )
|
||||||
|
{
|
||||||
|
typedef struct set_order_str
|
||||||
|
{
|
||||||
|
unsigned beg_evt_idx;
|
||||||
|
set_t* set;
|
||||||
|
} set_order_t;
|
||||||
|
|
||||||
|
unsigned setAllocN = _set_count(p);
|
||||||
|
unsigned setN = 0;
|
||||||
|
set_order_t* setA = mem::allocZ<set_order_t>(setAllocN);
|
||||||
|
|
||||||
|
for(set_t* s=p->begSetL; s!=nullptr; s=s->link)
|
||||||
|
{
|
||||||
|
if( s->eventN > 0 )
|
||||||
|
{
|
||||||
|
setA[setN].beg_evt_idx = s->eventA[0]->index;
|
||||||
|
setA[setN].set = s;
|
||||||
|
setN += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort( setA, setA+setN, [](auto a, auto b){return a.beg_evt_idx<b.beg_evt_idx;});
|
||||||
|
|
||||||
|
unsigned set_id = 0;
|
||||||
|
std::for_each( setA, setA+setN, [&](auto a){ a.set->id = set_id++; });
|
||||||
|
|
||||||
|
mem::release(setA);
|
||||||
|
}
|
||||||
|
|
||||||
rc_t _validate_sets( score_parse_t* p )
|
rc_t _validate_sets( score_parse_t* p )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
@ -1037,6 +1076,8 @@ cw::rc_t cw::score_parse::create( handle_t& hRef, const char* fname, double srat
|
|||||||
|
|
||||||
_fill_sets(p);
|
_fill_sets(p);
|
||||||
|
|
||||||
|
_order_set_ids_by_time( p );
|
||||||
|
|
||||||
if((rc = _validate_sets(p)) != kOkRC )
|
if((rc = _validate_sets(p)) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
@ -1115,10 +1156,7 @@ const cw::score_parse::section_t* cw::score_parse::section_list( handle_t h )
|
|||||||
unsigned cw::score_parse::set_count( handle_t h )
|
unsigned cw::score_parse::set_count( handle_t h )
|
||||||
{
|
{
|
||||||
score_parse_t* p = _handleToPtr(h);
|
score_parse_t* p = _handleToPtr(h);
|
||||||
unsigned n = 0;
|
return _set_count(p);
|
||||||
for(set_t* s = p->begSetL; s!=nullptr; s=s->link)
|
|
||||||
++n;
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const cw::score_parse::set_t* cw::score_parse::set_list( handle_t h )
|
const cw::score_parse::set_t* cw::score_parse::set_list( handle_t h )
|
||||||
|
@ -960,7 +960,7 @@ cw::rc_t cw::sfscore::destroy( handle_t& hRef )
|
|||||||
void cw::sfscore::clear_all_performance_data( handle_t h )
|
void cw::sfscore::clear_all_performance_data( handle_t h )
|
||||||
{
|
{
|
||||||
sfscore_t* p = _handleToPtr(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->eventA, p->eventA + p->eventN, [](event_t& e){ e.perfFl=false; e.perfCnt=0; 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; } );
|
std::for_each( p->setA, p->setA + p->setN, [](set_t& s){ s.perfEventCnt=0; s.perfUpdateCnt=false; } );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -997,7 +997,8 @@ cw::rc_t cw::sfscore::set_perf( handle_t h, unsigned event_idx, double secs, uin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e->perfCnt += 1;
|
||||||
e->perfFl = true;
|
e->perfFl = true;
|
||||||
e->perfVel = vel;
|
e->perfVel = vel;
|
||||||
e->perfSec = secs;
|
e->perfSec = secs;
|
||||||
|
@ -53,15 +53,17 @@ namespace cw
|
|||||||
unsigned varN; // Length of varA[]
|
unsigned varN; // Length of varA[]
|
||||||
|
|
||||||
unsigned bpm; // beats per minute
|
unsigned bpm; // beats per minute
|
||||||
double bpm_rval;
|
double bpm_rval; //
|
||||||
double relTempo; // relative tempo (1=min tempo)
|
double relTempo; // relative tempo (1=min tempo)
|
||||||
|
|
||||||
bool perfFl; // has this event been performed
|
bool perfFl; // has this event been performed
|
||||||
|
unsigned perfCnt; // count of time this event was performed (if perfCnt > 1 then the event was duplicated during performance)
|
||||||
double perfSec; // performance event time
|
double perfSec; // performance event time
|
||||||
uint8_t perfVel; // performance event velocity
|
uint8_t perfVel; // performance event velocity
|
||||||
unsigned perfDynLevel; // performance dynamic level
|
unsigned perfDynLevel; // performance dynamic level
|
||||||
double perfMatchCost; // performance match cost (or DBL_MAX if not valid)
|
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.
|
||||||
|
Loading…
Reference in New Issue
Block a user