cwSfScore.h/cpp, cwSfScoreParser.h/cpp, Makefile.am : Initial commmit.
This commit is contained in:
parent
39599e3e2e
commit
3fa4acceee
@ -67,8 +67,11 @@ libcwSRC += src/libcw/cwIoMidiRecordPlay.cpp src/libcw/cwIoAudioRecordPlay.cpp
|
||||
libcwHDR += src/libcw/cwIoPresetSelApp.h src/libcw/cwPianoScore.h src/libcw/cwPresetSel.h src/libcw/cwVelTableTuner.h
|
||||
libcwSRC += src/libcw/cwIoPresetSelApp.cpp src/libcw/cwPianoScore.cpp src/libcw/cwPresetSel.cpp src/libcw/cwVelTableTuner.cpp
|
||||
|
||||
libcwHDR += src/libcw/cwCmInterface.h src/libcw/cwScoreFollower.h src/libcw/cwScoreFollowerPerf.h src/libcw/cwMidiState.h src/libcw/cwSvgMidi.h src/libcw/cwSvgScoreFollow.h
|
||||
libcwSRC += src/libcw/cwCmInterface.cpp src/libcw/cwScoreFollower.cpp src/libcw/cwMidiState.cpp src/libcw/cwSvgMidi.cpp src/libcw/cwSvgScoreFollow.cpp
|
||||
libcwHDR += src/libcw/cwCmInterface.h src/libcw/cwScoreFollower.h src/libcw/cwSfScoreParser.h src/libcw/cwSfScore.h
|
||||
libcwSRC += src/libcw/cwCmInterface.cpp src/libcw/cwScoreFollower.cpp src/libcw/cwSfScoreParser.cpp src/libcw/cwSfScore.cpp
|
||||
|
||||
libcwHDR += src/libcw/cwScoreFollowerPerf.h src/libcw/cwMidiState.h src/libcw/cwSvgMidi.h src/libcw/cwSvgScoreFollow.h
|
||||
libcwSRC += src/libcw/cwMidiState.cpp src/libcw/cwSvgMidi.cpp src/libcw/cwSvgScoreFollow.cpp
|
||||
|
||||
endif
|
||||
|
||||
|
943
cwSfScore.cpp
Normal file
943
cwSfScore.cpp
Normal file
@ -0,0 +1,943 @@
|
||||
#include "cwCommon.h"
|
||||
#include "cwLog.h"
|
||||
#include "cwCommonImpl.h"
|
||||
#include "cwMem.h"
|
||||
#include "cwText.h"
|
||||
#include "cwObject.h"
|
||||
#include "cwMidi.h"
|
||||
#include "cwFileSys.h"
|
||||
#include "cwSfScore.h"
|
||||
#include "cwCsv.h"
|
||||
#include "cwNumericConvert.h"
|
||||
#include "cwTime.h"
|
||||
#include "cwVectOps.h"
|
||||
#include "cwSfScoreParser.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, "<invalid>" }
|
||||
};
|
||||
|
||||
varMap_t _varMapA[] =
|
||||
{
|
||||
{ kEvenVarScId, kEvenScFl, "e"},
|
||||
{ kDynVarScId, kDynScFl, "d"},
|
||||
{ kTempoVarScId,kTempoScFl,"t"},
|
||||
{ kInvalidId, 0, "<invalid>"}
|
||||
};
|
||||
*/
|
||||
|
||||
typedef struct sfscore_str
|
||||
{
|
||||
//dynRef_t* dynRefA;
|
||||
//unsigned dynRefN;
|
||||
|
||||
parser::handle_t parserH;
|
||||
|
||||
event_t* eventA;
|
||||
unsigned eventN;
|
||||
unsigned eventAllocN;
|
||||
|
||||
set_t* setL;
|
||||
|
||||
section_t* sectionA;
|
||||
unsigned sectionN;
|
||||
unsigned sectionAllocN;
|
||||
|
||||
} sfscore_t;
|
||||
|
||||
sfscore_t* _handleToPtr( handle_t h )
|
||||
{ return handleToPtr<handle_t,sfscore_t>(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; i<p->dynRefN; ++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 )
|
||||
{
|
||||
mem::release(s->eleArray);
|
||||
mem::release(s->sectArray);
|
||||
mem::release(s);
|
||||
}
|
||||
|
||||
void _destroy_section( section_t* s )
|
||||
{
|
||||
char* ss = (char*)(s->label);
|
||||
mem::release(ss);
|
||||
}
|
||||
|
||||
rc_t _destroy( sfscore_t* p )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
|
||||
set_t* s = p->setL;
|
||||
while( s!= nullptr )
|
||||
{
|
||||
set_t* s0 = s->llink;
|
||||
_destroy_set(s);
|
||||
s=s0;
|
||||
}
|
||||
|
||||
for(unsigned i=0; i<p->sectionN; ++i)
|
||||
_destroy_section( p->sectionA + i );
|
||||
mem::release(p->sectionA);
|
||||
|
||||
mem::release(p->eventA);
|
||||
|
||||
/*
|
||||
for(unsigned i=0; i<p->dynRefN; ++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 rc = kOkRC;
|
||||
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 )
|
||||
{
|
||||
unsigned n = 0;
|
||||
event_t* e0 = end_set_evt;
|
||||
|
||||
begEvtRef = nullptr;
|
||||
|
||||
for(; e0>=p->eventA; --e0)
|
||||
if( cwIsFlag(e0->flags,varTypeFlag) )
|
||||
{
|
||||
if( e0 == prev_end_evt )
|
||||
break;
|
||||
|
||||
++n;
|
||||
begEvtRef = e0;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
// 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 )
|
||||
{
|
||||
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 ];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
section_t* _find_section(sfscore_t* p, const char* sectionLabel )
|
||||
{
|
||||
for(unsigned i=0; i<p->sectionN; ++i)
|
||||
if( textIsEqual(p->sectionA[i].label,sectionLabel) )
|
||||
return p->sectionA + i;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rc_t _connect_section_to_set( sfscore_t* p, set_t* set, const char* section_label )
|
||||
{
|
||||
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<section_t*>(set->sectArray,set->sectCnt);
|
||||
set->sectArray[ set->sectCnt-1 ] = section;
|
||||
|
||||
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 )
|
||||
{
|
||||
rc = cwLogError(kOpFailRC,"Unable to locate the '%s' var set.",_varTypeFlagToLabel(varTypeFlag));
|
||||
goto errLabel;
|
||||
}
|
||||
else
|
||||
{
|
||||
set_t* set = mem::allocZ<set_t>();
|
||||
unsigned i;
|
||||
|
||||
set->varId = _varFlagToTypeId(varTypeFlag);
|
||||
set->eleCnt = set_eventN;
|
||||
set->eleArray = mem::allocZ<event_t*>(set_eventN);
|
||||
|
||||
// assign section to set
|
||||
if((rc = _connect_section_to_set(p,set,section_label)) != kOkRC )
|
||||
{
|
||||
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( 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',<dyn mark> (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;
|
||||
}
|
||||
|
||||
switch( e->type )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
rc = cwLogError(kSyntaxErrorRC,"The section label '%s' could not be found.",cwStringNullGuard(sectionLabel));
|
||||
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;
|
||||
}
|
||||
|
||||
// assign a starting event index to this event
|
||||
section->begEvtIndex = e->index;
|
||||
}
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc_t _parse_csv_events( sfscore_t* p, csv::handle_t csvH )
|
||||
{
|
||||
rc_t rc;
|
||||
unsigned cur_line_idx = 0;
|
||||
unsigned curBarNumb = kInvalidId;
|
||||
unsigned curBarNoteIdx = 0;
|
||||
|
||||
// get the line count from the CSV file
|
||||
if((rc = line_count(csvH,p->eventAllocN)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"Score CSV line count failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// allocate the event array
|
||||
p->eventA = mem::allocZ<event_t>(p->eventAllocN);
|
||||
|
||||
do
|
||||
{
|
||||
cur_line_idx = cur_line_index(csvH);
|
||||
|
||||
// advance the CSV line cursor
|
||||
switch(rc = next_line(csvH))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}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<section_t>(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;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
cw::rc_t cw::sfscore::create( handle_t& hRef,
|
||||
const char* fname,
|
||||
double srate,
|
||||
const dyn_ref_t* dynRefA,
|
||||
unsigned dynRefN )
|
||||
{
|
||||
rc_t rc;
|
||||
|
||||
if((rc = destroy(hRef)) != kOkRC )
|
||||
return rc;
|
||||
|
||||
sfscore_t* p = mem::allocZ<sfscore_t>();
|
||||
|
||||
if((rc = parser::create(p->parserH,fname,dynRefA,dynRefN)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"sfscore parse failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
hRef.set(p);
|
||||
|
||||
errLabel:
|
||||
if( rc != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"sfscore create failed.");
|
||||
_destroy(p);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::sfscore::destroy( handle_t& hRef )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
if(!hRef.isValid())
|
||||
return rc;
|
||||
|
||||
sfscore_t* p = _handleToPtr(hRef);
|
||||
|
||||
if((rc = _destroy(p)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"Destroy failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
hRef.clear();
|
||||
|
||||
errLabel:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
unsigned cw::sfscore::event_count( handle_t h )
|
||||
{
|
||||
sfscore_t* p = _handleToPtr(h);
|
||||
return p->eventN;
|
||||
}
|
||||
|
||||
void cw::sfscore::report( handle_t h )
|
||||
{
|
||||
sfscore_t* p = _handleToPtr(h);
|
||||
report(p->parserH);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
// parse the test cfg
|
||||
if((rc = cfg->getv( "cm_score_fname", cm_score_fname,
|
||||
"srate", srate,
|
||||
"dyn_ref", dynArrayNode )) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"sfscore test parse params failed on.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// parse the dynamics ref. array
|
||||
dynRefN = dynArrayNode->child_count();
|
||||
dynRefA = mem::allocZ<dyn_ref_t>(dynRefN);
|
||||
|
||||
for(unsigned i=0; i<dynRefN; ++i)
|
||||
{
|
||||
const object_t* pair = dynArrayNode->child_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();
|
||||
}
|
||||
|
||||
|
||||
time::get(t0);
|
||||
|
||||
if((rc = create(h,cm_score_fname,srate,dynRefA,dynRefN)) != kOkRC )
|
||||
{
|
||||
rc = cwLogError(rc,"Score test create failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
report(h);
|
||||
|
||||
printf("%i events %i ms\n",event_count(h), time::elapsedMs(t0) );
|
||||
|
||||
errLabel:
|
||||
destroy(h);
|
||||
mem::release(dynRefA);
|
||||
return rc;
|
||||
}
|
168
cwSfScore.h
Normal file
168
cwSfScore.h
Normal file
@ -0,0 +1,168 @@
|
||||
#ifndef cwSfScore_h
|
||||
#define cwSfScore_h
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace sfscore
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
kInvalidEvtScId = 0,
|
||||
kTimeSigEvtScId,
|
||||
kKeySigEvtScId,
|
||||
kTempoEvtScId,
|
||||
kTrackEvtScId,
|
||||
kTextEvtScId,
|
||||
kNameEvtScId,
|
||||
kEOTrackEvtScId,
|
||||
kCopyEvtScId,
|
||||
kBlankEvtScId,
|
||||
kBarEvtScId,
|
||||
kPgmEvtScId,
|
||||
kCtlEvtScId,
|
||||
kNonEvtScId,
|
||||
kPedalEvtScId
|
||||
};
|
||||
|
||||
// Flags used by event_t.flags
|
||||
enum
|
||||
{
|
||||
kEvenScFl = 0x001, // This note is marked for evenness measurement
|
||||
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
|
||||
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)
|
||||
};
|
||||
|
||||
|
||||
// Id's used by set_t.varId and as indexes into
|
||||
// section_t.vars[].
|
||||
enum
|
||||
{
|
||||
kInvalidVarScId = 0, // 0
|
||||
kMinVarScId = 1,
|
||||
kEvenVarScId = kMinVarScId, // 1
|
||||
kDynVarScId = 2, // 2
|
||||
kTempoVarScId = 3, // 3
|
||||
kScVarCnt = 4
|
||||
};
|
||||
|
||||
enum : uint8_t {
|
||||
kInvalidDynVel = 0
|
||||
};
|
||||
|
||||
struct loc_str;
|
||||
struct set_str;
|
||||
|
||||
// The score can be divided into arbitrary non-overlapping sections.
|
||||
typedef struct section_str
|
||||
{
|
||||
const char* label; // section label
|
||||
unsigned index; // index of this record in the internal section array
|
||||
struct loc_str* locPtr; // location where this section starts
|
||||
unsigned begEvtIndex; // score element index where this section starts
|
||||
unsigned setCnt; // Count of elements in setArray[]
|
||||
struct set_str** setArray; // Ptrs to sets which are applied to this section.
|
||||
double vars[ kScVarCnt ]; // Set to DBL_MAX by default.
|
||||
} section_t;
|
||||
|
||||
typedef struct event_str
|
||||
{
|
||||
unsigned type; // Event type
|
||||
double secs; // Time location in seconds
|
||||
double durSecs; // Duration in seconds
|
||||
unsigned index; // Index of this event in the event array.
|
||||
unsigned locIdx; // Index of the location 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 vel; // MIDI velocity of this note
|
||||
unsigned flags; // Attribute flags for this event
|
||||
unsigned dynVal; // Dynamcis value pppp to ffff (1 to 11) for this note.
|
||||
double frac; // Note's time value for tempo and non-grace evenness notes.
|
||||
unsigned barNumb; // Bar id of the measure containing this event.
|
||||
unsigned barNoteIdx; // Index of this note in this bar
|
||||
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 csvEventId; // EventId from CSV 'evt' column.
|
||||
} event_t;
|
||||
|
||||
// A 'set' is a collection of events that are grouped in time and all marked with a given attribute.
|
||||
// (e.g. eveness, tempo, dynamcs ... )
|
||||
typedef struct set_str
|
||||
{
|
||||
unsigned varId; // See kXXXVarScId flags above
|
||||
event_t** eleArray; // Events that make up this set in time order
|
||||
unsigned eleCnt; //
|
||||
section_t** sectArray; // Sections this set will be applied to
|
||||
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
|
||||
} 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
|
||||
// locc_t record.
|
||||
typedef struct loc_str
|
||||
{
|
||||
unsigned index; // index of this location record
|
||||
double secs; // Time of this location
|
||||
unsigned evtCnt; // Count of events in evtArray[].
|
||||
event_t** evtArray; // Events which occur at this time.
|
||||
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)
|
||||
section_t* begSectPtr; // NULL if this location does not start a section
|
||||
marker_t* markList; // List of markers assigned to this location
|
||||
} loc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* label;
|
||||
uint8_t vel;
|
||||
} dyn_ref_t;
|
||||
|
||||
typedef handle<struct sfscore_str> handle_t;
|
||||
|
||||
rc_t create( handle_t& h, const char* fname, double srate, const dyn_ref_t* dynRefA=nullptr, unsigned dynRefN=0 );
|
||||
rc_t destroy( handle_t& h );
|
||||
|
||||
unsigned event_count( handle_t h );
|
||||
|
||||
void report( handle_t h );
|
||||
|
||||
|
||||
rc_t test( const object_t* cfg );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
1105
cwSfScoreParser.cpp
Normal file
1105
cwSfScoreParser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
106
cwSfScoreParser.h
Normal file
106
cwSfScoreParser.h
Normal file
@ -0,0 +1,106 @@
|
||||
#ifndef cwSfScoreParser_h
|
||||
#define cwSfScoreParser_h
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace sfscore
|
||||
{
|
||||
|
||||
enum {
|
||||
kEvenFl = 0x0001,
|
||||
kEvenEndFl = 0x0002,
|
||||
kDynFl = 0x0004,
|
||||
kDynEndFl = 0x0008,
|
||||
kTempoFl = 0x0010,
|
||||
kTempoEndFl = 0x0020,
|
||||
|
||||
kFlagMask = 0x003f
|
||||
};
|
||||
|
||||
|
||||
unsigned opcode_label_to_id( const char* label );
|
||||
const char* opcode_id_to_label( unsigned opcode_id );
|
||||
|
||||
unsigned var_label_to_type_id( const char* label );
|
||||
unsigned var_label_to_type_flag( const char* label );
|
||||
const char* var_type_id_to_label( unsigned varTypeId );
|
||||
const char* var_type_flag_to_label( unsigned varTypeFlag );
|
||||
char var_type_flag_to_char( unsigned varTypeFlag );
|
||||
unsigned var_type_id_to_flag( unsigned varTypeId ); // returns type flag
|
||||
unsigned var_type_id_to_mask( unsigned varTypeId ); // returns type flag and end flag mask
|
||||
unsigned var_type_id_to_end_flag( unsigned varTypeId ); // returns end flag
|
||||
unsigned var_type_flag_to_id( unsigned varTypeFlag );
|
||||
|
||||
namespace parser
|
||||
{
|
||||
typedef handle<struct sfscore_parser_str> handle_t;
|
||||
|
||||
typedef struct p_section_str
|
||||
{
|
||||
char* label;
|
||||
unsigned begEvtIdx;
|
||||
unsigned endEvtIdx;
|
||||
struct p_section_str* link;
|
||||
} p_section_t;
|
||||
|
||||
typedef struct p_set_str
|
||||
{
|
||||
unsigned id; //
|
||||
unsigned varTypeId; //
|
||||
p_section_t* target_section; // section to which this set will be applied
|
||||
struct p_event_str* beg_event; // first event in this section
|
||||
unsigned eventN; // count of events in this set
|
||||
struct p_event_str** eventA; // points to each event this set
|
||||
struct p_set_str* link; //
|
||||
} p_set_t;
|
||||
|
||||
|
||||
typedef struct p_event_str
|
||||
{
|
||||
unsigned typeId; // opcode type id
|
||||
unsigned csvEventId; // CSV 'evt' id
|
||||
unsigned csvRowNumb; // CSV line number
|
||||
unsigned line; //
|
||||
unsigned index; // index into eventArray[]
|
||||
double secs; // event offset from beginning of score in seconds
|
||||
double barSecs; // event offset from bar in sectonds
|
||||
unsigned locIdx; // location index (chord notes share the same locIdx)
|
||||
unsigned barNumb; // bar this event belongs to
|
||||
unsigned barNoteIdx; // note index of this note in the bar to which it belongs.
|
||||
p_section_t* section; // section to which this event belongs
|
||||
unsigned sectionIdx; // note index of this note in the section to which it belongs
|
||||
unsigned flags; // attribute flags
|
||||
midi::byte_t pitch;
|
||||
midi::byte_t vel;
|
||||
unsigned dynVal; // index into dynRefA[]
|
||||
double t_frac; //
|
||||
char* sciPitch; //
|
||||
|
||||
char* sectionLabelA[ kScVarCnt ]; // var end section labels (if this event is the last event in a section)
|
||||
p_set_t* setA[ kScVarCnt ]; // set points (if this event is part of a set)
|
||||
|
||||
} p_event_t;
|
||||
|
||||
rc_t create( handle_t& hRef, const char* fname, const dyn_ref_t* dynRefA, unsigned dynRefN );
|
||||
rc_t destroy( handle_t& hRef );
|
||||
|
||||
unsigned event_count( handle_t h );
|
||||
const p_event_t* event_array( handle_t h );
|
||||
|
||||
unsigned section_count( handle_t h );
|
||||
const p_section_t* section_list( handle_t h );
|
||||
|
||||
unsigned set_count( handle_t h );
|
||||
const p_set_t* set_array( handle_t h );
|
||||
|
||||
|
||||
void report( handle_t h );
|
||||
|
||||
rc_t test( const char* fname, const dyn_ref_t* dynRefA, unsigned dynRefN );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user