cwScoreParse.h/cpp : Converted location variables names to consistently use oLocId and eLocId.

Added: event_t.bpm_rval, use of 'show_warnings_fl', more validity checks.
This commit is contained in:
kevin 2023-09-12 17:53:35 -04:00
parent 7c076fbef1
commit b9f497e1ec
2 changed files with 145 additions and 62 deletions

View File

@ -190,9 +190,13 @@ namespace cw
{
rc_t rc;
if((rc = getv(csvH,"bpm",e->bpm)) != kOkRC )
if((rc = getv(csvH,
"bpm",e->bpm,
"rval",e->bpm_rval )) != kOkRC )
{
rc = cwLogError(rc,"BPM row parse failed.");
}
return rc;
}
@ -268,10 +272,10 @@ namespace cw
const char* dynLabel = nullptr;
const char* evenLabel = nullptr;
const char* tempoLabel = nullptr;
const char* oloc = nullptr;
const char* oLocId = nullptr;
if((rc = getv(csvH,
"oloc", oloc,
"oloc", oLocId,
"rval", e->rval,
"dots", e->dotCnt,
"sci_pitch",sciPitch,
@ -290,10 +294,10 @@ namespace cw
goto errLabel;
}
if( textLength(oloc) > 0 )
if((rc = string_to_number(oloc,e->oloc)) != kOkRC )
if( textLength(oLocId) > 0 )
if((rc = string_to_number(oLocId,e->oLocId)) != kOkRC )
{
rc = cwLogError(rc,"Error converting oloc (%s) to number.",oloc);
rc = cwLogError(rc,"Error converting oLocId (%s) to number.",oLocId);
goto errLabel;
}
@ -397,6 +401,8 @@ namespace cw
section_t* cur_section = nullptr;
unsigned cur_bar_numb = 1;
unsigned bar_evt_idx = 0;
unsigned bpm = 0;
double bpm_rval = 0;
unsigned barPitchCntV[ midi::kMidiNoteCnt ];
vop::zero(barPitchCntV,midi::kMidiNoteCnt);
@ -412,14 +418,12 @@ namespace cw
event_t* e = p->eventA + p->eventN;
e->oloc = kInvalidIdx;
e->oLocId = kInvalidIdx;
if((rc = getv(csvH,
"opcode",opcodeLabel,
"index", e->csvId,
"voice", e->voice,
"loc", e->loc,
"loctn", e->loctn,
"eloc", e->eLocId,
"tick", e->tick,
"sec", e->sec )) != kOkRC )
{
@ -429,6 +433,8 @@ namespace cw
e->csvRowNumb = cur_line_index(csvH) + 1;
e->opId = opcode_label_to_id(opcodeLabel);
e->index = p->eventN;
e->dynLevel = kInvalidIdx;
switch( e->opId )
{
@ -453,7 +459,32 @@ namespace cw
break;
case kBpmTId:
rc = _parse_bpm_row(p,csvH, e );
if((rc = _parse_bpm_row(p,csvH, e )) == kOkRC )
{
// if the cur BPM has not yet been set then go backward setting
// all events prior to this to the initial BPM
if( bpm == 0 && e->bpm != 0 )
std::for_each(p->eventA,e,[e](auto& x){ x.bpm = e->bpm; x.bpm_rval=e->bpm_rval; });
// if the parsed BPM is invalid ...
if( e->bpm == 0 || e->bpm_rval==0 )
{
e->bpm = bpm; // ... then ignore it
e->bpm_rval = bpm_rval;
}
else
{
bpm = e->bpm; // ... otherwise make it the current BPM
bpm_rval = e->bpm_rval;
}
// Be sure that all events on this location have the same BPM
for(event_t* e0 = e - 1; e0>=p->eventA && e0->eLocId==e->eLocId; --e0)
{
e0->bpm = e->bpm;
e0->bpm_rval = e->bpm_rval;
}
}
break;
case kNoteOnTId:
@ -462,6 +493,7 @@ namespace cw
e->barPitchIdx = barPitchCntV[e->d0];
unsigned hash = form_hash(e->opId,cur_bar_numb,e->d0,e->barPitchIdx);
if( _hash_to_event(p,hash) != nullptr )
{
rc = cwLogError(kInvalidStateRC,"The event hash '%x' is is duplicated.",hash);
@ -502,6 +534,8 @@ namespace cw
e->section = cur_section;
e->barNumb = cur_bar_numb;
e->barEvtIdx = bar_evt_idx++;
e->bpm = bpm;
e->bpm_rval = bpm_rval;
p->eventN += 1;
}
@ -527,7 +561,7 @@ namespace cw
rc_t _parse_csv( score_parse_t* p, const char* fname )
{
rc_t rc = kOkRC;
const char* titleA[] = { "opcode","meas","index","voice","loc","loctn","oloc","tick","sec",
const char* titleA[] = { "opcode","meas","index","voice","loc","eloc","oloc","tick","sec",
"dur","rval","dots","sci_pitch","dmark","dlevel","status","d0","d1",
"bar","section","bpm","grace","tie","onset","pedal","dyn","even","tempo" };
@ -613,7 +647,7 @@ namespace cw
// then the set is complete
// (this handles the case where there are multiple events
// on the same end set location)
if( endLoc != kInvalidIdx && (e->loctn > endLoc || ei==p->eventN-1) )
if( endLoc != kInvalidIdx && (e->eLocId > endLoc || ei==p->eventN-1) )
{
cur_set->eventA = mem::allocZ<event_t*>(cur_set->eventN);
setId += 1;
@ -633,7 +667,7 @@ namespace cw
cur_set->eventN += 1;
if( cwIsFlag(e->varA[vi].flags,kSetEndVarFl) )
endLoc = e->loctn;
endLoc = e->eLocId;
}
}
}
@ -682,11 +716,11 @@ namespace cw
{
unsigned j;
for(j=0; j<loc_i; ++j)
if( loc[j] == set->eventA[i]->loctn )
if( loc[j] == set->eventA[i]->eLocId )
break;
if( j == loc_i )
loc[ loc_i++ ] = set->eventA[i]->loctn;
loc[ loc_i++ ] = set->eventA[i]->eLocId;
}
}
@ -733,12 +767,12 @@ namespace cw
}
}
void _fill_sections( score_parse_t* p )
void _fill_section_sets( score_parse_t* p )
{
// allocate memory to hold the set ptr arrays in each section
for(section_t* s = p->sectionL; s!=nullptr; s=s->link)
s->setA = mem::allocZ<set_t*>(s->setN);
// fill the section->setA[] ptrs
for(set_t* set = p->begSetL; set!=nullptr; set=set->link)
{
@ -746,20 +780,37 @@ namespace cw
set->targetSection->setA[ set->sectionSetIdx ] = set;
// set the section beg/end events
if( set->targetSection->begEvent == nullptr )
if( set->targetSection->begSetEvent == nullptr )
{
set->targetSection->begEvent = set->eventA[0];
set->targetSection->endEvent = set->eventA[ set->eventN-1 ];
set->targetSection->begSetEvent = set->eventA[0];
set->targetSection->endSetEvent = set->eventA[ set->eventN-1 ];
}
else
{
if( set->eventA[0]->sec < set->targetSection->begEvent->sec )
set->targetSection->begEvent = set->eventA[0];
if( set->eventA[0]->sec < set->targetSection->begSetEvent->sec )
set->targetSection->begSetEvent = set->eventA[0];
if( set->eventA[set->eventN-1]->sec > set->targetSection->endEvent->sec )
set->targetSection->endEvent = set->eventA[ set->eventN-1 ];
if( set->eventA[set->eventN-1]->sec > set->targetSection->endSetEvent->sec )
set->targetSection->endSetEvent = set->eventA[ set->eventN-1 ];
}
}
}
rc_t _fill_section_beg_end_evt( score_parse_t* p )
{
rc_t rc = kOkRC;
for(unsigned i=0; i<p->eventN; ++i)
{
event_t* e = p->eventA + i;
assert( e->section != nullptr );
if( e->section->begEvent == nullptr || e->index < e->section->begEvent->index )
e->section->begEvent = e;
if( e->section->endEvent == nullptr || e->index > e->section->endEvent->index )
e->section->endEvent = e;
}
return rc;
}
bool _compare_sections(const section_t* sec0, const section_t* sec1)
@ -808,7 +859,7 @@ namespace cw
mem::release(secA);
}
rc_t _validate_sections( score_parse_t* p )
rc_t _validate_sections( score_parse_t* p, bool show_warnings_fl )
{
rc_t rc = kOkRC;
@ -818,10 +869,11 @@ namespace cw
{
if( s->setN == 0 )
{
cwLogWarning("The section '%s' does not have any sets assigned to it.",cwStringNullGuard(s->label));
if( show_warnings_fl )
cwLogWarning("The section '%s' does not have any sets assigned to it.",cwStringNullGuard(s->label));
}
else
if( s->begEvent == nullptr || s->endEvent == nullptr )
if( s->begSetEvent == nullptr || s->endSetEvent == nullptr )
{
rc = cwLogError(kInvalidStateRC,"The section '%s' does not beg/end events.",cwStringNullGuard(s->label));
continue;
@ -836,6 +888,31 @@ namespace cw
s0 = s;
}
// verify that there are no event gaps between the sections
if( p->sectionL != nullptr and p->sectionL->link != nullptr )
{
s0 = p->sectionL;
for(section_t* s=s0->link; s!=nullptr; s=s->link)
{
if( s0->endEvent == nullptr )
rc = cwLogError(kInvalidStateRC,"The section '%s' does not have an end event.",cwStringNullGuard(s0->label));
else
{
if( s->begEvent == nullptr )
rc = cwLogError(kInvalidStateRC,"The section '%s' does not have a begin event.",cwStringNullGuard(s->label));
else
{
if( s0->endEvent->index+1 != s->begEvent->index )
rc = cwLogError(kInvalidStateRC,"The sections '%s' and '%s' do not begin/end on consecutive events.",cwStringNullGuard(s0->label),cwStringNullGuard(s->label));
}
}
s0 = s;
}
}
if( rc != kOkRC )
rc = cwLogError(rc,"Section validation failed.");
return rc;
@ -908,6 +985,11 @@ unsigned cw::score_parse::dyn_ref_label_to_level( handle_t h, const char* label
return marker_to_level( p->dynRefH, label );
}
unsigned cw::score_parse::dyn_ref_vel_to_level( handle_t h, uint8_t vel )
{
score_parse_t* p = _handleToPtr(h);
return velocity_to_level(p->dynRefH,vel);
}
unsigned cw::score_parse::form_hash( unsigned op_id, unsigned bar, uint8_t midi_pitch, unsigned barPitchIdx )
{
@ -932,7 +1014,7 @@ void cw::score_parse::parse_hash( unsigned hash, unsigned& op_idRef, unsi
}
cw::rc_t cw::score_parse::create( handle_t& hRef, const char* fname, double srate, dyn_ref_tbl::handle_t dynRefH )
cw::rc_t cw::score_parse::create( handle_t& hRef, const char* fname, double srate, dyn_ref_tbl::handle_t dynRefH, bool show_warnings_fl )
{
rc_t rc = kOkRC;
score_parse_t* p = nullptr;
@ -960,16 +1042,15 @@ cw::rc_t cw::score_parse::create( handle_t& hRef, const char* fname, double srat
_fill_target_sections(p);
_fill_sections(p);
_fill_section_sets(p);
_sort_sections(p);
if((rc = _validate_sections(p)) != kOkRC )
_fill_section_beg_end_evt(p);
if((rc = _validate_sections(p,show_warnings_fl)) != kOkRC )
goto errLabel;
hRef.set(p);
errLabel:
@ -1055,11 +1136,9 @@ void cw::score_parse::report( handle_t h )
const char* B = "B:";
const char* blank = " ";
const unsigned flN = 6;
printf("row op section bar bei voc tick sec rval dot lo c lctn oloc flags bpm stat d0 d1 spich hash \n");
printf("---- --- ------- ----- --- --- ---- ------- ------ --- ----- ----- ----- ----- --- ---- ---- --- ----- --------\n");
printf("row op section bpm b_rval bar bei voc tick sec rval dot eloc oloc flags bpm stat d0 d1 spich hash \n");
printf("---- --- ------- --- ------ ----- --- --- ---- ------- ------ --- ----- ----- ----- --- ---- ---- --- ----- --------\n");
for(unsigned i=0; i<p->eventN; ++i)
{
@ -1076,11 +1155,13 @@ void cw::score_parse::report( handle_t h )
if( cwIsFlag(e->flags,kTieEndFl)) { flag_str[fli++] = 'T'; }
if( cwIsFlag(e->flags,kOnsetFl)) { flag_str[fli++] = 'o'; }
printf("%4i %3s %2s%4s %2s%3i %3i %3i %4i %7.3f %6.3f %3i %5i %5i %5i %5s %3i 0x%02x 0x%02x %3i %5s",
printf("%4i %3s %2s%4s %3i %6.4f %2s%3i %3i %3i %4i %7.3f %6.3f %3i %5i %5i %5s %3i 0x%02x 0x%02x %3i %5s",
e->csvRowNumb,
opcode_id_to_label(e->opId),
secLabel,
e->section == nullptr || e->section->label==nullptr ? "" : e->section->label ,
e->bpm,
e->bpm_rval,
barLabel,
e->barNumb,
e->barEvtIdx,
@ -1089,9 +1170,8 @@ void cw::score_parse::report( handle_t h )
e->sec,
e->rval,
e->dotCnt,
e->loc,
e->loctn,
e->oloc,
e->eLocId,
e->oLocId,
flag_str,
e->bpm,
e->status,

View File

@ -47,26 +47,28 @@ namespace cw
struct event_str;
typedef struct section_str
{
char* label;
unsigned csvRowNumb; // score CSV row number where this section starts
unsigned setN;
struct set_str** setA;
struct event_str* begEvent;
struct event_str* endEvent;
struct section_str* link;
char* label; // This sections label
unsigned csvRowNumb; // score CSV row number where this section starts
unsigned setN; // Count of elements in setA[]
struct set_str** setA; // setA[setN] Array of pointers to sets that are applied to this section.
struct event_str* begEvent; // first event in this section
struct event_str* endEvent; // last event in this section
struct event_str* begSetEvent; // first set event in this section
struct event_str* endSetEvent; // last set event in this section
struct section_str* link; // p->sectionL links
} section_t;
struct event_str;
typedef struct set_str
{
unsigned id;
unsigned varTypeId;
unsigned eventN;
struct event_str** eventA;
section_t* targetSection;
unsigned sectionSetIdx; // index of this set in the section
struct set_str* link;
unsigned id; // Unique id for this set
unsigned varTypeId; // Type of measurement to perform on this set.
unsigned eventN; // Count of elements in eventA[]
struct event_str** eventA; // eventA[eventN] Pointers to all events in this set.
section_t* targetSection; // Section this set will be applied to.
unsigned sectionSetIdx; // Index of this set in the targetSection->setA[].
struct set_str* link; // p->setL link
} set_t;
typedef struct event_var_str
@ -81,7 +83,7 @@ namespace cw
{
unsigned csvRowNumb; // CSV row number this event was derived from
unsigned opId; // event type
unsigned csvId; // CSV 'index' column
unsigned index; // index of this recod in event_array()
section_t* section; // section that this event belongs to
unsigned barNumb; //
unsigned barEvtIdx; // index of this event in this bar
@ -93,10 +95,10 @@ namespace cw
unsigned dotCnt;
unsigned dynLevel; // dynamic level based on marker
unsigned hash; // [ op_id:4 bar:12 pitch:8 bar_pitch_n:8 ]
unsigned loc;
unsigned loctn;
unsigned oloc;
unsigned eLocId; // event location id (includes all events, oloc includes just note-ons)
unsigned oLocId; // onset location id (onset loc id's used by sfScore)
unsigned bpm;
double bpm_rval;
unsigned flags;
midi::byte_t status;
midi::byte_t d0;
@ -118,11 +120,12 @@ namespace cw
const char* dyn_ref_level_to_label( handle_t h, unsigned vel );
unsigned dyn_ref_label_to_level( handle_t h, const char* label );
unsigned dyn_ref_vel_to_level( handle_t h, uint8_t vel );
unsigned form_hash( unsigned op_id, unsigned bar, uint8_t midi_pitch, unsigned barPitchIdx );
void parse_hash( unsigned hash, unsigned& op_idRef, unsigned& barRef, uint8_t& midi_pitchRef, unsigned& barPitchIdxRef );
rc_t create( handle_t& hRef, const char* fname, double srate, dyn_ref_tbl::handle_t dynRefH );
rc_t create( handle_t& hRef, const char* fname, double srate, dyn_ref_tbl::handle_t dynRefH, bool show_warnings_fl=false );
rc_t destroy( handle_t& hRef );
double sample_rate( handle_t h );