From e1d84b28615eca803d1e7bdc2a613901e2cd31ab Mon Sep 17 00:00:00 2001 From: kevin Date: Sat, 5 Aug 2023 12:34:46 -0400 Subject: [PATCH] cwSfScore.h/cpp : Added event(),loc_count(),loc() and parse_dyn_ref_cfg(). Remove functions that are now implemented in sfMatch. --- cwSfScore.cpp | 1126 ++++++++++++++++++------------------------------- cwSfScore.h | 9 +- 2 files changed, 409 insertions(+), 726 deletions(-) diff --git a/cwSfScore.cpp b/cwSfScore.cpp index 16f9d7e..fe9520d 100644 --- a/cwSfScore.cpp +++ b/cwSfScore.cpp @@ -12,181 +12,43 @@ #include "cwTime.h" #include "cwVectOps.h" #include "cwSfScoreParser.h" +#include "cwMidi.h" namespace cw { namespace sfscore { - - /* - typedef struct varMap_str - { - unsigned typeId; - unsigned flag; - const char* label; - } varMap_t; - - typedef struct dynRef_str - { - char* label; - unsigned labelCharCnt; - uint8_t vel; - } dynRef_t; - - typedef idLabelPair_t opcodeMap_t; - - opcodeMap_t _opcodeMapA[] = - { - { kTimeSigEvtScId, "tsg" }, - { kKeySigEvtScId, "ksg" }, - { kTempoEvtScId, "tmp" }, - { kTrackEvtScId, "trk" }, - { kTextEvtScId, "txt" }, - { kNameEvtScId, "nam" }, - { kEOTrackEvtScId, "eot" }, - { kCopyEvtScId, "cpy" }, - { kBlankEvtScId, "blk" }, - { kBarEvtScId, "bar" }, - { kPgmEvtScId, "pgm" }, - { kCtlEvtScId, "ctl" }, - { kNonEvtScId, "non" }, - { kPedalEvtScId, "ped" }, - { kInvalidId, "" } - }; - - varMap_t _varMapA[] = - { - { kEvenVarScId, kEvenScFl, "e"}, - { kDynVarScId, kDynScFl, "d"}, - { kTempoVarScId,kTempoScFl,"t"}, - { kInvalidId, 0, ""} - }; - */ typedef struct sfscore_str { - //dynRef_t* dynRefA; - //unsigned dynRefN; - parser::handle_t parserH; - event_t* eventA; - unsigned eventN; - unsigned eventAllocN; + event_t* eventA; + unsigned eventN; - set_t* setL; + set_t* setA; + unsigned setN; section_t* sectionA; unsigned sectionN; - unsigned sectionAllocN; + + loc_t* locA; + unsigned locN; } sfscore_t; + typedef struct rpt_evt_str + { + event_t* event; + loc_t* loc; + section_t* section; + set_t* setA[ kScVarCnt ]; + } rpt_event_t; + + sfscore_t* _handleToPtr( handle_t h ) { return handleToPtr(h); } - /* - unsigned _opcode_label_to_id( const char* label ) - { - unsigned id; - if((id = labelToId( _opcodeMapA, label, kInvalidId )) == kInvalidId ) - cwLogError(kInvalidArgRC,"'%s' is not a valid event opcode type label.",cwStringNullGuard(label)); - - return id; - } - - const char* _opcode_id_to_label( unsigned opcodeId ) - { - const char* label; - if((label = idToLabel( _opcodeMapA, opcodeId, kInvalidEvtScId)) == nullptr ) - cwLogError(kInvalidArgRC,"The event opcode type id '%i' is not valid.",opcodeId); - - return label; - } - - - unsigned _varLabelToTypeId( const char* label ) - { - if( label!=nullptr && textLength(label)>0 ) - { - char varLabel[] = { label[0],0 }; - for(unsigned i=0; _varMapA[i].typeId != kInvalidId; ++i) - if( textCompare(varLabel,_varMapA[i].label) == 0 ) - return _varMapA[i].typeId; - } - - cwLogError(kInvalidArgRC,"The variable label '%s' is not valid.",cwStringNullGuard(label)); - - return kInvalidId; - } - const char* _varTypeIdToLabel( unsigned varTypeId ) - { - for(unsigned i=0; _varMapA[i].typeId != kInvalidId; ++i) - if( _varMapA[i].typeId == varTypeId ) - return _varMapA[i].label; - - cwLogError(kInvalidArgRC,"The variable type id '%i' is not valid.",varTypeId); - - return nullptr; - } - - unsigned _varTypeIdToFlag( unsigned varTypeId ) - { - for(unsigned i=0; _varMapA[i].typeId != kInvalidId; ++i) - if( _varMapA[i].typeId == varTypeId ) - return _varMapA[i].flag; - - cwLogError(kInvalidArgRC,"The variable type id '%i' is not valid.",varTypeId); - return 0; - } - - unsigned _varFlagToTypeId( unsigned varFlag ) - { - for(unsigned i=0; _varMapA[i].typeId != kInvalidId; ++i) - if( _varMapA[i].flag == varFlag ) - return _varMapA[i].typeId; - - cwLogError(kInvalidArgRC,"The variable flag id '0x%x' is not valid.",varFlag); - return kInvalidId; - } - - unsigned _varLabelToFlag( const char* varLabel ) - { - unsigned varId; - if(varLabel==nullptr || textLength(varLabel)==0 || (varId = _varLabelToTypeId(varLabel)) == kInvalidId ) - return 0; - return _varTypeIdToFlag(varId); - } - - const char* _varTypeFlagToLabel( unsigned varFlag ) - { - unsigned varId; - if((varId = _varFlagToTypeId(varFlag)) != kInvalidId ) - return _varTypeIdToLabel(varId); - - return nullptr; - } - - unsigned _dynLabelToLevel( sfscore_t* p, const char* dynLabel ) - { - const char* end; - unsigned char_cnt; - - if( dynLabel == nullptr || textLength(dynLabel)==0 ) - return kInvalidDynVel; - - end = nextWhiteCharEOS(dynLabel); - assert(end != nullptr ); - char_cnt = end - dynLabel; - - for(unsigned i=0; idynRefN; ++i) - if( textCompare(p->dynRefA[i].label,dynLabel,char_cnt) == 0 ) - return p->dynRefA[i].vel; - - cwLogError(kSyntaxErrorRC,"The dynamic label '%s' is not valid.",cwStringNullGuard(dynLabel)); - return 0; - } - */ void _destroy_set( set_t* s ) { @@ -199,626 +61,366 @@ namespace cw { char* ss = (char*)(s->label); mem::release(ss); + mem::release(s->setArray); } rc_t _destroy( sfscore_t* p ) { rc_t rc = kOkRC; - set_t* s = p->setL; - while( s!= nullptr ) + for(unsigned i=0; ilocN; ++i) + mem::release(p->locA[i].evtArray); + mem::release(p->locA); + + for(unsigned i=0; isetN; ++i) { - set_t* s0 = s->llink; - _destroy_set(s); - s=s0; - } - + mem::release(p->setA[i].eleArray); + mem::release(p->setA[i].sectArray); + } + mem::release(p->setA); + for(unsigned i=0; isectionN; ++i) _destroy_section( p->sectionA + i ); mem::release(p->sectionA); mem::release(p->eventA); - /* - for(unsigned i=0; idynRefN; ++i) - mem::release(p->dynRefA[i].label); - mem::release(p->dynRefA); - */ - destroy(p->parserH); mem::release(p); return rc; } - /* - rc_t _parse_bar( sfscore_t* p, event_t* e, const char* barNumbString ) + rc_t _create_event_array( sfscore_t* p ) { rc_t rc = kOkRC; + + const parser::p_event_t* pe_array = parser::event_array(p->parserH); + + p->eventN = parser::event_count(p->parserH); + + if( pe_array == nullptr || p->eventN == 0 ) + { + rc = cwLogError(kInvalidStateRC,"No events were found."); + goto errLabel; + } + + p->eventA = mem::allocZ(p->eventN); + p->locN = 0; + + for(unsigned i=0; ieventN; ++i) + { + event_t* e = p->eventA + i; + const parser::p_event_t* pe = pe_array + i; + + e->type = pe->typeId; + e->secs = pe->secs; + e->index = pe->index; + e->locIdx = pe->locIdx; + e->pitch = pe->pitch; + e->vel = pe->vel; + e->flags = pe->flags; + e->dynVal = pe->dynVal; + e->frac = pe->t_frac; + e->barNumb = pe->barNumb; + e->barNoteIdx = pe->barNoteIdx; + e->csvRowNumb = pe->csvRowNumb; + e->line = pe->line; + e->csvEventId = pe->csvEventId; + + if( e->locIdx > p->locN ) + p->locN = e->locIdx; + + } + + p->locN += 1; // add one to convert locN from index to count + + cwLogInfo("%i locations.",p->locN); + + errLabel: return rc; } - // Iterate backward from the last event in a set to locate beginning of the set and return - // a pointer to the first event in the set and the count of events in the set. - unsigned _calc_set_event_count( sfscore_t* p, const event_t* prev_end_evt, event_t* end_set_evt, unsigned varTypeFlag, event_t*& begEvtRef ) + rc_t _create_loc_array( sfscore_t* p ) { - unsigned n = 0; - event_t* e0 = end_set_evt; - - begEvtRef = nullptr; + rc_t rc = kOkRC; + unsigned ebi = 0; - for(; e0>=p->eventA; --e0) - if( cwIsFlag(e0->flags,varTypeFlag) ) + if( p->locN == 0) + { + rc = cwLogError(kInvalidStateRC,"No locations were found."); + goto errLabel; + } + + p->locA = mem::allocZ(p->locN); + + for(unsigned i=0; ieventN; ++i) + { + const event_t* e = p->eventA + i; + + if( e->locIdx != p->eventA[ebi].locIdx || i==p->eventN-1 ) { - if( e0 == prev_end_evt ) - break; + unsigned locIdx = p->eventA[ebi].locIdx; - ++n; - begEvtRef = e0; + assert( locIdx < p->locN); + + loc_t* loc = p->locA + locIdx; + loc->index = p->eventA[ebi].locIdx; + loc->secs = p->eventA[ebi].secs; + loc->barNumb = p->eventA[ebi].barNumb; + loc->evtCnt = (i - ebi) + (i==p->eventN-1 ? 1 : 0); + loc->evtArray = mem::allocZ( loc->evtCnt ); + + for(unsigned j=0; jevtCnt; ++j) + { + assert( ebi + j < p->eventN ); + loc->evtArray[j] = p->eventA + (ebi+j); + } + + ebi = i; } + + } + - return n; + errLabel: + return rc; } - - // Get the ending event from the previous set of the same var type. - const event_t* _get_prev_end_event( sfscore_t* p, unsigned varTypeFlag ) + + rc_t _create_section_array( sfscore_t* p ) { - const set_t* s; - unsigned varTypeId = _varFlagToTypeId(varTypeFlag); - for(s=p->setL; s!=nullptr; s=s->llink) - if( s->varId == varTypeId ) - return s->eleArray[ s->eleCnt-1 ]; + rc_t rc = kOkRC; + p->sectionN = parser::section_count(p->parserH); - return nullptr; + // the location array must have already been created. + assert( p->locA != nullptr ); + + if( p->sectionN == 0 ) + { + rc = cwLogError(kInvalidStateRC,"No sections were found."); + goto errLabel; + } + else + { + p->sectionA = mem::allocZ(p->sectionN); + + const parser::p_section_t* ps = parser::section_list(p->parserH); + for(unsigned i=0; isectionN; ++i) + { + section_t* section = p->sectionA + i; + section->label = mem::duplStr(ps->label); + section->index = i; + section->begEvtIndex = ps->begEvtIdx; + section->locPtr = p->locA + p->eventA[ps->begEvtIdx].locIdx; + section->locPtr->begSectPtr = section; + + for(unsigned j=0; jvars[j] = DBL_MAX; + + ps = ps->link; + } + } + + errLabel: + return rc; } - section_t* _find_section(sfscore_t* p, const char* sectionLabel ) + section_t* _label_to_section( sfscore_t* p, const char* label ) { for(unsigned i=0; isectionN; ++i) - if( textIsEqual(p->sectionA[i].label,sectionLabel) ) + if( textIsEqual(p->sectionA[i].label,label) ) return p->sectionA + i; - - return nullptr; + + return nullptr; } - rc_t _connect_section_to_set( sfscore_t* p, set_t* set, const char* section_label ) + rc_t _create_set_array( sfscore_t* p ) { rc_t rc = kOkRC; - - section_t* section; - if((section = _find_section(p,section_label)) == nullptr ) - { - rc = cwLogError(kSyntaxErrorRC,"The section label '%s' could not be found.",cwStringNullGuard(section_label)); - goto errLabel; - } - - set->sectCnt += 1; - set->sectArray = mem::resizeZ(set->sectArray,set->sectCnt); - set->sectArray[ set->sectCnt-1 ] = section; + const parser::p_set_t* ps = set_list(p->parserH); - errLabel: - return rc; - } - - - // Create a 'set' record. - rc_t _create_set( sfscore_t* p, event_t* end_set_evt, unsigned varTypeFlag, const char* section_label ) - { - rc_t rc = kOkRC; - event_t* beg_set_evt = nullptr; - event_t* e = nullptr; - unsigned set_eventN = 0; - const event_t* prev_end_evt = _get_prev_end_event(p,varTypeFlag); - - // iterate backward to determine the beginning event in this set and the count of events in it - if((set_eventN = _calc_set_event_count( p, prev_end_evt, end_set_evt, varTypeFlag, beg_set_evt )) == 0 || beg_set_evt == nullptr ) + p->setN = parser::set_count(p->parserH); + if( p->setN == 0 ) { - rc = cwLogError(kOpFailRC,"Unable to locate the '%s' var set.",_varTypeFlagToLabel(varTypeFlag)); + rc = cwLogError(kInvalidStateRC,"No sets were found."); goto errLabel; } else { - set_t* set = mem::allocZ(); - unsigned i; - - set->varId = _varFlagToTypeId(varTypeFlag); - set->eleCnt = set_eventN; - set->eleArray = mem::allocZ(set_eventN); + p->setA = mem::allocZ( p->setN ); - // assign section to set - if((rc = _connect_section_to_set(p,set,section_label)) != kOkRC ) + // for each set + for(unsigned i=0; isetN; ++i,ps=ps->link) { - cwLogError(rc,"Section '%s' assignment to set failed.",section_label); - goto errLabel; - } - - - // fill in s->eleArray[] - for(i=0,e=beg_set_evt; e<=end_set_evt; ++e) - if( cwIsFlag(e->flags,varTypeFlag) ) + assert(ps != nullptr); + section_t* section = nullptr; + set_t* set = p->setA + i; + + set->id = ps->id; + set->varId = ps->varTypeId; + + // fill in the events belonging to this list + set->eleCnt = ps->eventN; + set->eleArray = mem::allocZ(set->eleCnt); + for(unsigned j=0; jeleCnt; ++j) + set->eleArray[j] = p->eventA + ps->eventA[j]->index; + + // add this set to the setList for the set's end loc + if( set->eleCnt > 0 ) { - assert( e > prev_end_evt ); - assert( i < set->eleCnt ); - set->eleArray[i++] = e; - } - - assert( i == set->eleCnt ); - - set->llink = p->setL; - p->setL = set; - } - - errLabel: - - return rc; - } - - // Once the var. spec. label is known to have a section id this function extracts the section label - unsigned _parse_set_end_section_label( const char* label, const char*& sectionLabelRef ) - { - rc_t rc = kOkRC; - const char* c = nullptr; - - sectionLabelRef = nullptr; - - // a label with a section will have internal whitespace - if((c = nextWhiteChar(label)) == nullptr ) - return rc; - - // advance past the white space to the first char of the section id - if( (c=nextNonWhiteChar(c)) == nullptr ) - goto errLabel; - - // parse the section id - sectionLabelRef = c; - - return rc; - - errLabel: - return cwLogError(kSyntaxErrorRC,"The section number could not be parsed from '%s'.",label); - } - - - // Parse the optional set section number following the var spec. label. - rc_t _parse_var_set_section_label(sfscore_t* p, event_t* e, const char* label, unsigned varTypeFlag ) - { - rc_t rc = kOkRC; - const char* section_label = nullptr; - - // attempt to get the section id following the var marker - if((rc = _parse_set_end_section_label(label,section_label)) != kOkRC ) - goto errLabel; - - // if a section id was found ... - if( section_label != nullptr ) - { - // then create the set - if((rc = _create_set(p,e,varTypeFlag,section_label)) != kOkRC ) - { - rc = cwLogError(rc,"Variable set create failed for var type:%s.",_varTypeFlagToLabel(varTypeFlag)); - goto errLabel; - } - } - - errLabel: - - return rc; - } - - // A variable specification indicate how a note is to be measured. It is contained - // in the 'tempo','even', and 'dyn' columns. The specification contains two parts: - // a char string id ('t','e', (e.g. p,pp,mf,fff,etc)) followed by - // an optional section identifier. The section identifer marks the end - // of a 'set' of var. spec's and also idicates the section which will be modified - // according to the measurements. - rc_t _parse_var_spec( sfscore_t* p, event_t* e, const char* label, unsigned varTypeFlag ) - { - rc_t rc = kOkRC; - - if( label==nullptr || textLength(label)==0) - return rc; - - // if this is a 'dynamics' marking - if( varTypeFlag == kDynScFl ) - { - if((e->dynVal = _dynLabelToLevel(p,label)) == kInvalidDynVel ) - { - cwLogError(kSyntaxErrorRC,"Note dynamic var spec parse failed on label:%s",cwStringNullGuard(label)); - goto errLabel; - } - } - else - { - // this is a 'tempo' or 'even' marking - if(_varLabelToFlag(label) != varTypeFlag ) - { - cwLogError(kSyntaxErrorRC,"Note %s var spec parse failed on label:%s.",_varTypeFlagToLabel(varTypeFlag),cwStringNullGuard(label)); - goto errLabel; - } - } - - // parse the optional section id. - if((rc = _parse_var_set_section_label(p,e,label,varTypeFlag)) != kOkRC ) - goto errLabel; - - e->flags |= varTypeFlag; - - errLabel: - return rc; - } - - rc_t _parse_csv_note(sfscore_t* p, - event_t* e, - uint8_t d0, - uint8_t d1, - const char* sciPitch, - const char* evenLabel, - const char* tempoLabel, - const char* dynLabel) - { - rc_t rc = kOkRC; - - if((rc = _parse_var_spec(p,e,evenLabel,kEvenScFl )) != kOkRC ) - goto errLabel; - - if((rc = _parse_var_spec(p,e,tempoLabel,kTempoScFl )) != kOkRC ) - goto errLabel; - - if((rc = _parse_var_spec(p,e,dynLabel,kDynScFl)) != kOkRC ) - goto errLabel; - - e->flags |= _varLabelToFlag(tempoLabel); - - e->pitch = d0; - e->vel = d1; - - errLabel: - return rc; - } - - - rc_t _parse_csv_row( sfscore_t* p, csv::handle_t& csvH, event_t* e, unsigned& curBarNumbRef, unsigned& curBarNoteIdxRef ) - { - rc_t rc = kOkRC; - - const char* opcodeLabel; - const char* arg0; - const char* evenLabel; - const char* tempoLabel; - const char* dynLabel; - uint8_t d0,d1; - const char* sectionLabel; - - if((rc = getv( csvH, - "opcode",opcodeLabel, - "evt", e->csvEventId, - "micros",e->secs, - "d0",d0, - "d1",d1, - "arg0",arg0, - "bar",e->barNumb, - "even",evenLabel, - "tempo",tempoLabel, - "t_frac",e->frac, - "dyn",dynLabel, - "section",sectionLabel )) != kOkRC ) - { - rc = cwLogError(rc,"Error parsing score CSV row." ); - goto errLabel; - } - - // validate the opcode - if((e->type = _opcode_label_to_id( opcodeLabel )) == kInvalidId ) - { - cwLogError(kSyntaxErrorRC,"The opcode type:'%s' is not valid.",cwStringNullGuard(opcodeLabel)); - goto errLabel; + loc_t* end_loc = p->locA + set->eleArray[set->eleCnt-1]->locIdx; + set->llink = end_loc->setList; + end_loc->setList = set; } - switch( e->type ) + // set the target-section related fields fro this set + if( ps->target_section != nullptr ) { - case kBarEvtScId: - if( curBarNumbRef != kInvalidId && e->barNumb != curBarNumbRef+1 ) - { - rc = cwLogError(kInvalidStateRC,"Missig bar number %i. Jumped from bar:%i to bar:%i.", curBarNumbRef+1,curBarNumbRef,e->barNumb); - goto errLabel; - } - - curBarNumbRef = e->barNumb; - curBarNoteIdxRef = 0; - break; - - case kCtlEvtScId: - break; - - case kNonEvtScId: - e->barNumb = curBarNumbRef; - e->barNoteIdx = curBarNoteIdxRef++; - if((rc = _parse_csv_note(p,e,d0,d1,arg0,evenLabel,tempoLabel,dynLabel)) != kOkRC ) - { - cwLogError(rc,"Note parse failed."); - goto errLabel; - } - break; - - default: - cwLogError(kInvalidArgRC,"The opcode type '%s' is not valid in this context.",cwStringNullGuard(opcodeLabel)); - goto errLabel; - break; - } - - - // if this event has a section label - if( sectionLabel != nullptr and textLength(sectionLabel)>0 ) - { - section_t* section; - - // locate the section record - if((section = _find_section(p,sectionLabel)) == nullptr ) + if((section = _label_to_section(p,ps->target_section->label)) == nullptr ) { - rc = cwLogError(kSyntaxErrorRC,"The section label '%s' could not be found.",cwStringNullGuard(sectionLabel)); + rc = cwLogError(kInvalidIdRC,"The section '%s' was not found."); goto errLabel; } - // verify that this section was not already assigned a starting event index - if( section->begEvtIndex != kInvalidIdx ) - { - rc = cwLogError(kInvalidIdRC,"The section label '%s' appears to be duplicated.",cwStringNullGuard(sectionLabel)); - goto errLabel; - } + set->sectCnt = 1; + set->sectArray = mem::allocZ(set->sectCnt); + set->sectArray[0] = section; - // assign a starting event index to this event - section->begEvtIndex = e->index; + section->setCnt += 1; + section->setArray = mem::resizeZ(section->setArray,section->setCnt); + section->setArray[ section->setCnt-1 ] = set; + } - + } + } errLabel: - return rc; + return rc; } - rc_t _parse_csv_events( sfscore_t* p, csv::handle_t csvH ) + void _report_print( sfscore_t* p, rpt_event_t* rptA, unsigned rptN ) { - rc_t rc; - unsigned cur_line_idx = 0; - unsigned curBarNumb = kInvalidId; - unsigned curBarNoteIdx = 0; + unsigned bar0 = 0; + const char* sec0 = nullptr; + const char* blank_str = " "; + const char* sec_str = "S:"; + const char* bar_str = "B:"; - // get the line count from the CSV file - if((rc = line_count(csvH,p->eventAllocN)) != kOkRC ) + printf("e idx loc secs op sectn sdx bar bdx scip vel frac\n"); + printf("----- ----- ------- --- ------ --- ----- --- ---- --- -----\n"); + + + for(rpt_event_t* r=rptA; revent; + const section_t* section = r->section; + + const char* d_bar_str = bar0 != e->barNumb ? bar_str : blank_str; + const char* d_sec_str = textIsEqual(sec0,section->label) ? blank_str : sec_str; + + char sciPitch[5]; + midi::midiToSciPitch( e->pitch, sciPitch, 5 ); + + bar0 = e->barNumb; + sec0 = section->label; + + printf("%5i %5i %7.3f %3s %2s%4s %3i %2s%3i %3i %4s %3i %5.3f ", + e->index, + e->locIdx, + e->secs, + opcode_id_to_label(e->type), + d_sec_str, + section==nullptr ? " " : cwStringNullGuard(section->label), + section->index, + d_bar_str, + e->barNumb, + e->barNoteIdx, + sciPitch, + e->vel, + e->frac ); + + for(unsigned refVarTypeId=kMinVarScId; refVarTypeIdsetA[refVarTypeId]; + if( set == nullptr || set->sectCnt==0 ) + printf(" "); + else + { + unsigned varRefFlags = var_type_id_to_mask(refVarTypeId); + + const char* sect_label = set->sectArray[0]==nullptr ? "****" : set->sectArray[0]->label; + printf("%c-%03i-%s ",var_type_flag_to_char(e->flags & varRefFlags), set->id, sect_label); + } + } + + printf("\n"); + } + + } + + rpt_event_t* _report_create( sfscore_t* p ) + { + rpt_event_t* rptA = mem::allocZ( p->eventN ); + unsigned curSectionIdx = 0; + + // for each location + for(unsigned i=0; ilocN; ++i) + { + loc_t* loc = p->locA + i; + assert(loc->index == i ); + + // for each event assigned to this location + for(unsigned j=0; jevtCnt; ++j) + { + unsigned event_idx = loc->evtArray[j]->index; + rpt_event_t* r = rptA + event_idx; + + // store the event + r->event = p->eventA + event_idx; + r->loc = loc; + + assert( r->event->index == event_idx ); + assert( r->event->barNumb == loc->barNumb ); + + // if this event is the first event in the next section + if( curSectionIdx < p->sectionN-1 && r->event->index == p->sectionA[ curSectionIdx+1 ].begEvtIndex ) + curSectionIdx += 1; + + r->section = p->sectionA + curSectionIdx; + + } } - // allocate the event array - p->eventA = mem::allocZ(p->eventAllocN); - - do + for(unsigned i=0; isetN; ++i) { - cur_line_idx = cur_line_index(csvH); - - // advance the CSV line cursor - switch(rc = next_line(csvH)) + set_t* set = p->setA + i; + for(unsigned j=0; jeleCnt; ++j) { - case kOkRC: - { - // verify that there is an available slot in the event array - if( p->eventN >= p->eventAllocN ) - { - rc = cwLogError(kBufTooSmallRC,"The event buffer is too small."); - goto errLabel; - } - - event_t* e = p->eventA + p->eventN; - e->index = p->eventN; - e->line = cur_line_idx; - e->csvRowNumb = cur_line_idx+1; - - if((rc = _parse_csv_row(p, csvH, e, curBarNumb, curBarNoteIdx )) != kOkRC ) - goto errLabel; - - - p->eventN += 1; - } - break; - - case kEofRC: - break; - - default: - rc = cwLogError(rc,"CSV line iteration error on CSV event parse."); - goto errLabel; + event_t* e = set->eleArray[j]; + rpt_event_t* r = rptA + e->index; + assert( r->setA[ set->varId ] == nullptr ); + r->setA[ set->varId ] = set; } - - }while( rc != kEofRC ); - - rc = kOkRC; - - errLabel: - if( rc != kOkRC ) - rc = cwLogError(rc,"CSV parse failed on row number:%i.",cur_line_idx+1); - - return rc; - } - - // scan the CSV and count the total number of sections - rc_t _get_section_count( csv::handle_t csvH, unsigned& sectionCntRef ) - { - rc_t rc = kOkRC ; - unsigned cur_line_idx = 0; - unsigned n = 0; - - sectionCntRef = 0; - do - { - cur_line_idx = cur_line_index(csvH); - - // advance the CSV line cursor - switch(rc = next_line(csvH)) - { - case kEofRC: - break; - - case kOkRC: - { - const char* sectionLabel = nullptr; - if((rc = getv(csvH,"section",sectionLabel)) != kOkRC ) - { - rc = cwLogError(rc,"Error parsing section field."); - goto errLabel; - } - - if( sectionLabel != nullptr ) - n += 1; - } - break; - - default: - rc = cwLogError(rc,"CSV line iteration failed."); - } - - } while( rc != kEofRC ); - - rc = kOkRC; - - sectionCntRef = n; - - errLabel: - if( rc != kOkRC ) - rc = cwLogError(rc,"Section count calculation failed on line index:%i.",cur_line_idx); - - return rc; - } - - // scan the CSV and create a record for every section - rc_t _parse_section_events(sfscore_t* p, csv::handle_t csvH, unsigned sectionCnt ) - { - rc_t rc = kOkRC; - unsigned cur_line_idx = 0; - - p->sectionAllocN = sectionCnt; - p->sectionN = 0; - p->sectionA = mem::allocZ(sectionCnt); - - do - { - cur_line_idx = cur_line_index(csvH); - - // advance the CSV line cursor - switch(rc = next_line(csvH)) - { - case kEofRC: - break; - - case kOkRC: - { - section_t* section = nullptr; - const char* sectionLabel = nullptr; - - // read the section column - if((rc = getv(csvH,"section",sectionLabel)) != kOkRC ) - { - rc = cwLogError(rc,"Error parsing section field."); - goto errLabel; - } - - // if the section column is not blank - if( sectionLabel != nullptr && textLength(sectionLabel)>0) - { - // verify that this section was not already created - if((section = _find_section(p,sectionLabel)) != nullptr ) - { - rc = cwLogError(kInvalidIdRC,"Multiple sections have the id '%s'.",sectionLabel); - goto errLabel; - } - else - { - // verify that an available slot exists to store the new section reocrd - if(p->sectionN >= p->sectionAllocN ) - { - rc = cwLogError(kBufTooSmallRC,"The section array is too small. The section count estimation is incomplete."); - goto errLabel; - } - - // create the section record - section = p->sectionA + p->sectionN; - section->label = mem::duplStr(sectionLabel); - section->index = p->sectionN; - section->begEvtIndex = kInvalidIdx; - vop::fill(section->vars,kScVarCnt,DBL_MAX); - p->sectionN += 1; - } - } - } - break; - default: - rc = cwLogError(rc,"CSV line iteration failed."); - } - - } while( rc != kEofRC ); - - rc = kOkRC; - - errLabel: - if( rc != kOkRC ) - rc = cwLogError(rc,"Section event parse failed on line index:%i.",cur_line_idx); - - return rc; - } - - rc_t _parse_sections(sfscore_t* p,csv::handle_t csvH) - { - rc_t rc; - unsigned sectionCnt = 0; - - if((rc = _get_section_count(csvH, sectionCnt )) != kOkRC ) - goto errLabel; - - if((rc = rewind(csvH)) != kOkRC ) - goto errLabel; - - if((rc = _parse_section_events(p,csvH,sectionCnt)) != kOkRC ) - goto errLabel; - - errLabel: - if(rc != kOkRC ) - rc = cwLogError(rc,"Section parse failed."); - return rc; - } - - - rc_t _parse_csv( sfscore_t* p, const char* fname ) - { - rc_t rc = kOkRC; - const char* titleA[] = { "id","trk","evt","opcode","dticks","micros","status","meta", - "ch","d0","d1","arg0","arg1","bar","skip","even","grace", - "tempo","t_frac","dyn","section","play_recd","remark" }; - unsigned titleN = sizeof(titleA)/sizeof(titleA[0]); - csv::handle_t csvH; - - // open the CSV file and validate the title row - if((rc = create( csvH, fname, titleA, titleN )) != kOkRC ) - { - rc = cwLogError(rc,"Score CSV parse failed on '%s'.",fname); - goto errLabel; } - // create p->sectionA[] - if((rc = _parse_sections(p,csvH)) != kOkRC ) - goto errLabel; - - if((rc = rewind(csvH)) != kOkRC ) - goto errLabel; - - // create p->eventA[] - if((rc = _parse_csv_events(p,csvH)) != kOkRC ) - goto errLabel; - - errLabel: - if(rc != kOkRC ) - rc = cwLogError(rc,"CSV parse failed on '%s'.",fname); - destroy(csvH); - return rc; + return rptA; + } + + rc_t _report( sfscore_t* p ) + { + rc_t rc = kOkRC; + + rpt_event_t* rptA = nullptr; + + if((rptA = _report_create(p)) != nullptr ) + { + + _report_print(p,rptA,p->eventN); + mem::release(rptA); + } + + + return rc; } - */ } } @@ -840,6 +442,19 @@ cw::rc_t cw::sfscore::create( handle_t& hRef, rc = cwLogError(rc,"sfscore parse failed."); goto errLabel; } + + if((rc = _create_event_array( p )) != kOkRC ) + goto errLabel; + + if((rc = _create_loc_array( p )) != kOkRC ) + goto errLabel; + + if((rc = _create_section_array( p )) != kOkRC ) + goto errLabel; + + if((rc = _create_set_array( p )) != kOkRC ) + goto errLabel; + hRef.set(p); @@ -879,22 +494,95 @@ unsigned cw::sfscore::event_count( handle_t h ) return p->eventN; } +cw::sfscore::event_t* cw::sfscore::event( handle_t h, unsigned idx ) +{ + sfscore_t* p = _handleToPtr(h); + return p->eventA + idx; +} + +unsigned cw::sfscore::loc_count( handle_t h ) +{ + sfscore_t* p = _handleToPtr(h); + return p->locN; +} + +cw::sfscore::loc_t* cw::sfscore::loc( handle_t h, unsigned idx ) +{ + sfscore_t* p = _handleToPtr(h); + return p->locA + idx; +} + +cw::rc_t cw::sfscore::parse_dyn_ref_cfg( const object_t* cfg, dyn_ref_t*& refArrayRef, unsigned& refArrayNRef) +{ + rc_t rc = kOkRC; + dyn_ref_t* dynRefA = nullptr; + + refArrayRef = nullptr; + refArrayNRef = 0; + + // parse the dynamics ref. array + unsigned dynRefN = cfg->child_count(); + + if( dynRefN == 0 ) + cwLogWarning("The dynamic reference array cfg. is empty."); + else + { + dynRefA = mem::allocZ(dynRefN); + + for(unsigned i=0; ichild_ele(i); + + if( !pair->is_pair() || pair->pair_label()==nullptr || pair->pair_value()==nullptr || pair->pair_value()->value( dynRefA[i].vel)!=kOkRC ) + { + rc = cwLogError(kSyntaxErrorRC,"Error parsing the dynamics reference array."); + goto errLabel; + } + + dynRefA[i].label = pair->pair_label(); + } + } + + + errLabel: + if( rc != kOkRC ) + mem::release(dynRefA); + else + { + refArrayRef = dynRefA; + refArrayNRef = dynRefN; + } + + return rc; +} + + void cw::sfscore::report( handle_t h ) { sfscore_t* p = _handleToPtr(h); - report(p->parserH); + if( p->parserH.isValid() ) + { + //printf("Score Parser Report\n"); + //report(p->parserH); + } + + printf("Score Report\n"); + _report(p); + + + } cw::rc_t cw::sfscore::test( const object_t* cfg ) { - rc_t rc = kOkRC; - const char* cm_score_fname = nullptr; - const object_t* dynArrayNode = nullptr; - dyn_ref_t* dynRefA = nullptr; - unsigned dynRefN = 0; - double srate = 0; - handle_t h; - time::spec_t t0; + rc_t rc = kOkRC; + const char* cm_score_fname = nullptr; + const object_t* dynArrayNode = nullptr; + dyn_ref_t* dynRefA = nullptr; + unsigned dynRefN = 0; + double srate = 0; + handle_t h; + time::spec_t t0; // parse the test cfg @@ -906,24 +594,12 @@ cw::rc_t cw::sfscore::test( const object_t* cfg ) goto errLabel; } - // parse the dynamics ref. array - dynRefN = dynArrayNode->child_count(); - dynRefA = mem::allocZ(dynRefN); - - for(unsigned i=0; ichild_ele(i); - - if( !pair->is_pair() || pair->pair_label()==nullptr || pair->pair_value()==nullptr || pair->pair_value()->value( dynRefA[i].vel)!=kOkRC ) - { - rc = cwLogError(kSyntaxErrorRC,"Error parsing the dynamics reference array."); - goto errLabel; - } - - dynRefA[i].label = pair->pair_label(); + rc = cwLogError(rc,"The reference dynamics array parse failed."); + goto errLabel; } - time::get(t0); if((rc = create(h,cm_score_fname,srate,dynRefA,dynRefN)) != kOkRC ) diff --git a/cwSfScore.h b/cwSfScore.h index a232011..e96a414 100644 --- a/cwSfScore.h +++ b/cwSfScore.h @@ -32,7 +32,7 @@ namespace cw kDynScFl = 0x002, // This note is marked for dynamics measurement kTempoScFl = 0x004, // This note is marked for tempo measurement //kSkipScFl = 0x008, // This isn't a real event (e.g. tied note) skip over it - //kGraceScFl = 0x010, // This is a grace note + kGraceScFl = 0x010, // This is a grace note kInvalidScFl = 0x020, // This note has a calculated time //kPedalDnScFl = 0x040, // This is a pedal down event (pitch holds the pedal id and durSecs holds the time the pedal will remain down.) //kPedalUpScFl = 0x080, // This is a pedal up event (pitch holds the pedal id) @@ -96,6 +96,7 @@ namespace cw // (e.g. eveness, tempo, dynamcs ... ) typedef struct set_str { + unsigned id; // Unique id for this set unsigned varId; // See kXXXVarScId flags above event_t** eleArray; // Events that make up this set in time order unsigned eleCnt; // @@ -154,7 +155,13 @@ namespace cw rc_t destroy( handle_t& h ); unsigned event_count( handle_t h ); + event_t* event( handle_t h, unsigned idx ); + unsigned loc_count( handle_t h ); + loc_t* loc( handle_t h, unsigned idx ); + + rc_t parse_dyn_ref_cfg( const object_t* cfg, dyn_ref_t*& refArrayRef, unsigned& refArrayNRef); + void report( handle_t h );