Merge branch 'master' of klarke.webfactional.com:webapps/git/repos/libcm with

spat lab mac.
This commit is contained in:
kevin 2013-11-19 11:15:12 -08:00
commit c946234fde
17 changed files with 3319 additions and 1438 deletions

View File

@ -6,6 +6,7 @@
#include "cmCtx.h" #include "cmCtx.h"
#include "cmMem.h" #include "cmMem.h"
#include "cmMallocDebug.h" #include "cmMallocDebug.h"
#include "cmLinkedHeap.h"
#include "cmMidi.h" #include "cmMidi.h"
#include "cmLex.h" #include "cmLex.h"
#include "cmCsv.h" #include "cmCsv.h"
@ -13,6 +14,7 @@
#include "cmMidiFile.h" #include "cmMidiFile.h"
#include "cmAudioFile.h" #include "cmAudioFile.h"
#include "cmTimeLine.h" #include "cmTimeLine.h"
#include "cmText.h"
#include "cmScore.h" #include "cmScore.h"
#include "cmVectOpsTemplateMain.h" #include "cmVectOpsTemplateMain.h"
@ -41,7 +43,8 @@ enum
kFracColScIdx = 18, kFracColScIdx = 18,
kDynColScIdx = 19, kDynColScIdx = 19,
kSectionColScIdx = 20, kSectionColScIdx = 20,
kRemarkColScIdx = 21 kRecdPlayColScIdx = 21,
kRemarkColScIdx = 22
}; };
@ -75,6 +78,15 @@ typedef struct cmScSet_str
struct cmScSet_str* link; // struct cmScSet_str* link; //
} cmScSet_t; } cmScSet_t;
typedef struct cmScMark_str
{
cmMarkScMId_t cmdId;
unsigned labelSymId;
unsigned scoreIdx;
unsigned csvRowIdx;
struct cmScMark_str* link;
} cmScMark_t;
typedef struct typedef struct
{ {
cmErr_t err; cmErr_t err;
@ -94,11 +106,15 @@ typedef struct
cmScoreSection_t* sect; cmScoreSection_t* sect;
unsigned sectCnt; unsigned sectCnt;
unsigned* markLabelArray; // one symId per unique cmScoreMarker_t.labelSymId;
unsigned markLabelCnt;
unsigned sciPitchLexTId; // sci pitch and section id lexer token id's unsigned sciPitchLexTId; // sci pitch and section id lexer token id's
unsigned sectionLexTId; unsigned sectionLexTId;
cmScSect_t* sectList; // lists used during parsing cmScSect_t* sectList; // lists used during parsing
cmScSet_t* setList; cmScSet_t* setList;
cmScMark_t* markList;
cmScoreSet_t* sets; cmScoreSet_t* sets;
unsigned setCnt; unsigned setCnt;
@ -313,6 +329,17 @@ unsigned _cmScLexSectionIdMatcher( const cmChar_t* cp, unsigned cn )
return 0; return 0;
} }
void _cmScFreeMarkList( cmScMark_t* markList )
{
cmScMark_t* mp = markList;
while( mp!=NULL )
{
cmScMark_t* np = mp->link;
cmMemFree(mp);
mp = np;
}
}
void _cmScFreeSetList( cmScSet_t* setList ) void _cmScFreeSetList( cmScSet_t* setList )
{ {
cmScSet_t* tp = setList; cmScSet_t* tp = setList;
@ -366,6 +393,8 @@ cmScRC_t _cmScFinalize( cmSc_t* p )
_cmScFreeSetList(p->setList); _cmScFreeSetList(p->setList);
_cmScFreeMarkList(p->markList);
if( p->loc != NULL ) if( p->loc != NULL )
{ {
for(i=0; i<p->locCnt; ++i) for(i=0; i<p->locCnt; ++i)
@ -373,12 +402,23 @@ cmScRC_t _cmScFinalize( cmSc_t* p )
cmMemFree(p->loc[i].evtArray); cmMemFree(p->loc[i].evtArray);
if( p->loc[i].begSectPtr != NULL ) if( p->loc[i].begSectPtr != NULL )
cmMemFree(p->loc[i].begSectPtr->setArray); cmMemFree(p->loc[i].begSectPtr->setArray);
// free the marker list assoc'd with this location
cmScoreMarker_t* smp = p->loc[i].markList;
while( smp!=NULL )
{
cmScoreMarker_t* np = smp->link;
cmMemFree(smp);
smp = np;
}
} }
cmMemFree(p->loc); cmMemFree(p->loc);
} }
cmMemPtrFree(&p->dynRefArray); cmMemPtrFree(&p->dynRefArray);
cmMemFree(p->markLabelArray);
cmMemFree(p->sect); cmMemFree(p->sect);
cmMemFree(p->fn); cmMemFree(p->fn);
cmMemFree(p->array); cmMemFree(p->array);
@ -557,6 +597,79 @@ cmScRC_t _cmScParseAttr(cmSc_t* p, unsigned scoreIdx, const cmChar_t* text, unsi
return kOkScRC; return kOkScRC;
} }
// Parse a record/playback string
cmScRC_t _cmScParseMarkers( cmSc_t* p, unsigned scoreIdx, const cmChar_t* text, unsigned rowIdx )
{
const cmChar_t* cp = text;
const cmChar_t* ip;
const cmChar_t* ep;
// if no symbol table has been registered then don't bother storing markers.
// (NOTE - THIS IS A HACK BECAUSE THE SCORE OBJECT USED IN THE cmdIf DOES NOT HAVE
// A SYMBOL TABLE - WE COULD EASILY ADD ONE IF IT EVENTUALLY NEEDS ACCESS TO THE MARKERS
// - OR A SYMBOL TABLE COULD BE ADDED TO THE SCORE ITSELF.)
if( cmSymTblIsValid(p->stH) == false )
return kOkScRC;
// go to command/id space
if((ip = cmTextNextWhiteOrEosC(text)) == NULL )
goto errLabel;
// goto label
if((ip = cmTextNextNonWhiteC(ip)) == NULL )
goto errLabel;
// goto end of label
if((ep = cmTextNextWhiteOrEosC(ip)) == NULL )
goto errLabel;
else
{
unsigned n = (ep-ip)+1;
cmChar_t markTextStr[n+1];
strncpy(markTextStr,ip,n);
// for each command code
// (there may be more than one character)
for(; *cp && !isspace(*cp); ++cp)
{
cmMarkScMId_t cmdId = kInvalidScMId;
switch( *cp )
{
case 'c': cmdId = kRecdBegScMId; break;
case 'e': cmdId = kRecdEndScMId; break;
case 'p': cmdId = kPlayBegScMId; break;
case 'd': cmdId = kPlayEndScMId; break;
case 'f': cmdId = kFadeScMId; break;
default:
return cmErrMsg(&p->err,kSyntaxErrScRC,"Unrecognized marker command character '%c' at row index %i.",*cp,rowIdx);
}
cmScMark_t* mp = cmMemAllocZ(cmScMark_t,1);
mp->cmdId = cmdId;
mp->labelSymId = cmSymTblRegisterSymbol(p->stH,markTextStr);
mp->scoreIdx = scoreIdx;
mp->csvRowIdx = rowIdx;
// insert the new mark at the end of the list
if( p->markList == NULL )
p->markList = mp;
else
{
cmScMark_t* ep = p->markList;
while( ep->link != NULL )
ep = ep->link;
ep->link = mp;
}
}
}
return kOkScRC;
errLabel:
return cmErrMsg(&p->err,kSyntaxErrScRC,"Invalid record/playback field ('%s') on row index:%i.",cmStringNullGuard(text),rowIdx);
}
void _cmScPrintSets( const cmChar_t* label, cmScSet_t* setList ) void _cmScPrintSets( const cmChar_t* label, cmScSet_t* setList )
{ {
printf("%s\n",label); printf("%s\n",label);
@ -598,7 +711,7 @@ cmScRC_t _cmScParseNoteOn( cmSc_t* p, unsigned rowIdx, cmScoreEvt_t* s, unsigned
return cmErrMsg(&p->err,kSyntaxErrScRC,"Expected a scientific pitch value"); return cmErrMsg(&p->err,kSyntaxErrScRC,"Expected a scientific pitch value");
if((midiPitch = cmSciPitchToMidi(sciPitch)) == kInvalidMidiPitch) if((midiPitch = cmSciPitchToMidi(sciPitch)) == kInvalidMidiPitch)
return cmErrMsg(&p->err,kSyntaxErrScRC,"Unable to convert the scientific pitch '%s' to a MIDI value. "); return cmErrMsg(&p->err,kSyntaxErrScRC,"Unable to convert the scientific pitch '%s' to a MIDI value. ");
// it is possible that note delta-secs field is empty - so default to 0 // it is possible that note delta-secs field is empty - so default to 0
if((secs = cmCsvCellDouble(p->cH, rowIdx, kSecsColScIdx )) == DBL_MAX) // Returns DBL_MAX on error. if((secs = cmCsvCellDouble(p->cH, rowIdx, kSecsColScIdx )) == DBL_MAX) // Returns DBL_MAX on error.
@ -658,6 +771,14 @@ cmScRC_t _cmScParseNoteOn( cmSc_t* p, unsigned rowIdx, cmScoreEvt_t* s, unsigned
durSecs = 0.25; durSecs = 0.25;
// parse the recd/play markers
if((attr = cmCsvCellText(p->cH,rowIdx,kRecdPlayColScIdx)) != NULL )
{
if((rc = _cmScParseMarkers(p,scoreIdx,attr,rowIdx)) != kOkScRC )
return rc;
}
s->type = kNonEvtScId; s->type = kNonEvtScId;
s->secs = secs; s->secs = secs;
s->pitch = midiPitch; s->pitch = midiPitch;
@ -870,6 +991,8 @@ cmScRC_t _cmScProcSets( cmSc_t* p )
} }
cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList ) cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
{ {
cmScRC_t rc = kOkScRC; cmScRC_t rc = kOkScRC;
@ -935,6 +1058,153 @@ cmScRC_t _cmScProcSections( cmSc_t* p, cmScSect_t* sectList )
return rc; return rc;
} }
const cmScoreLoc_t* _cmScFindMarkLoc( cmSc_t* p, cmMarkScMId_t cmdId, unsigned labelSymId, const cmScoreMarker_t** markRef )
{
unsigned i;
for(i=0; i<p->locCnt; ++i)
{
cmScoreMarker_t* smp = p->loc[i].markList;
for(; smp!=NULL; smp=smp->link)
{
if( smp->markTypeId==cmdId && smp->labelSymId==labelSymId )
return p->loc + i;
if( markRef != NULL )
*markRef = smp;
}
}
return NULL;
}
unsigned _cmScMarkerLabelIndex( cmSc_t* p, unsigned labelSymId )
{
unsigned i;
for(i=0; i<p->markLabelCnt; ++i)
if( p->markLabelArray[i] == labelSymId )
return i;
return cmInvalidIdx;
}
// Verify that the record/play begin/end and fade markers fall in the correct time order.
// (e.g. 'begin' must be before 'end' and 'fade' must be between and 'begin' and 'end').
cmScRC_t _cmScValidateMarkers( cmSc_t* p )
{
cmScRC_t rc = kOkScRC;
unsigned i;
for(i=0; i<p->locCnt; ++i)
{
cmScoreMarker_t* sm0p = p->loc[i].markList;
for(; sm0p!=NULL; sm0p=sm0p->link)
{
const cmScoreLoc_t* sl0p;
const cmScoreLoc_t* sl1p;
switch( sm0p->markTypeId )
{
case kRecdBegScMId:
if((sl0p = _cmScFindMarkLoc(p,kRecdEndScMId, sm0p->labelSymId, NULL )) == NULL )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record begin' marker at CSV row index %i does not have an associated 'record end' marker.",sm0p->csvRowIdx);
else
if( sl0p->index <= p->loc[i].index )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record end' marker comes before associated with the 'record begin' marker at CSV row index %i.",sm0p->csvRowIdx);
break;
case kRecdEndScMId:
if((sl0p = _cmScFindMarkLoc(p,kRecdBegScMId, sm0p->labelSymId, NULL )) == NULL )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record end' marker at CSV row index %i does not have an associated 'record begin' marker.",sm0p->csvRowIdx);
else
if( sl0p->index > p->loc[i].index )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'record begin' marker comes after the associated with the 'record end' marker at CSV row index %i.",sm0p->csvRowIdx);
break;
case kFadeScMId:
if((sl0p = _cmScFindMarkLoc(p,kRecdBegScMId, sm0p->labelSymId, NULL )) == NULL )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i does not have an associated 'record begin' marker.",sm0p->csvRowIdx);
else
if((sl1p = _cmScFindMarkLoc(p,kRecdEndScMId, sm0p->labelSymId, NULL )) == NULL )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i does not have an associated 'record end' marker.",sm0p->csvRowIdx);
else
if( sl0p->index > p->loc[i].index || sl1p->index < p->loc[i].index )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'fade' marker at CSV row index %i is not between it's associated 'record begin' and 'record end' markers.",sm0p->csvRowIdx);
break;
case kPlayBegScMId:
if((sl0p = _cmScFindMarkLoc(p,kPlayEndScMId, sm0p->labelSymId, NULL )) == NULL )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play begin' marker at CSV row index %i does not have an associated 'play end' marker.",sm0p->csvRowIdx);
else
if( sl0p->index <= p->loc[i].index )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play end' marker comes before associated with the 'play begin' marker at CSV row index %i.",sm0p->csvRowIdx);
break;
case kPlayEndScMId:
if((sl0p = _cmScFindMarkLoc(p,kPlayBegScMId, sm0p->labelSymId, NULL )) == NULL )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play end' marker at CSV row index %i does not have an associated 'play begin' marker.",sm0p->csvRowIdx);
else
if( sl0p->index > p->loc[i].index )
rc = cmErrMsg(&p->err,kSyntaxErrScRC,"The 'play begin' marker comes after the associated with the 'play end' marker at CSV row index %i.",sm0p->csvRowIdx);
break;
default:
break;
}
}
}
return rc;
}
cmScRC_t _cmScProcMarkers( cmSc_t* p )
{
// for each marker in the p->markList
// (p->markList is created by _cmScParseMarkers() during CSV file parsing.)
cmScMark_t* mp = p->markList;
for(; mp!=NULL; mp=mp->link)
{
assert( mp->scoreIdx < p->cnt );
// get the score location assoc'd with this marker
unsigned locIdx = p->array[ mp->scoreIdx ].locIdx;
assert( locIdx < p->locCnt );
cmScoreLoc_t* slp = p->loc + locIdx;
// create a cmScoreMarker record.
cmScoreMarker_t* smp = cmMemAllocZ(cmScoreMarker_t,1);
smp->markTypeId = mp->cmdId;
smp->labelSymId = mp->labelSymId;
smp->csvRowIdx = mp->csvRowIdx;
smp->scoreLocPtr = slp;
// attach the new scoreMarker record to the assoc'd score loc. recd
if( slp->markList == NULL )
slp->markList = smp;
else
{
cmScoreMarker_t* sm0p = slp->markList;
while( sm0p->link != NULL )
sm0p = sm0p->link;
sm0p->link = smp;
}
// if the id represented by this marker
if( _cmScMarkerLabelIndex(p,smp->labelSymId) == cmInvalidIdx )
{
p->markLabelArray = cmMemResizeP(unsigned,p->markLabelArray,p->markLabelCnt+1);
p->markLabelArray[p->markLabelCnt] = smp->labelSymId;
p->markLabelCnt += 1;
}
}
// validate the markers
return _cmScValidateMarkers(p);
}
cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn ) cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
{ {
cmScRC_t rc = kOkScRC; cmScRC_t rc = kOkScRC;
@ -1036,27 +1306,30 @@ cmScRC_t _cmScParseFile( cmSc_t* p, cmCtx_t* ctx, const cmChar_t* fn )
break; break;
} }
if( secs != DBL_MAX ) if( rc == kOkScRC )
cur_secs = secs;
// form the section list
if( j > 0 )
if((rc = _cmScParseSectionColumn(p,i,j-1,p->sectList)) != kOkScRC )
break;
// the bar lines don't have times so set the time of the bar line to the
// time of the first event in the bar.
if( barEvtIdx != cmInvalidIdx && secs != DBL_MAX )
{ {
assert( p->array[ barEvtIdx ].type == kBarEvtScId ); if( secs != DBL_MAX )
p->array[ barEvtIdx ].secs = secs; cur_secs = secs;
// handle the case where the previous bar had no events // form the section list
// BUG BUG BUG this is a hack which will fail if the first bar does not have events. if( j > 0 )
if( barEvtIdx>=1 && p->array[ barEvtIdx-1].type == kBarEvtScId ) if((rc = _cmScParseSectionColumn(p,i,j-1,p->sectList)) != kOkScRC )
p->array[ barEvtIdx-1].secs = secs; break;
barEvtIdx = cmInvalidIdx; // the bar lines don't have times so set the time of the bar line to the
// time of the first event in the bar.
if( barEvtIdx != cmInvalidIdx && secs != DBL_MAX )
{
assert( p->array[ barEvtIdx ].type == kBarEvtScId );
p->array[ barEvtIdx ].secs = secs;
// handle the case where the previous bar had no events
// BUG BUG BUG this is a hack which will fail if the first bar does not have events.
if( barEvtIdx>=1 && p->array[ barEvtIdx-1].type == kBarEvtScId )
p->array[ barEvtIdx-1].secs = secs;
barEvtIdx = cmInvalidIdx;
}
} }
} }
@ -1164,6 +1437,9 @@ cmScRC_t cmScoreInitialize( cmCtx_t* ctx, cmScH_t* hp, const cmChar_t* fn, doubl
if((rc = _cmScProcSections(p,p->sectList)) != kOkScRC ) if((rc = _cmScProcSections(p,p->sectList)) != kOkScRC )
goto errLabel; goto errLabel;
if((rc = _cmScProcMarkers(p)) != kOkScRC )
goto errLabel;
// load the dynamic reference array // load the dynamic reference array
if( dynRefArray != NULL && dynRefCnt > 0) if( dynRefArray != NULL && dynRefCnt > 0)
{ {
@ -1409,6 +1685,30 @@ unsigned cmScoreSetCount( cmScH_t h )
return p->setCnt; return p->setCnt;
} }
unsigned cmScoreMarkerLabelCount( cmScH_t h )
{
cmSc_t* p = _cmScHandleToPtr(h);
return p->markLabelCnt;
}
unsigned cmScoreMarkerLabelSymbolId( cmScH_t h, unsigned idx )
{
cmSc_t* p = _cmScHandleToPtr(h);
assert( idx < p->markLabelCnt );
return p->markLabelArray[idx];
}
const cmScoreMarker_t* cmScoreMarker( cmScH_t h, cmMarkScMId_t markMId, unsigned labelSymId )
{
cmSc_t* p = _cmScHandleToPtr(h);
const cmScoreMarker_t* smp = NULL;
if( _cmScFindMarkLoc(p, markMId, labelSymId, &smp ) == NULL )
return NULL;
return smp;
}
cmScRC_t cmScoreSeqNotify( cmScH_t h ) cmScRC_t cmScoreSeqNotify( cmScH_t h )
{ {
cmScRC_t rc = kOkScRC; cmScRC_t rc = kOkScRC;
@ -1502,7 +1802,7 @@ void _cmScPerfSortTimes( unsigned *v, unsigned n )
fl = true; fl = true;
} }
} }
--n; --n;
} }
} }
@ -1568,13 +1868,13 @@ bool _cmScPerfEven(cmSc_t* p, cmScoreSet_t* stp, bool printMissFl)
if(printFl) if(printFl)
{ {
/* /*
for(i=0; i<stp->eleCnt; ++i) for(i=0; i<stp->eleCnt; ++i)
{ {
printf("%i %i ",i,v[i]); printf("%i %i ",i,v[i]);
if( i > 0 ) if( i > 0 )
printf("%i ", d[i-1]); printf("%i ", d[i-1]);
printf("\n"); printf("\n");
} }
*/ */
printf("%s EVENESS:%f\n",sortFl?"SORTED ":"",stp->value); printf("%s EVENESS:%f\n",sortFl?"SORTED ":"",stp->value);
} }
@ -1955,6 +2255,214 @@ void cmScorePrint( cmScH_t h, cmRpt_t* rpt )
} }
} }
cmScRC_t cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* scoreFn )
{
cmScRC_t rc = kOkScRC;
cmMidiFileH_t mfH = cmMidiFileNullHandle;
cmCsvH_t csvH = cmCsvNullHandle;
cmErr_t err;
cmChar_t* titles[] = {"id","trk","evt","opcode","dticks","micros","status","meta","ch","d0","d1","arg0","arg1","bar","skip","even","grace","tempo","t frac","dyn","section","remark", NULL };
cmErrSetup(&err,&ctx->rpt,"MIDI to Score");
if( cmMidiFileOpen(midiFn, &mfH, ctx ) != kOkMfRC )
return cmErrMsg(&err,kMidiFileFailScRC,"Unable to open the MIDI file '%s'.",midiFn);
if( cmCsvInitialize(&csvH,ctx) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Unable to initialize the CSV file: '%s'.",scoreFn);
goto errLabel;
}
// Convert the track message 'dtick' field to delta-microseconds.
cmMidiFileTickToMicros(mfH);
unsigned msgCnt = cmMidiFileMsgCount(mfH);
unsigned i;
const cmMidiTrackMsg_t** tmpp = cmMidiFileMsgArray(mfH);
double acc_secs = 0;
unsigned lexTId = 0;
cmCsvCell_t* cp = NULL;
if( cmCsvAppendRow(csvH, &cp, cmCsvInsertSymText(csvH,titles[0]), kStrCsvTFl, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'id' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
for(i=1; titles[i]!=NULL; ++i)
{
if( cmCsvInsertTextColAfter(csvH, cp, &cp, titles[i], lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting column index '%i' label in '%s'.",i,cmStringNullGuard(scoreFn));
goto errLabel;
}
}
for(i=0; i<msgCnt; ++i)
{
const cmMidiTrackMsg_t* tmp = tmpp[i];
const cmChar_t* opStr = NULL;
unsigned midiCh = 0;
unsigned d0 = 0;
unsigned d1 = 0;
unsigned metaId = 0;
double dsecs = (double)tmp->dtick / 1000000.0;
acc_secs += dsecs;
if( tmp->status == kMetaStId )
{
opStr = cmMidiMetaStatusToLabel(tmp->metaId);
metaId = tmp->metaId;
switch( tmp->metaId )
{
case kTempoMdId:
d0 = tmp->u.iVal;
}
}
else
{
opStr = cmMidiStatusToLabel(tmp->status);
if( cmMidiIsChStatus( tmp->status ) )
{
midiCh = tmp->u.chMsgPtr->ch;
d0 = tmp->u.chMsgPtr->d0;
d1 = tmp->u.chMsgPtr->d1;
}
}
cp = NULL;
// skip note-off messages
if( tmp->status == kNoteOffMdId )
continue;
if( cmCsvAppendRow(csvH, &cp, cmCsvInsertSymUInt(csvH,i), kIntCsvTFl, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'id' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->trkIdx, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'trk' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, 0, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'evt' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertTextColAfter(csvH, cp, &cp, opStr, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'opcode' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertDoubleColAfter(csvH, cp, &cp, dsecs, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'dticks' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertDoubleColAfter(csvH, cp, &cp, acc_secs, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'micros' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertHexColAfter(csvH, cp, &cp, tmp->status, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'status' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, metaId, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'meta' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, midiCh, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'ch' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, d0, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'd0' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, d1, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'd1' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
switch( tmp->status )
{
case kNoteOnMdId:
if( cmCsvInsertTextColAfter(csvH, cp, &cp, cmMidiToSciPitch(tmp->u.chMsgPtr->d0,NULL,0), lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'opcode' column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
case kMetaStId:
switch( tmp->metaId )
{
case kTimeSigMdId:
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->num, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. numerator column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, tmp->u.timeSigPtr->den, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting time sign. denominator column in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
break;
case kTempoMdId:
if( cmCsvInsertUIntColAfter(csvH, cp, &cp, 60000000/tmp->u.iVal, lexTId ) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"Error inserting 'tempo' in '%s'.",cmStringNullGuard(scoreFn));
goto errLabel;
}
break;
}
}
}
if( cmCsvWrite(csvH,scoreFn) != kOkCsvRC )
{
cmErrMsg(&err,kCsvFailScRC,"The score output file '%s' could not be written.",cmStringNullGuard(scoreFn));
goto errLabel;
}
errLabel:
cmMidiFileClose(&mfH);
cmCsvFinalize(&csvH);
return rc;
}
void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn ) void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn )
{ {
cmScH_t h = cmScNullHandle; cmScH_t h = cmScNullHandle;

View File

@ -12,8 +12,8 @@ extern "C" {
kSyntaxErrScRC, kSyntaxErrScRC,
kInvalidIdxScRC, kInvalidIdxScRC,
kTimeLineFailScRC, kTimeLineFailScRC,
kInvalidDynRefCntScRC kInvalidDynRefCntScRC,
kMidiFileFailScRC
}; };
enum enum
@ -36,12 +36,12 @@ extern "C" {
// Flags used by cmScoreEvt_t.flags // Flags used by cmScoreEvt_t.flags
enum enum
{ {
kEvenScFl = 0x01, // This note is marked for evenness measurement kEvenScFl = 0x001, // This note is marked for evenness measurement
kDynScFl = 0x02, // This note is marked for dynamics measurement kDynScFl = 0x002, // This note is marked for dynamics measurement
kTempoScFl = 0x04, // This note is marked for tempo measurement kTempoScFl = 0x004, // This note is marked for tempo measurement
kSkipScFl = 0x08, // This isn't a real event (e.g. tied note) skip over it kSkipScFl = 0x008, // This isn't a real event (e.g. tied note) skip over it
kGraceScFl = 0x10, // This is a grace note kGraceScFl = 0x010, // This is a grace note
kInvalidScFl = 0x20 // This note has a calculated time kInvalidScFl = 0x020 // This note has a calculated time
}; };
@ -103,7 +103,26 @@ extern "C" {
double value; double value;
struct cmScoreSet_str* llink; // cmScoreLoc_t setList link struct cmScoreSet_str* llink; // cmScoreLoc_t setList link
} cmScoreSet_t; } cmScoreSet_t;
typedef enum
{
kInvalidScMId,
kRecdBegScMId,
kRecdEndScMId,
kFadeScMId,
kPlayBegScMId,
kPlayEndScMId
} cmMarkScMId_t;
// score markers
typedef struct cmScoreMarker_str
{
cmMarkScMId_t markTypeId; // marker type
unsigned labelSymId; // marker label
struct cmScoreLoc_str* scoreLocPtr; // score location of the marker
unsigned csvRowIdx; // score CSV file line assoc'd w/ this marker
struct cmScoreMarker_str* link; // cmScoreLoc_t.markList links
} cmScoreMarker_t;
// All events which are simultaneous are collected into a single // All events which are simultaneous are collected into a single
// cmScoreLoc_t record. // cmScoreLoc_t record.
@ -116,6 +135,7 @@ extern "C" {
unsigned barNumb; // Bar number this event is contained by. unsigned barNumb; // Bar number this event is contained by.
cmScoreSet_t* setList; // Set's which end on this time location (linked through cmScoreSet_t.llink) cmScoreSet_t* setList; // Set's which end on this time location (linked through cmScoreSet_t.llink)
cmScoreSection_t* begSectPtr; // NULL if this location does not start a section cmScoreSection_t* begSectPtr; // NULL if this location does not start a section
cmScoreMarker_t* markList; // List of markers assigned to this location
} cmScoreLoc_t; } cmScoreLoc_t;
typedef void (*cmScCb_t)( void* arg, const void* data, unsigned byteCnt ); typedef void (*cmScCb_t)( void* arg, const void* data, unsigned byteCnt );
@ -170,6 +190,10 @@ extern "C" {
// Return the count of sets. // Return the count of sets.
unsigned cmScoreSetCount( cmScH_t h ); unsigned cmScoreSetCount( cmScH_t h );
unsigned cmScoreMarkerLabelCount( cmScH_t h );
unsigned cmScoreMarkerLabelSymbolId( cmScH_t h, unsigned idx );
const cmScoreMarker_t* cmScoreMarker( cmScH_t h, cmMarkScMId_t markMId, unsigned labelSymId );
// Make callbacks for all events in the score. The callbacks // Make callbacks for all events in the score. The callbacks
// contain cmScMsg_t records serialized as a byte stream. // contain cmScMsg_t records serialized as a byte stream.
// Use cmScoreDecode() to convert the byte string to a // Use cmScoreDecode() to convert the byte string to a
@ -235,6 +259,9 @@ extern "C" {
void cmScorePrint( cmScH_t h, cmRpt_t* rpt ); void cmScorePrint( cmScH_t h, cmRpt_t* rpt );
// Generate a new score file from a MIDI file.
cmScRC_t cmScoreFileFromMidi( cmCtx_t* ctx, const cmChar_t* midiFn, const cmChar_t* scoreFn );
void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn ); void cmScoreTest( cmCtx_t* ctx, const cmChar_t* fn );

58
cmCsv.c
View File

@ -729,6 +729,20 @@ unsigned cmCsvInsertSymUInt( cmCsvH_t h, unsigned v )
return cmInvalidId; return cmInvalidId;
} }
unsigned cmCsvInsertSymHex( cmCsvH_t h, unsigned v )
{
const char* fmt = "0x%x";
unsigned n = snprintf(NULL,0,fmt,v)+1;
char buf[n];
buf[0]= 0;
if( snprintf(buf,n,fmt,v) == n-1 )
return cmCsvInsertSymText(h,buf);
_cmCsvError(_cmCsvHandleToPtr(h),kDataCvtErrCsvRC,"The unsigned int 0x%x could not be converted to text.",v);
return cmInvalidId;
}
unsigned cmCsvInsertSymFloat( cmCsvH_t h, float v ) unsigned cmCsvInsertSymFloat( cmCsvH_t h, float v )
{ {
const char* fmt = "%f"; const char* fmt = "%f";
@ -812,6 +826,24 @@ cmCsvRC_t cmCsvSetCellUInt( cmCsvH_t h, unsigned row, unsigned col, unsigned
return kOkCsvRC; return kOkCsvRC;
} }
cmCsvRC_t cmCsvSetCellHex( cmCsvH_t h, unsigned row, unsigned col, unsigned v )
{
cmCsvCell_t* cp;
unsigned symId;
if((cp = _cmCsvCellPtr(h,row,col)) == NULL )
return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
if((symId = cmCsvInsertSymHex(h,v)) == cmInvalidId )
return cmErrLastRC(&_cmCsvHandleToPtr(h)->err);
cp->symId = symId;
cp->flags &= !kTypeTMask;
cp->flags |= kIntCsvTFl;
return kOkCsvRC;
}
cmCsvRC_t cmCsvSetCellFloat( cmCsvH_t h, unsigned row, unsigned col, float v ) cmCsvRC_t cmCsvSetCellFloat( cmCsvH_t h, unsigned row, unsigned col, float v )
{ {
cmCsvCell_t* cp; cmCsvCell_t* cp;
@ -985,7 +1017,7 @@ cmCsvRC_t cmCsvInsertTextColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
cmCsvCell_t* ncp; cmCsvCell_t* ncp;
if( cellPtrPtr != NULL ) if( cellPtrPtr != NULL )
cellPtrPtr = NULL; *cellPtrPtr = NULL;
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC ) if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
if((rc = cmCsvSetCellText(h, ncp->row, ncp->col, text )) == kOkCsvRC ) if((rc = cmCsvSetCellText(h, ncp->row, ncp->col, text )) == kOkCsvRC )
@ -1001,7 +1033,7 @@ cmCsvRC_t cmCsvInsertIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
cmCsvCell_t* ncp; cmCsvCell_t* ncp;
if( cellPtrPtr != NULL ) if( cellPtrPtr != NULL )
cellPtrPtr = NULL; *cellPtrPtr = NULL;
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC ) if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
if((rc = cmCsvSetCellInt(h, ncp->row, ncp->col, val )) == kOkCsvRC ) if((rc = cmCsvSetCellInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
@ -1017,7 +1049,7 @@ cmCsvRC_t cmCsvInsertUIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
cmCsvCell_t* ncp; cmCsvCell_t* ncp;
if( cellPtrPtr != NULL ) if( cellPtrPtr != NULL )
cellPtrPtr = NULL; *cellPtrPtr = NULL;
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC ) if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
if((rc = cmCsvSetCellUInt(h, ncp->row, ncp->col, val )) == kOkCsvRC ) if((rc = cmCsvSetCellUInt(h, ncp->row, ncp->col, val )) == kOkCsvRC )
@ -1027,13 +1059,29 @@ cmCsvRC_t cmCsvInsertUIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
return rc; return rc;
} }
cmCsvRC_t cmCsvInsertHexColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val, unsigned lexTId )
{
cmCsvRC_t rc;
cmCsvCell_t* ncp;
if( cellPtrPtr != NULL )
*cellPtrPtr = NULL;
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
if((rc = cmCsvSetCellHex(h, ncp->row, ncp->col, val )) == kOkCsvRC )
if( cellPtrPtr != NULL )
*cellPtrPtr = ncp;
return rc;
}
cmCsvRC_t cmCsvInsertFloatColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val, unsigned lexTId ) cmCsvRC_t cmCsvInsertFloatColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val, unsigned lexTId )
{ {
cmCsvRC_t rc; cmCsvRC_t rc;
cmCsvCell_t* ncp; cmCsvCell_t* ncp;
if( cellPtrPtr != NULL ) if( cellPtrPtr != NULL )
cellPtrPtr = NULL; *cellPtrPtr = NULL;
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC ) if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
if((rc = cmCsvSetCellFloat(h, ncp->row, ncp->col, val )) == kOkCsvRC ) if((rc = cmCsvSetCellFloat(h, ncp->row, ncp->col, val )) == kOkCsvRC )
@ -1049,7 +1097,7 @@ cmCsvRC_t cmCsvInsertDoubleColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCs
cmCsvCell_t* ncp; cmCsvCell_t* ncp;
if( cellPtrPtr != NULL ) if( cellPtrPtr != NULL )
cellPtrPtr = NULL; *cellPtrPtr = NULL;
if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC ) if((rc = cmCsvInsertColAfter(h, leftCellPtr, &ncp, cmInvalidId, 0, lexTId )) == kOkCsvRC )
if((rc = cmCsvSetCellDouble(h, ncp->row, ncp->col, val )) == kOkCsvRC ) if((rc = cmCsvSetCellDouble(h, ncp->row, ncp->col, val )) == kOkCsvRC )

View File

@ -109,13 +109,16 @@ extern "C" {
unsigned cmCsvInsertSymText( cmCsvH_t h, const char* text ); unsigned cmCsvInsertSymText( cmCsvH_t h, const char* text );
unsigned cmCsvInsertSymInt( cmCsvH_t h, int v ); unsigned cmCsvInsertSymInt( cmCsvH_t h, int v );
unsigned cmCsvInsertSymUInt( cmCsvH_t h, unsigned v ); unsigned cmCsvInsertSymUInt( cmCsvH_t h, unsigned v );
unsigned cmCsvInsertSymHex( cmCsvH_t h, unsigned v );
unsigned cmCsvInsertSymFloat( cmCsvH_t h, float v ); unsigned cmCsvInsertSymFloat( cmCsvH_t h, float v );
unsigned cmCsvInsertSymDouble( cmCsvH_t h, double v ); unsigned cmCsvInsertSymDouble( cmCsvH_t h, double v );
// Set the value associated with a cell. // Set the value associated with a cell.
cmCsvRC_t cmCsvSetCellText( cmCsvH_t h, unsigned row, unsigned col, const char* text ); cmCsvRC_t cmCsvSetCellText( cmCsvH_t h, unsigned row, unsigned col, const char* text );
cmCsvRC_t cmCsvSetCellInt( cmCsvH_t h, unsigned row, unsigned col, int v ); cmCsvRC_t cmCsvSetCellInt( cmCsvH_t h, unsigned row, unsigned col, int v );
cmCsvRC_t cmCsvSetCellUInt( cmCsvH_t h, unsigned row, unsigned col, unsigned v ); cmCsvRC_t cmCsvSetCellUInt( cmCsvH_t h, unsigned row, unsigned col, unsigned v );
cmCsvRC_t cmCsvSetCellHex( cmCsvH_t h, unsigned row, unsigned col, unsigned v );
cmCsvRC_t cmCsvSetCellFloat( cmCsvH_t h, unsigned row, unsigned col, float v ); cmCsvRC_t cmCsvSetCellFloat( cmCsvH_t h, unsigned row, unsigned col, float v );
cmCsvRC_t cmCsvSetCellDouble( cmCsvH_t h, unsigned row, unsigned col, double v ); cmCsvRC_t cmCsvSetCellDouble( cmCsvH_t h, unsigned row, unsigned col, double v );
@ -134,6 +137,7 @@ extern "C" {
cmCsvRC_t cmCsvInsertTextColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, const char* val, unsigned lexTId ); cmCsvRC_t cmCsvInsertTextColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, const char* val, unsigned lexTId );
cmCsvRC_t cmCsvInsertIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, int val, unsigned lexTId ); cmCsvRC_t cmCsvInsertIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, int val, unsigned lexTId );
cmCsvRC_t cmCsvInsertUIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val, unsigned lexTId ); cmCsvRC_t cmCsvInsertUIntColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val, unsigned lexTId );
cmCsvRC_t cmCsvInsertHexColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, unsigned val, unsigned lexTId );
cmCsvRC_t cmCsvInsertFloatColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val, unsigned lexTId ); cmCsvRC_t cmCsvInsertFloatColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, float val, unsigned lexTId );
cmCsvRC_t cmCsvInsertDoubleColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, double val, unsigned lexTId ); cmCsvRC_t cmCsvInsertDoubleColAfter( cmCsvH_t h, cmCsvCell_t* leftCellPtr, cmCsvCell_t** cellPtrPtr, double val, unsigned lexTId );

2602
cmData.c

File diff suppressed because it is too large Load Diff

608
cmData.h
View File

@ -5,129 +5,6 @@
extern "C" { extern "C" {
#endif #endif
enum
{
kOkDtRC = cmOkRC,
kCvtErrDtRC,
kVarArgErrDtRC,
kMissingFieldDtRC,
kEolDtRC
};
enum
{
kInvalidDtChar = 0xff,
kInvalidDtUChar = 0xff,
kInvalidDtShort = 0xffff,
kInvalidDtUShort = 0xffff,
kInvalidDtInt = 0xffffffff,
kInvalidDtUInt = 0xffffffff,
kInvalidDtLong = 0xffffffff,
kInvalidDtULong = 0xffffffff,
};
typedef enum
{
kInvalidDtId,
kMinValDtId,
kNullDtId = kMinValDtId,
kUCharDtId,
kCharDtId,
kUShortDtId,
kShortDtId,
kUIntDtId,
kIntDtId,
kULongDtId,
kLongDtId,
kFloatDtId,
kDoubleDtId,
kStrDtId,
kConstStrDtId,
kMaxValDtId = kConstStrDtId,
kMinPtrDtId,
kUCharPtrDtId = kMinPtrDtId, // cnt=array element count
kCharPtrDtId,
kUShortPtrDtId,
kShortPtrDtId,
kUIntPtrDtId,
kIntPtrDtId,
kULongPtrDtId,
kLongPtrDtId,
kFloatPtrDtId,
kDoublePtrDtId,
kVoidPtrDtId,
kMaxPtrDtId = kVoidPtrDtId,
kMinStructDtId,
kListDtId = kMinStructDtId, // children nodes are array elements, cnt=child count
kPairDtId, // key/value pairs, cnt=2, first child is key, second is value
kRecordDtId, // children nodes are pairs, cnt=pair count
kMaxStructDtId,
kOptArgDtFl = 0x80000000
} cmDataFmtId_t;
enum
{
kDynObjDtFl = 0x01, // object was dynamically allocated
kDynPtrDtFl = 0x02 // ptr array was dynamically allocated
};
typedef struct cmData_str
{
cmDataFmtId_t tid; // data format id
unsigned flags; //
struct cmData_str* parent; // this childs parent
struct cmData_str* sibling; // this childs left sibling
unsigned cnt; // array ele count
union
{
char c;
unsigned char uc;
short s;
unsigned short us;
int i;
unsigned int ui;
long l;
unsigned long ul;
float f;
double d;
cmChar_t* z;
const cmChar_t* cz;
void* vp;
char* cp;
unsigned char* ucp;
short* sp;
unsigned short* usp;
int* ip;
unsigned int* uip;
long* lp;
unsigned long* ulp;
float* fp;
double* dp;
struct cmData_str* child; // first child (array,record,pair)
} u;
} cmData_t;
typedef unsigned cmDtRC_t;
extern cmData_t cmDataNull;
bool cmDataIsValue( const cmData_t* p );
bool cmDataIsPtr( const cmData_t* p );
bool cmDataIsStruct( const cmData_t* p ); // is a pair,list or record
/* /*
TODO: TODO:
0) Figure out a error handling scheme that does not rely on 0) Figure out a error handling scheme that does not rely on
@ -144,7 +21,7 @@ extern "C" {
the array space. This will allow dynamic allocattion to the array space. This will allow dynamic allocattion to
occur at runtime. Make var args functions for list and occur at runtime. Make var args functions for list and
record objects which also take this flag. record objects which also take this flag.
Where ever a function may be implemented using Whereever a function may be implemented using
static/dynamic allocation this flag should be present. static/dynamic allocation this flag should be present.
(e.g. string allocation for pair labels) (e.g. string allocation for pair labels)
This choice is common enough that it may be worth This choice is common enough that it may be worth
@ -170,40 +47,227 @@ extern "C" {
*/ */
bool canConvertType( cmDataFmtId_t srcId, cmDataFmtId_t dstId ); enum
bool willTruncate( cmDataFmtId_t srcId, cmDataFmtId_t dstId ); {
bool canConvertObj( const cmData_t* srcObj, cmData_t* dstObj ); kOkDtRC = cmOkRC,
bool willTruncateObj(const cmData_t* srcObj, cmData_t* dstObj ); kAssertErrDtRC,
kConstErrDtRC,
kCvtErrDtRC,
kInvalidContDtRC,
kInvalidTypeDtRC,
kEolDtRC
};
typedef unsigned cmDtRC_t;
typedef enum
{
kInvalidTypeDtId,// 0
kNullDtId, // 1 the data object exists but it has no data
kUCharDtId, // 2
kCharDtId, // 3
kUShortDtId, // 4
kShortDtId, // 5
kUIntDtId, // 6
kIntDtId, // 7
kULongDtId, // 8
kLongDtId, // 9
kFloatDtId, // 10
kDoubleDtId, // 11
kStrDtId, // 12 zero terminated string
kBlobDtId, // 13 application defined raw memory object
kStructDtId // 14 node is a pair,list, or recd
} cmDataTypeId_t;
typedef enum
{
kInvalidCntDtId, // 0
kScalarDtId, // 1
kArrayDtId, // 2
kPairDtId, // 3
kListDtId, // 4
kRecordDtId // 5
} cmDataContainerId_t;
enum
{
kNoFlagsDtFl = 0x00,
// Indicate that the memory used by the data object
// was dynamically allocated and should be released
// by cmDataFree().
kFreeObjDtFl = 0x01,
// Indicate that the memory used by strings, blobs
// and arrays should be freed by cmDataFree().
kFreeValueDtFl = 0x02,
// Indicate that the value of the object cannot be changed.
// (but the object could be reassigned as a new type).
kConstValueDtFl = 0x04,
// Indicate that the type of the object cannot be changed.
// (but the value may be changed).
kConstObjDtFl = 0x08,
// Indicate that the array or string should not be
// internally reallocated but rather the source pointer
// should be taken as the new value of the object.
kNoCopyDtFl = 0x10,
};
typedef struct cmData_str
{
cmDataTypeId_t tid; // data format id
cmDataContainerId_t cid; // container id
unsigned flags; //
struct cmData_str* parent; // this childs parent
struct cmData_str* sibling; // this childs left sibling
unsigned cnt; // byte cnt for strings/blobs and ele count for arrays
union
{
char c;
unsigned char uc;
short s;
unsigned short us;
int i;
unsigned int ui;
long l;
unsigned long ul;
float f;
double d;
cmChar_t* z;
void* vp;
/*
char* cp;
unsigned char* ucp;
short* sp;
unsigned short* usp;
int* ip;
unsigned int* uip;
long* lp;
unsigned long* ulp;
float* fp;
double* dp;
*/
struct cmData_str* child; // first child (list,record,pair)
} u;
} cmData_t;
extern cmData_t cmDataNull;
const cmChar_t* cmDataTypeToLabel( cmDataTypeId_t tid );
cmDataTypeId_t cmDataLabelToType( const cmChar_t* typeLabelStr );
// Returns 1 for kStrDtId.
// Returns cmInvalidCnt if tid is not recognized.
unsigned dmDataByteWidth( cmDataTypeId_t tid );
const cmChar_t* cmDataContainerIdToLabel( cmDataContainerId_t tid );
cmDataContainerId_t cmDataLabelToContainerId( const cmChar_t* contLabelStr );
bool cmDataIsConstObj( const cmData_t* d );
void cmDataEnableConstObj( cmData_t* d, bool enaFl );
bool cmDataIsConstValue( const cmData_t* d );
void cmDataEnableConstValue( cmData_t* d, bool enaFl );
bool cmDataIsFreeValue( const cmData_t* d );
void cmDataEnableFreeValue( cmData_t* d, bool enaFl );
// Returns true if this is a scalar or array node.
bool cmDataIsLeaf( const cmData_t* d);
// Return true if this is NOT a scalar or array node.
bool cmDataIsStruct( const cmData_t* d );
// Get the value of an object without conversion. //----------------------------------------------------------------------------
// The data type id must match the return type or the // Scalar related functions
// conversion must be an automatic C conversion. //
char cmDataChar( const cmData_t* p );
unsigned char cmDataUChar( const cmData_t* p );
short cmDataShort( const cmData_t* p );
unsigned short cmDataUShort( const cmData_t* p );
int cmDataInt( const cmData_t* p );
unsigned int cmDataUInt( const cmData_t* p );
long cmDataLong( const cmData_t* p );
unsigned long cmDataULong( const cmData_t* p );
float cmDataFloat( const cmData_t* p );
double cmDataDouble( const cmData_t* p );
cmChar_t* cmDataStr( const cmData_t* p );
const cmChar_t* cmDataConstStr( const cmData_t* p );
void* cmDataVoidPtr( const cmData_t* p );
char* cmDataCharPtr( const cmData_t* p );
unsigned char* cmDataUCharPtr( const cmData_t* p );
short* cmDataShortPtr( const cmData_t* p );
unsigned short* cmDataUShortPtr( const cmData_t* p );
int* cmDataIntPtr( const cmData_t* p );
unsigned int* cmDataUIntPtr( const cmData_t* p );
long* cmDataLongPtr( const cmData_t* p );
unsigned long* cmDataULongPtr( const cmData_t* p );
float* cmDataFloatPtr( const cmData_t* p );
double* cmDataDoublePtr( const cmData_t* p );
// Dynamically allocate a scalar object and set it's value.
// The 'flags' argument may include kConstValueDtFl and kConstObjDtFl.
// The string and blob constructors may also use the
// kNoCopyDtFl and the kFreeValueDtFl.
// Generic:
// 'byteCnt' is ignored for all types other than strings and blobs.
cmDtRC_t cmDataNewScalar( cmData_t* parent, cmDataTypeId_t tid, unsigned flags, void* vp, unsigned byteCnt, cmData_t** ref );
// Type specific
cmDtRC_t cmDataNewNull( cmData_t* parent, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewChar( cmData_t* parent, unsigned flags, char v, cmData_t** ref );
cmDtRC_t cmDataNewUChar( cmData_t* parent, unsigned flags, unsigned char v, cmData_t** ref );
cmDtRC_t cmDataNewShort( cmData_t* parent, unsigned flags, short v, cmData_t** ref );
cmDtRC_t cmDataNewUShort( cmData_t* parent, unsigned flags, unsigned short v, cmData_t** ref );
cmDtRC_t cmDataNewInt( cmData_t* parent, unsigned flags, int v, cmData_t** ref );
cmDtRC_t cmDataNewUInt( cmData_t* parent, unsigned flags, unsigned int v, cmData_t** ref );
cmDtRC_t cmDataNewLong( cmData_t* parent, unsigned flags, long v, cmData_t** ref );
cmDtRC_t cmDataNewULong( cmData_t* parent, unsigned flags, unsigned long v, cmData_t** ref );
cmDtRC_t cmDataNewFloat( cmData_t* parent, unsigned flags, float v, cmData_t** ref );
cmDtRC_t cmDataNewDouble( cmData_t* parent, unsigned flags, double v, cmData_t** ref );
cmDtRC_t cmDataNewStr( cmData_t* parent, unsigned flags, cmChar_t* str, cmData_t** ref );
cmDtRC_t cmDataNewConstStr( cmData_t* parent, unsigned flags, const cmChar_t* str, cmData_t** ref );
cmDtRC_t cmDataNewStrN( cmData_t* parent, unsigned flags, cmChar_t* str, unsigned charCnt, cmData_t** ref );
cmDtRC_t cmDataNewConstStrN(cmData_t* parent, unsigned flags, const cmChar_t* str, unsigned charCnt, cmData_t** ref );
cmDtRC_t cmDataNewBlob( cmData_t* parent, unsigned flags, void* vp, unsigned byteCnt, cmData_t** ref );
cmDtRC_t cmDataNewConstBlob(cmData_t* parent, unsigned flags, const void* vp, unsigned byteCnt, cmData_t** ref );
// Set the value and type of an existing scalar object.
// These functions begin by releasing any resources held by *p
// prior to resetting the type and value of the object.
// The 'flags' argument to cmDataSetStr() and cmDataSetConstStr()
// may use the kNoCopyDtFl and the kFreeValueDtFl
cmDtRC_t cmDataSetScalarValue( cmData_t* d, cmDataTypeId_t tid, void* vp, unsigned byteCnt, unsigned flags );
cmDtRC_t cmDataSetNull( cmData_t* p );
cmDtRC_t cmDataSetChar( cmData_t* p, char v );
cmDtRC_t cmDataSetUChar( cmData_t* p, unsigned char v );
cmDtRC_t cmDataSetShort( cmData_t* p, short v );
cmDtRC_t cmDataSetUShort( cmData_t* p, unsigned short v );
cmDtRC_t cmDataSetInt( cmData_t* p, int v );
cmDtRC_t cmDataSetUInt( cmData_t* p, unsigned int v );
cmDtRC_t cmDataSetLong( cmData_t* p, long v );
cmDtRC_t cmDataSetULong( cmData_t* p, unsigned long v );
cmDtRC_t cmDataSetFloat( cmData_t* p, float v );
cmDtRC_t cmDataSetDouble( cmData_t* p, double v );
cmDtRC_t cmDataSetStr( cmData_t* p, unsigned flags, cmChar_t* s );
cmDtRC_t cmDataSetConstStr( cmData_t* p, unsigned flags, const cmChar_t* s );
cmDtRC_t cmDataSetStrN( cmData_t* p, unsigned flags, cmChar_t* s, unsigned charCnt );
cmDtRC_t cmDataSetConstStrN( cmData_t* p, unsigned flags, const cmChar_t* s, unsigned charCnt );
cmDtRC_t cmDataSetBlob( cmData_t* p, unsigned flags, void* v, unsigned byteCnt );
cmDtRC_t cmDataSetConstBlob( cmData_t* p, unsigned flags, const void* v, unsigned byteCnt );
// Get the value of an object. No conversion is applied the
// type must match exactly or an error is generated.
cmDtRC_t cmDataChar( const cmData_t* p, char* v );
cmDtRC_t cmDataUChar( const cmData_t* p, unsigned char* v );
cmDtRC_t cmDataShort( const cmData_t* p, short* v );
cmDtRC_t cmDataUShort( const cmData_t* p, unsigned short* v );
cmDtRC_t cmDataInt( const cmData_t* p, int* v );
cmDtRC_t cmDataUInt( const cmData_t* p, unsigned int* v );
cmDtRC_t cmDataLong( const cmData_t* p, long* v );
cmDtRC_t cmDataULong( const cmData_t* p, unsigned long* v );
cmDtRC_t cmDataFloat( const cmData_t* p, float* v );
cmDtRC_t cmDataDouble( const cmData_t* p, double* v );
cmDtRC_t cmDataStr( const cmData_t* p, cmChar_t** v );
cmDtRC_t cmDataConstStr( const cmData_t* p, const cmChar_t** v );
cmDtRC_t cmDataBlob( const cmData_t* p, cmChar_t** v, unsigned* byteCntRef );
cmDtRC_t cmDataConstBlob( const cmData_t* p, const cmChar_t** v, unsigned* byteCntRef );
// Get the value of an object with conversion. // Get the value of an object with conversion.
cmDtRC_t cmDataGetChar( const cmData_t* p, char* v ); cmDtRC_t cmDataGetChar( const cmData_t* p, char* v );
@ -217,125 +281,96 @@ extern "C" {
cmDtRC_t cmDataGetFloat( const cmData_t* p, float* v ); cmDtRC_t cmDataGetFloat( const cmData_t* p, float* v );
cmDtRC_t cmDataGetDouble( const cmData_t* p, double* v ); cmDtRC_t cmDataGetDouble( const cmData_t* p, double* v );
// Returns the pointer - does not copy the data.
cmDtRC_t cmDataGetStr( const cmData_t* p, char** v );
cmDtRC_t cmDataGetConstStr( const cmData_t* p, const char** v );
cmDtRC_t cmDataGetVoidPtr( const cmData_t* p, void** v );
cmDtRC_t cmDataGetCharPtr( const cmData_t* p, char** v );
cmDtRC_t cmDataGetUCharPtr( const cmData_t* p, unsigned char** v );
cmDtRC_t cmDataGetShortPtr( const cmData_t* p, short** v );
cmDtRC_t cmDataGetUShortPtr( const cmData_t* p, unsigned short** v );
cmDtRC_t cmDataGetIntPtr( const cmData_t* p, int** v );
cmDtRC_t cmDataGetUIntPtr( const cmData_t* p, unsigned int** v );
cmDtRC_t cmDataGetLongPtr( const cmData_t* p, long** v );
cmDtRC_t cmDataGetULongPtr( const cmData_t* p, unsigned long** v );
cmDtRC_t cmDataGetFloatPtr( const cmData_t* p, float** v );
cmDtRC_t cmDataGetDoublePtr( const cmData_t* p, double** v );
//----------------------------------------------------------------------------
// Array related functions
//
// Set the value and type of an existing scalar object. // Notes:
// 1) string arrays are arrays of string pointers.
// 2) blob arrays (array of void pointers) are not supported because
// there is no direct way to determine the length of each blob
// and therefore they cannot be internally duplicated - a special scheme
// could be devised (length goes in first 4 bytes) to make this
// work but we will defer that until the need arises.
//
// Dynamically allocate a new array data object.
//
// eleCnt referes to the number of elements in the array pointed
// to by 'vp'. The number of bytes pointed to by 'vp' is then
// cmDataByteWidth(tid)*eleCnt.
//
// If no flags are set then the array pointed to by 'vp' is reallocated
// and kDataFreeDtFl is set.
//
// If kFreeValueDtFl is set then the object will take responsibility for
// releasing the memory pointed to by 'vp' when the object is destroyed
// or the array is reassigned.
//
// If kNoCopyDtFl is set then 'vp' becomes the internal array
// value (vp[cnt]) is NOT reallocated). In this case the client is
// responsibile for eventually releasing the associated memory - when
// the data object is no longer valid.
cmDtRC_t cmDataNewArray( cmData_t* parent, cmDataTypeId_t tid, void* vp, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewCharArray( cmData_t* parent, char* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewUCharArray( cmData_t* parent, unsigned char* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewShortArray( cmData_t* parent, short* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewUShortArray( cmData_t* parent, unsigned short* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewIntArray( cmData_t* parent, int* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewUIntArray( cmData_t* parent, unsigned int* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewLongArray( cmData_t* parent, long* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewULongArray( cmData_t* parent, unsigned long* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewFloatArray( cmData_t* parent, float* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewDoubleArray( cmData_t* parent, double* v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewStrArray( cmData_t* parent, cmChar_t** v, unsigned eleCnt, unsigned flags, cmData_t** ref );
cmDtRC_t cmDataNewConstStrArray( cmData_t* parent, const cmChar_t** v,unsigned eleCnt, unsigned flags, cmData_t** ref );
// Set the value and type of an existing scalar object.
//
// These functions begin by releasing any resources held by *p // These functions begin by releasing any resources held by *p
// prior to resetting the type and value of the object. // prior to resetting the type and value of the object.
cmData_t* cmDataSetNull( cmData_t* p ); // The 'flags' argument may include kConstValueDtFl, kConstObjDtFl,
cmData_t* cmDataSetChar( cmData_t* p, char v ); // kNoCopyDtFl and the kFreeValueDtFl.
cmData_t* cmDataSetUChar( cmData_t* p, unsigned char v );
cmData_t* cmDataSetShort( cmData_t* p, short v );
cmData_t* cmDataSetUShort( cmData_t* p, unsigned short v );
cmData_t* cmDataSetInt( cmData_t* p, int v );
cmData_t* cmDataSetUInt( cmData_t* p, unsigned int v );
cmData_t* cmDataSetLong( cmData_t* p, long v );
cmData_t* cmDataSetULong( cmData_t* p, unsigned long v );
cmData_t* cmDataSetFloat( cmData_t* p, float v );
cmData_t* cmDataSetDouble( cmData_t* p, double v );
cmData_t* cmDataSetStr( cmData_t* p, cmChar_t* s );
cmData_t* cmDataSetConstStr( cmData_t* p, const cmChar_t* s );
// Set the type and value of an existing data object to an external array. // Generic set array functions. 'vp' is assumed to point to an array
// These functions begin by releasing any resources help by *p. // of the type defined by 'tid'.
// The array pointed to by 'vp' is not copied or duplicated. cmDtRC_t cmDataSetArrayValue( cmData_t* dt, cmDataTypeId_t tid, void* vp, unsigned eleCnt, unsigned flags );
// 'vp' is simply assigned as the data space for the object and therefore must remain
// valid for the life of the object.
cmData_t* cmDataSetVoidPtr( cmData_t* p, void* vp, unsigned cnt );
cmData_t* cmDataSetCharPtr( cmData_t* p, char* vp, unsigned cnt );
cmData_t* cmDataSetUCharPtr( cmData_t* p, unsigned char* vp, unsigned cnt );
cmData_t* cmDataSetShortPtr( cmData_t* p, short* vp, unsigned cnt );
cmData_t* cmDataSetUShortPtr( cmData_t* p, unsigned short* vp, unsigned cnt );
cmData_t* cmDataSetIntPtr( cmData_t* p, int* vp, unsigned cnt );
cmData_t* cmDataSetUIntPtr( cmData_t* p, unsigned int* vp, unsigned cnt );
cmData_t* cmDataSetLongPtr( cmData_t* p, long* vp, unsigned cnt );
cmData_t* cmDataSetULongPtr( cmData_t* p, unsigned long* vp, unsigned cnt );
cmData_t* cmDataSetFloatPtr( cmData_t* p, float* vp, unsigned cnt );
cmData_t* cmDataSetDoublePtr( cmData_t* p, double* vp, unsigned cnt );
// Set the value of an existing array based data object. // Type sepctific set array functions.
// These functions begin by releasing any resources help by *p cmDtRC_t cmDataSetCharArray( cmData_t* d, char* v, unsigned eleCnt, unsigned flags );
// and then dynamically allocate the internal array and copy cmDtRC_t cmDataSetUCharArray( cmData_t* d, unsigned char* v, unsigned eleCnt, unsigned flags );
// the array data into it. cmDtRC_t cmDataSetShortArray( cmData_t* d, short* v, unsigned eleCnt, unsigned flags );
cmData_t* cmDataSetStrAlloc( cmData_t* p, const cmChar_t* s ); cmDtRC_t cmDataSetUShortArray( cmData_t* d, unsigned short* v, unsigned eleCnt, unsigned flags );
cmData_t* cmDataSetConstStrAlloc( cmData_t* p, const cmChar_t* s ); cmDtRC_t cmDataSetIntArray( cmData_t* d, int* v, unsigned eleCnt, unsigned flags );
cmData_t* cmDataSetVoidAllocPtr( cmData_t* p, const void* vp, unsigned cnt ); cmDtRC_t cmDataSetUIntArray( cmData_t* d, unsigned int* v, unsigned eleCnt, unsigned flags );
cmData_t* cmDataSetCharAllocPtr( cmData_t* p, const char* vp, unsigned cnt ); cmDtRC_t cmDataSetLongArray( cmData_t* d, long* v, unsigned eleCnt, unsigned flags );
cmData_t* cmDataSetUCharAllocPtr( cmData_t* p, const unsigned char* vp, unsigned cnt ); cmDtRC_t cmDataSetULongArray( cmData_t* d, unsigned long* v, unsigned eleCnt, unsigned flags );
cmData_t* cmDataSetShortAllocPtr( cmData_t* p, const short* vp, unsigned cnt ); cmDtRC_t cmDataSetFloatArray( cmData_t* d, float* v, unsigned eleCnt, unsigned flags );
cmData_t* cmDataSetUShortAllocPtr( cmData_t* p, const unsigned short* vp, unsigned cnt ); cmDtRC_t cmDataSetDoubleArray( cmData_t* d, double* v, unsigned eleCnt, unsigned flags );
cmData_t* cmDataSetIntAllocPtr( cmData_t* p, const int* vp, unsigned cnt ); cmDtRC_t cmDataSetStrArray( cmData_t* d, cmChar_t** v, unsigned eleCnt, unsigned flags );
cmData_t* cmDataSetUIntAllocPtr( cmData_t* p, const unsigned int* vp, unsigned cnt ); cmDtRC_t cmDataSetConstStrArray(cmData_t* d,const cmChar_t** v,unsigned eleCnt, unsigned flags );
cmData_t* cmDataSetLongAllocPtr( cmData_t* p, const long* vp, unsigned cnt );
cmData_t* cmDataSetULongAllocPtr( cmData_t* p, const unsigned long* vp, unsigned cnt ); // Return the count of elements in a n array.
cmData_t* cmDataSetFloatAllocPtr( cmData_t* p, const float* vp, unsigned cnt ); unsigned cmDataArrayEleCount( const cmData_t* d );
cmData_t* cmDataSetDoubleAllocPtr( cmData_t* p, const double* vp, unsigned cnt );
// Get a pointer to the base of an array.
// The type must match exactly or an error is generated.
// Use cmDataEleCount() to determine the number of elements in the array.
cmDtRC_t cmDataCharArray( const cmData_t* d, char** v );
cmDtRC_t cmDataUCharArray( const cmData_t* d, unsigned char** v );
cmDtRC_t cmDataShortArray( const cmData_t* d, short** v );
cmDtRC_t cmDataUShortArray( const cmData_t* d, unsigned short** v );
cmDtRC_t cmDataIntArray( const cmData_t* d, int** v );
cmDtRC_t cmDataUIntArray( const cmData_t* d, unsigned int** v );
cmDtRC_t cmDataLongArray( const cmData_t* d, long** v );
cmDtRC_t cmDataULongArray( const cmData_t* d, unsigned long** v );
cmDtRC_t cmDataFloatArray( const cmData_t* d, float** v );
cmDtRC_t cmDataDoubleArray( const cmData_t* d, double** v );
cmDtRC_t cmDataStrArray( const cmData_t* d, cmChar_t*** v );
cmDtRC_t cmDataConstStrArray( const cmData_t* d, const cmChar_t*** v );
// Dynamically allocate a data object and set it's value.
cmData_t* cmDataAllocNull( cmData_t* parent );
cmData_t* cmDataAllocChar( cmData_t* parent, char v );
cmData_t* cmDataAllocUChar( cmData_t* parent, unsigned char v );
cmData_t* cmDataAllocShort( cmData_t* parent, short v );
cmData_t* cmDataAllocUShort( cmData_t* parent, unsigned short v );
cmData_t* cmDataAllocInt( cmData_t* parent, int v );
cmData_t* cmDataAllocUInt( cmData_t* parent, unsigned int v );
cmData_t* cmDataAllocLong( cmData_t* parent, long v );
cmData_t* cmDataAllocULong( cmData_t* parent, unsigned long v );
cmData_t* cmDataAllocFloat( cmData_t* parent, float v );
cmData_t* cmDataAllocDouble( cmData_t* parent, double v );
// Dynamically allocate a data object and set its array value to an external
// array. v[cnt] is assigned as the internal data space for the object and
// therefore must remain valid for the life of the object.
// See the cmDataXXXAlocPtr() for equivalent functions which dynamically
// allocate the intenal data space.
cmData_t* cmDataAllocStr( cmData_t* parent, cmChar_t* str );
cmData_t* cmDataAllocConstStr( cmData_t* parent, const cmChar_t* str );
cmData_t* cmDataAllocCharPtr( cmData_t* parent, char* v, unsigned cnt );
cmData_t* cmDataAllocUCharPtr( cmData_t* parent, unsigned char* v, unsigned cnt );
cmData_t* cmDataAllocShortPtr( cmData_t* parent, short* v, unsigned cnt );
cmData_t* cmDataAllocUShortPtr( cmData_t* parent, unsigned short* v, unsigned cnt );
cmData_t* cmDataAllocIntPtr( cmData_t* parent, int* v, unsigned cnt );
cmData_t* cmDataAllocUIntPtr( cmData_t* parent, unsigned int* v, unsigned cnt );
cmData_t* cmDataAllocLongPtr( cmData_t* parent, long* v, unsigned cnt );
cmData_t* cmDataAllocULongPtr( cmData_t* parent, unsigned long* v, unsigned cnt );
cmData_t* cmDataAllocFloatPtr( cmData_t* parent, float* v, unsigned cnt );
cmData_t* cmDataAllocDoublePtr( cmData_t* parent, double* v, unsigned cnt );
cmData_t* cmDataAllocVoidPtr( cmData_t* parent, void* v, unsigned cnt );
// Dynamically allocate a data object and its array value.
// These functions dynamically allocate the internal array data space
// and copy v[cnt] into it.
cmData_t* cmDataStrAlloc( cmData_t* parent, cmChar_t* str );
cmData_t* cmDataConstStrAlloc( cmData_t* parent, const cmChar_t* str );
cmData_t* cmDataCharAllocPtr( cmData_t* parent, const char* v, unsigned cnt );
cmData_t* cmDataUCharAllocPtr( cmData_t* parent, const unsigned char* v, unsigned cnt );
cmData_t* cmDataShortAllocPtr( cmData_t* parent, const short* v, unsigned cnt );
cmData_t* cmDataUShortAllocPtr( cmData_t* parent, const unsigned short* v, unsigned cnt );
cmData_t* cmDataIntAllocPtr( cmData_t* parent, const int* v, unsigned cnt );
cmData_t* cmDataUIntAllocPtr( cmData_t* parent, const unsigned int* v, unsigned cnt );
cmData_t* cmDataLongAllocPtr( cmData_t* parent, const long* v, unsigned cnt );
cmData_t* cmDataULongAllocPtr( cmData_t* parent, const unsigned long* v, unsigned cnt );
cmData_t* cmDataFloatAllocPtr( cmData_t* parent, const float* v, unsigned cnt );
cmData_t* cmDataDoubleAllocPtr( cmData_t* parent, const double* v, unsigned cnt );
cmData_t* cmDataVoidAllocPtr( cmData_t* parent, const void* v, unsigned cnt );
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Structure related functions // Structure related functions
// //
@ -428,6 +463,7 @@ extern "C" {
cmData_t* cmDataAllocPairId( cmData_t* parent, unsigned keyId, cmData_t* value ); cmData_t* cmDataAllocPairId( cmData_t* parent, unsigned keyId, cmData_t* value );
// Dynamically allocate the label but link (w/o realloc) the value. // Dynamically allocate the label but link (w/o realloc) the value.
cmData_t* cmDataAllocPairLabelN(cmData_t* parent, const cmChar_t* label, unsigned charCnt, cmData_t* value);
cmData_t* cmDataAllocPairLabel( cmData_t* parent, const cmChar_t* label, cmData_t* value ); cmData_t* cmDataAllocPairLabel( cmData_t* parent, const cmChar_t* label, cmData_t* value );
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -445,15 +481,15 @@ extern "C" {
// Var-args fmt: // Var-args fmt:
// <typeId> <value> {<cnt>} // <contId> {<typeId>} <value> {<cnt>}
// scalar types: <value> is literal,<cnt> is not included // scalar types: <value> is literal,<cnt> is not included
// null has no <value> or <cnt> // null has no <value> or <cnt>
// ptr types: <value> is pointer,<cnt> is element count // array types: <value> is pointer,<cnt> is element count
// struct types: <value> is cmData_t, <cnt> is not included // struct types: <value> is cmData_t, <typeId> and <cnt> is not included
// Indicate the end of argument list by setting <typeId> to kInvalidDtId. // Indicate the end of argument list by setting <typeId> to kInvalidDtId.
// The memory for array based data types is dynamically allocated. // The memory for array based data types is dynamically allocated.
cmData_t* cmDataListAllocV(cmData_t* parent, va_list vl ); cmRC_t cmDataListAllocV(cmData_t* parent, cmData_t** ref, va_list vl );
cmData_t* cmDataListAllocA(cmData_t* parent, ... ); cmRC_t cmDataListAllocA(cmData_t* parent, cmData_t** ref, ... );
// Returns a ptr to 'ele'. // Returns a ptr to 'ele'.
cmData_t* cmDataListAppendEle( cmData_t* p, cmData_t* ele ); cmData_t* cmDataListAppendEle( cmData_t* p, cmData_t* ele );
@ -464,9 +500,6 @@ extern "C" {
cmData_t* cmDataListInsertEle( cmData_t* p, unsigned index, cmData_t* ele ); cmData_t* cmDataListInsertEle( cmData_t* p, unsigned index, cmData_t* ele );
cmData_t* cmDataListInsertEleN(cmData_t* p, unsigned index, cmData_t* ele[], unsigned n ); cmData_t* cmDataListInsertEleN(cmData_t* p, unsigned index, cmData_t* ele[], unsigned n );
cmData_t* cmDataListUnlink( cmData_t* p, unsigned index );
cmData_t* cmDataListFree( cmData_t* p, unsigned index );
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Record related functions // Record related functions
// //
@ -487,17 +520,17 @@ extern "C" {
unsigned cmDataRecdKeyId( cmData_t* p, unsigned index ); unsigned cmDataRecdKeyId( cmData_t* p, unsigned index );
const cmChar_t* cmDataRecdKeyLabel( cmData_t* p, unsigned index ); const cmChar_t* cmDataRecdKeyLabel( cmData_t* p, unsigned index );
cmData_t* cmRecdMake( cmData_t* parent, cmData_t* p ); cmData_t* cmDataRecdMake( cmData_t* parent, cmData_t* p );
cmData_t* cmRecdAlloc( cmData_t* parent ); cmData_t* cmDataRecdAlloc( cmData_t* parent );
// Append a pair node by linking the pair node 'pair' to the record node 'p'. // Append a pair node by linking the pair node 'pair' to the record node 'p'.
// 'pair' is simply linked to 'p' via cmDataAppendChild() no // 'pair' is simply linked to 'p' via cmDataAppendChild() no
// reallocation or duplicattion takes place. // reallocation or duplicattion takes place.
cmData_t* cmRecdAppendPair( cmData_t* p, cmData_t* pair ); cmData_t* cmDataRecdAppendPair( cmData_t* p, cmData_t* pair );
// Var-args format: // Var-args format:
// <label|id> <typeId> <value> {<cnt>} // <label|id> {<cid>} <typeId> <value> {<cnt>}
// scalar types: <value> is literal,<cnt> is not included // scalar types: <value> is literal,<cnt> is not included
// null type: has no <value> or <cnt> // null type: has no <value> or <cnt>
// ptr types: <value> is pointer, <cnt> is element count // ptr types: <value> is pointer, <cnt> is element count
@ -529,13 +562,28 @@ extern "C" {
unsigned cmDataSerializeByteCount( const cmData_t* p ); unsigned cmDataSerializeByteCount( const cmData_t* p );
cmDtRC_t cmDataSerialize( const cmData_t* p, void* buf, unsigned bufByteCnt ); cmDtRC_t cmDataSerialize( const cmData_t* p, void* buf, unsigned bufByteCnt );
cmDtRC_t cmDataDeserialize( const void* buf, unsigned bufByteCnt, cmData_t** pp ); cmDtRC_t cmDataDeserialize( const void* buf, unsigned bufByteCnt, cmData_t** pp );
//-----------------------------------------------------------------------------
typedef cmHandle_t cmDataParserH_t;
//static cmDataParserH_t cmDataParserNullHandle;
cmDtRC_t cmDataParserCreate( cmCtx_t* ctx, cmDataParserH_t* hp );
cmDtRC_t cmDataParserDestroy( cmDataParserH_t* hp );
bool cmDataParserIsValid( cmDataParserH_t h );
// Parse a text representation into a 'record' type.
// Note that the text is wrapped with implied curly braces
// (e.g. "{ text }"). The contents of the text should therefore
// fit the record syntax (e.g. the first token should be a
// 'pair' label.
cmDtRC_t cmDataParserExec( cmDataParserH_t h, const cmChar_t* text, cmData_t** pp );
//-----------------------------------------------------------------------------
void cmDataPrint( const cmData_t* p, cmRpt_t* rpt ); void cmDataPrint( const cmData_t* p, cmRpt_t* rpt );
void cmDataTest( cmCtx_t* ctx ); void cmDataTest( cmCtx_t* ctx );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -60,7 +60,11 @@ extern "C" {
// Draw the page. // Draw the page.
void cmGrPageDraw( cmGrPgH_t h, cmGrDcH_t dcH ); void cmGrPageDraw( cmGrPgH_t h, cmGrDcH_t dcH );
// Label callback functions are used to translate numeric axis values to
// text strings. Multiple label callback functions can be registered with
// a page and then assigned to a given view axis via cmGrViewSetLabelFunc().
typedef void (*cmGrLabelFunc_t)( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value ); typedef void (*cmGrLabelFunc_t)( void* arg, cmChar_t* label, unsigned labelCharCnt, cmGrV_t value );
// Returns id of the new page label function. // Returns id of the new page label function.
unsigned cmGrPageLabelFuncRegister( cmGrPgH_t h, cmGrLabelFunc_t func, void* arg, const cmChar_t* label ); unsigned cmGrPageLabelFuncRegister( cmGrPgH_t h, cmGrLabelFunc_t func, void* arg, const cmChar_t* label );
unsigned cmGrPageLabelFuncCount( cmGrPgH_t h ); unsigned cmGrPageLabelFuncCount( cmGrPgH_t h );

173
cmLex.c
View File

@ -7,6 +7,12 @@
#include "cmMallocDebug.h" #include "cmMallocDebug.h"
#include "cmFile.h" #include "cmFile.h"
enum
{
kRealFloatLexFl = 0x01,
kIntUnsignedLexFl = 0x02
};
typedef struct typedef struct
{ {
unsigned code; unsigned code;
@ -29,6 +35,7 @@ cmLexErrorRecd cmLexErrorArray[] =
{ kMemAllocErrLexRC, "An attempted memory allocation failed"}, { kMemAllocErrLexRC, "An attempted memory allocation failed"},
{ kEofRC, "The end of the input text was encountered (this is a normal condition not an error)"}, { kEofRC, "The end of the input text was encountered (this is a normal condition not an error)"},
{ kInvalidLexTIdLexRC, "An invalid token id was encountered."}, { kInvalidLexTIdLexRC, "An invalid token id was encountered."},
{ kSignErrorLexRC, "A signed integer has a 'u' or 'U' suffix."},
{ kInvalidLexRC, "Unknown lexer error code." } { kInvalidLexRC, "Unknown lexer error code." }
}; };
@ -75,6 +82,7 @@ typedef struct cmLex_str
cmChar_t* textBuf; // text buf used by cmLexSetFile() cmChar_t* textBuf; // text buf used by cmLexSetFile()
unsigned attrFlags; // used to store the int and real suffix type flags
} cmLex; } cmLex;
@ -148,7 +156,7 @@ unsigned _cmLexRealMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
unsigned i = 0; unsigned i = 0;
unsigned n = 0; // decimal point counter unsigned n = 0; // decimal point counter
unsigned d = 0; // digit counter unsigned d = 0; // digit counter
bool fl = false; // true if this real includes an exponent bool fl = false; // expo flag
for(; i<cn && n<=1; ++i) for(; i<cn && n<=1; ++i)
{ {
@ -170,10 +178,12 @@ unsigned _cmLexRealMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
// if there was at least one digit and the next char is an 'e' // if there was at least one digit and the next char is an 'e'
if( d>0 && i<cn && (cp[i] == 'e' || cp[i] == 'E') ) if( d>0 && i<cn && (cp[i] == 'e' || cp[i] == 'E') )
{ {
d=0; unsigned e=0;
++i; ++i;
unsigned j = i; unsigned j = i;
fl = false;
for(; i<cn; ++i) for(; i<cn; ++i)
{ {
if( i==j && cp[i]=='-' ) // allow the char following the e to be '-' if( i==j && cp[i]=='-' ) // allow the char following the e to be '-'
@ -181,6 +191,7 @@ unsigned _cmLexRealMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
if( isdigit(cp[i]) ) if( isdigit(cp[i]) )
{ {
++e;
++d; ++d;
continue; continue;
} }
@ -190,17 +201,42 @@ unsigned _cmLexRealMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
} }
// an exp exists if digits follwed the 'e' // an exp exists if digits follwed the 'e'
fl = d > 0; fl = e > 0;
} }
return i>1 && (n==1 || fl) ? i : 0; // if at least one digit was found
if( d>0 )
{
// Note that this path allows a string w/o a decimal pt to trigger a match.
if(i<cn)
{
// if the real has a suffix
switch(cp[i])
{
case 'F':
case 'f':
p->attrFlags = cmSetFlag(p->attrFlags,kRealFloatLexFl);
++i;
break;
}
}
// match w/o suffix return
if( d>0 && (fl || n==1 || cmIsFlag(p->attrFlags,kRealFloatLexFl)) )
return i;
}
return 0; // no-match return
} }
unsigned _cmLexIntMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr ) unsigned _cmLexIntMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
{ {
unsigned i = 0; unsigned i = 0;
bool signFl = false; bool signFl = false;
for(; i<cn; ++i) for(; i<cn; ++i)
{ {
if( i==0 && cp[i]=='-' ) if( i==0 && cp[i]=='-' )
@ -222,9 +258,35 @@ unsigned _cmLexIntMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cm
// //
// The current implementation recognizes all numeric strings // The current implementation recognizes all numeric strings
// containing a decimal point as reals. // containing a decimal point as reals.
return signFl && i==1 ? 0 : i; // if no integer was found
if( (signFl && i==0) || i==0 )
return 0;
// check for suffix
if(i<cn )
{
switch(cp[i])
{
case 'u':
case 'U':
if( signFl )
_cmLexError(p,kSignErrorLexRC,"A signed integer has a 'u' or 'U' suffix.");
else
{
p->attrFlags = cmSetFlag(p->attrFlags,kIntUnsignedLexFl);
++i;
}
break;
default:
break;
}
}
return i;
} }
unsigned _cmLexHexMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr ) unsigned _cmLexHexMatcher( cmLex* p, const cmChar_t* cp, unsigned cn, const cmChar_t* keyStr )
@ -387,23 +449,6 @@ cmLexH cmLexInit( const cmChar_t* cp, unsigned cn, unsigned flags, cmRpt_t* rpt
_cmLexSetTextBuffer( p, cp, cn ); _cmLexSetTextBuffer( p, cp, cn );
/*
p->cp = (cn==0) ? NULL : cp;
p->cn = (cp==NULL) ? 0 : cn;
p->ci = 0;
p->curTokenId = kErrorLexTId;
p->curTokenCharIdx = cmInvalidIdx;
p->curTokenCharCnt = 0;
p->curLine = 0;
p->curCol = 0;
p->nextLine = 0;
p->nextCol = 0;
*/
int init_mfn = 10; int init_mfn = 10;
p->mfp = cmMemAllocZ( cmLexMatcher, init_mfn ); p->mfp = cmMemAllocZ( cmLexMatcher, init_mfn );
p->mfn = init_mfn; p->mfn = init_mfn;
@ -537,70 +582,6 @@ cmRC_t cmLexSetFile( cmLexH h, const cmChar_t* fn )
return rc; return rc;
} }
/*
cmRC_t cmLexSetFile( cmLexH h, const cmChar_t* fn )
{
cmRC_t rc = kOkLexRC;
FILE* fp = NULL;
cmLex* p = _cmLexHandleToPtr(h);
unsigned n = 0;
assert( fn != NULL && p != NULL );
// open the file
if((fp = fopen(fn,"rb")) == NULL )
return _cmLexError(p,kFileOpenErrLexRC,"Unable to open the file:'%s'.",fn);
// seek to the end
if( fseek(fp,0,SEEK_END) != 0 )
{
rc= _cmLexError(p,kFileSeekErrLexRC,"Unable to seek to the end of '%s'.",fn);
goto errLabel;
}
// get the length of the file
if( (n=ftell(fp)) == 0 )
{
rc = _cmLexError(p,kFileOpenErrLexRC,"The file '%s' appears to be empty.",fn);
goto errLabel;
}
// rewind the file
if( fseek(fp,0,SEEK_SET) != 0 )
{
rc = _cmLexError(p,kFileSeekErrLexRC,"Unable to seek to the beginning of '%s'.",fn);
goto errLabel;
}
// allocate the text buffer
if((p->textBuf = cmMemResizeZ( char, p->textBuf, n+1)) == NULL )
{
rc = _cmLexError(p,kMemAllocErrLexRC,"Unable to allocate the text file buffer for:'%s'.",fn);
goto errLabel;
}
// read the file into the text buffer
if( fread(p->textBuf,n,1,fp) != 1 )
{
rc = _cmLexError(p,kFileReadErrLexRC,"File read failed on:'%s'.",fn);
goto errLabel;
}
if((rc = _cmLexSetTextBuffer( p, p->textBuf, n )) != kOkLexRC )
goto errLabel;
errLabel:
// close the file
if( fclose(fp) != 0 )
{
rc = _cmLexError(p,kFileCloseErrLexRC,"File close failed on:'%s'.",fn);
goto errLabel;
}
return rc;
}
*/
cmLexMatcher* _cmLexFindUserToken( cmLex* p, unsigned id, const cmChar_t* tokenStr ) cmLexMatcher* _cmLexFindUserToken( cmLex* p, unsigned id, const cmChar_t* tokenStr )
{ {
@ -689,9 +670,9 @@ unsigned cmLexGetNextToken( cmLexH h )
p->curTokenId = kErrorLexTId; p->curTokenId = kErrorLexTId;
p->curTokenCharIdx = cmInvalidIdx; p->curTokenCharIdx = cmInvalidIdx;
p->curTokenCharCnt = 0; p->curTokenCharCnt = 0;
p->attrFlags = 0;
// try each matcher
// try each mater
for(; mi<p->mfi; ++mi) for(; mi<p->mfi; ++mi)
if( p->mfp[mi].enableFl ) if( p->mfp[mi].enableFl )
{ {
@ -701,6 +682,7 @@ unsigned cmLexGetNextToken( cmLexH h )
else else
charCnt = p->mfp[mi].userPtr( p->cp + p->ci, p->cn - p->ci); charCnt = p->mfp[mi].userPtr( p->cp + p->ci, p->cn - p->ci);
// notice if the matcher set the error code
if( cmErrLastRC(&p->err) != kOkLexRC ) if( cmErrLastRC(&p->err) != kOkLexRC )
return kErrorLexTId; return kErrorLexTId;
@ -823,6 +805,19 @@ float cmLexTokenFloat( cmLexH h )
double cmLexTokenDouble( cmLexH h ) double cmLexTokenDouble( cmLexH h )
{ return strtod( cmLexTokenText(h),NULL ); } { return strtod( cmLexTokenText(h),NULL ); }
bool cmLexTokenIsUnsigned( cmLexH h )
{
cmLex* p = _cmLexHandleToPtr(h);
return p->curTokenId == kIntLexTId && cmIsFlag(p->attrFlags,kIntUnsignedLexFl);
}
bool cmLexTokenIsSinglePrecision( cmLexH h )
{
cmLex* p = _cmLexHandleToPtr(h);
return p->curTokenId == kRealLexTId && cmIsFlag(p->attrFlags,kRealFloatLexFl);
}
unsigned cmLexCurrentLineNumber( cmLexH h ) unsigned cmLexCurrentLineNumber( cmLexH h )
{ {
cmLex* p = _cmLexHandleToPtr(h); cmLex* p = _cmLexHandleToPtr(h);

15
cmLex.h
View File

@ -50,7 +50,8 @@ enum
kMemAllocErrLexRC, //< 10 An attempted memory allocation failed kMemAllocErrLexRC, //< 10 An attempted memory allocation failed
kEofRC, //< 11 The end of the input text was encountered (this is a normal condition not an error) kEofRC, //< 11 The end of the input text was encountered (this is a normal condition not an error)
kInvalidLexTIdLexRC, //< 12 An invalid lex token id was encountered. kInvalidLexTIdLexRC, //< 12 An invalid lex token id was encountered.
kInvalidLexRC //< 13 Sentinal value. kSignErrorLexRC, //< 13 An signed integer has a 'u' or 'U' suffix."
kInvalidLexRC //< 1r Sentinal value.
}; };
@ -119,15 +120,23 @@ unsigned cmLexTokenCharCount( cmLexH h );
// Return the value of the current token as an integer. // Return the value of the current token as an integer.
int cmLexTokenInt( cmLexH h ); int cmLexTokenInt( cmLexH h );
// Return the value of the current token as an integer. // Return the value of the current token as an unsigned integer.
unsigned cmLexTokenUInt( cmLexH h ); unsigned cmLexTokenUInt( cmLexH h );
// Return the value of the current token as an integer. // Return the value of the current token as a float.
float cmLexTokenFloat( cmLexH h ); float cmLexTokenFloat( cmLexH h );
// Return the value of the current token as a double. // Return the value of the current token as a double.
double cmLexTokenDouble( cmLexH h ); double cmLexTokenDouble( cmLexH h );
// Return true if the current token is an int and it was suffixed
// with 'u' to indicate that it is unsigned.
bool cmLexTokenIsUnsigned( cmLexH h );
// Return true if the current token is a real and it was suffexed
// with 'f' to indicate that it is a single precision float.
bool cmLexTokenIsSinglePrecision( cmLexH h );
// Return the line number associated with the current token // Return the line number associated with the current token
unsigned cmLexCurrentLineNumber( cmLexH h ); unsigned cmLexCurrentLineNumber( cmLexH h );

View File

@ -64,7 +64,7 @@ extern "C" {
{ {
unsigned uid; // uid's are unique among all msg's in the file unsigned uid; // uid's are unique among all msg's in the file
unsigned dtick; // delta ticks unsigned dtick; // delta ticks
unsigned atick; unsigned atick; // accumulated ticks
cmMidiByte_t status; // ch msg's have the channel value removed (it is stored in u.chMsgPtr->ch) cmMidiByte_t status; // ch msg's have the channel value removed (it is stored in u.chMsgPtr->ch)
cmMidiByte_t metaId; // cmMidiByte_t metaId; //
unsigned short trkIdx; // unsigned short trkIdx; //

353
cmProc4.c
View File

@ -4135,3 +4135,356 @@ cmRC_t cmScModulatorDump( cmScModulator* p )
return rc; return rc;
} }
//=======================================================================================================================
cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs )
{
cmRecdPlay* op = cmObjAlloc(cmRecdPlay,c,p);
if( cmRecdPlayInit(op,srate,fragCnt,chCnt,initFragSecs,maxLaSecs,curLaSecs) != cmOkRC )
cmRecdPlayFree(&op);
return op;
}
cmRC_t cmRecdPlayFree( cmRecdPlay** pp )
{
cmRC_t rc = cmOkRC;
if( pp==NULL || *pp==NULL )
return rc;
cmRecdPlay* p = *pp;
if((rc = cmRecdPlayFinal(p)) != cmOkRC )
return rc;
cmObjFree(pp);
return rc;
}
cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs )
{
cmRC_t rc;
unsigned i;
if( curLaSecs > maxLaSecs )
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The initial look-ahead time %f is greater than the maximum look-ahead time %f.",curLaSecs,maxLaSecs);
if((rc = cmRecdPlayFinal(p)) != cmOkRC )
return rc;
if( chCnt == 0 )
return cmOkRC;
p->frags = cmMemAllocZ(cmRecdPlayFrag,fragCnt);
p->fragCnt = fragCnt;
p->srate = srate;
p->chCnt = chCnt;
p->initFragSecs = initFragSecs;
p->maxLaSmpCnt = floor(maxLaSecs*srate);
p->curLaSmpCnt = floor(curLaSecs*srate);
p->laChs = cmMemAllocZ(cmSample_t*,chCnt);
p->laSmpIdx = 0;
for(i=0; i<chCnt; ++i)
p->laChs[i] = cmMemAllocZ(cmSample_t,p->maxLaSmpCnt);
return rc;
}
cmRC_t cmRecdPlayFinal( cmRecdPlay* p )
{
unsigned i,j;
// free the fragments
for(i=0; i<p->fragCnt; ++i)
{
for(j=0; j<p->chCnt; ++j)
cmMemFree(p->frags[i].chArray[j]);
cmMemFree(p->frags[i].chArray);
}
// free the look-ahead buffers
for(i=0; i<p->chCnt; ++i)
cmMemFree(p->laChs[i]);
cmMemPtrFree(&p->laChs);
cmMemPtrFree(&p->frags);
p->fragCnt = 0;
p->chCnt = 0;
p->rlist = NULL;
p->plist = NULL;
return cmOkRC;
}
cmRC_t cmRecdPlayRegisterFrag( cmRecdPlay* p, unsigned fragIdx, unsigned labelSymId )
{
assert( fragIdx < p->fragCnt );
unsigned i;
p->frags[ fragIdx ].labelSymId = labelSymId;
p->frags[ fragIdx ].chArray = cmMemResizeZ(cmSample_t*,p->frags[fragIdx].chArray,p->chCnt);
for(i=0; i<p->chCnt; ++i)
{
p->frags[ fragIdx ].allocCnt = floor(p->initFragSecs * p->srate);
p->frags[ fragIdx ].chArray[i] = cmMemResizeZ(cmSample_t,p->frags[ fragIdx ].chArray[i],p->frags[fragIdx].allocCnt);
}
return cmOkRC;
}
cmRC_t cmRecdPlayRewind( cmRecdPlay* p )
{
unsigned i;
p->laSmpIdx = 0;
while( p->plist != NULL )
cmRecdPlayEndPlay(p,p->plist->labelSymId);
while( p->rlist != NULL )
cmRecdPlayEndRecord(p,p->plist->labelSymId);
for(i=0; i<p->fragCnt; ++i)
p->frags[i].playIdx = 0;
return cmOkRC;
}
cmRC_t cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId )
{
unsigned i;
for(i=0; i<p->fragCnt; ++i)
if( p->frags[i].labelSymId == labelSymId )
{
// if the frag is not already on the recd list
if( p->frags[i].rlink == NULL )
{
p->frags[i].recdIdx = 0;
p->frags[i].playIdx = 0;
p->frags[i].rlink = p->rlist;
p->rlist = p->frags + i;
// handle LA buf longer than frag buf.
int cpyCnt = cmMin(p->curLaSmpCnt,p->frags[i].allocCnt);
// go backwards in LA buf from newest sample to find init src offset
int srcOffs = p->laSmpIdx - cpyCnt;
// if the src is before the first sample in the LA buf then wrap to end of buf
if( srcOffs < 0 )
srcOffs += p->maxLaSmpCnt;
assert( 0 <= srcOffs && srcOffs < p->maxLaSmpCnt );
// cnt of samples to copy from LA buf (limited by end of LA buf)
int n0 = cmMin(cpyCnt,p->maxLaSmpCnt - srcOffs);
// if necessary wrap to begin of LA buf for remaining samples
int n1 = cpyCnt>n0 ? n1 = cpyCnt-n0 : 0;
int j;
assert(n0+n1 == cpyCnt );
for(j=0; j<p->chCnt; ++j)
cmVOS_Copy(p->frags[i].chArray[j],n0,p->laChs[j]+srcOffs);
if( n1 > 0 )
{
for(j=0; j<p->chCnt; ++j)
cmVOS_Copy(p->frags[i].chArray[j]+n0,n1,p->laChs[j]);
}
p->frags[i].recdIdx = cpyCnt;
}
return cmOkRC;
}
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'begin record'.",labelSymId);
}
cmRC_t cmRecdPlayEndRecord( cmRecdPlay* p, unsigned labelSymId )
{
cmRecdPlayFrag* fp = p->rlist;
cmRecdPlayFrag* pp = NULL;
for(; fp != NULL; fp=fp->rlink )
{
if( fp->labelSymId == labelSymId )
{
if( pp == NULL )
p->rlist = fp->rlink;
else
pp->rlink = fp->rlink;
fp->rlink = NULL;
return cmOkRC;
}
pp = fp;
}
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'end record'.",labelSymId);
}
cmRC_t cmRecdPlayBeginPlay( cmRecdPlay* p, unsigned labelSymId )
{
unsigned i;
for(i=0; i<p->fragCnt; ++i)
if( p->frags[i].labelSymId == labelSymId )
{
// if the frag is not already on the play list
if( p->frags[i].plink == NULL )
{
p->frags[i].playIdx = 0;
p->frags[i].fadeSmpIdx = 0;
p->frags[i].fadeDbPerSec = 0.0;
p->frags[i].plink = p->plist;
p->plist = p->frags + i;
}
return cmOkRC;
}
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'begin play'.",labelSymId);
}
cmRC_t cmRecdPlayEndPlay( cmRecdPlay* p, unsigned labelSymId )
{
cmRecdPlayFrag* fp = p->plist;
cmRecdPlayFrag* pp = NULL;
for(; fp != NULL; fp=fp->plink )
{
if( fp->labelSymId == labelSymId )
{
if( pp == NULL )
p->plist = fp->plink;
else
pp->plink = fp->plink;
fp->plink = NULL;
return cmOkRC;
}
pp = fp;
}
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'end play'.",labelSymId);
}
cmRC_t cmRecdPlayBeginFade( cmRecdPlay* p, unsigned labelSymId, double fadeDbPerSec )
{
cmRecdPlayFrag* fp = p->plist;
for(; fp != NULL; fp=fp->plink )
if( fp->labelSymId == labelSymId )
{
fp->fadeDbPerSec = -fabs(fadeDbPerSec);
return cmOkRC;
}
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "The fragment label symbol id '%i' not found for 'fade begin'.",labelSymId);
}
cmRC_t cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_t** oChs, unsigned chCnt, unsigned smpCnt )
{
unsigned i;
chCnt = cmMin(chCnt, p->chCnt);
//-------------------------------------------------------------------
// copy incoming audio into the look-head buffers
//
// if the number of incoming samples is longer than the look-head buffer
// then copy exactly maxLaSmpCnt samples from the end of the incoming sample
// buffer to the look-ahead buffer.
unsigned srcOffs = 0;
unsigned srcSmpCnt = smpCnt;
if( srcSmpCnt > p->maxLaSmpCnt )
{
// advance incoming sample buffer so that there are maxLaSmpCnt samples remaining
srcOffs = smpCnt-p->maxLaSmpCnt;
srcSmpCnt = p->maxLaSmpCnt; // decrease the total samples to copy
}
// count of samples from cur posn to end of the LA buffer.
unsigned n0 = cmMin(srcSmpCnt, p->maxLaSmpCnt - p->laSmpIdx );
// count of samples past the end of the LA buffer to be wrapped into begin of buffer
unsigned n1 = srcSmpCnt>n0 ? srcSmpCnt-n0 : 0;
assert(n0+n1 == srcSmpCnt);
// copy first block to end of LA buffer
for(i=0; i<chCnt; ++i)
cmVOS_Copy(p->laChs[i]+p->laSmpIdx,n0,iChs[i] + srcOffs);
p->laSmpIdx += n0;
if( n1!=0)
{
// copy second block to begin of LA buffer
for(i=0; i<chCnt; ++i)
cmVOS_Copy(p->laChs[i],n1,iChs[i] + srcOffs + n0);
p->laSmpIdx = n1;
}
//-------------------------------------------------------------------
// copy incoming audio into the active record buffers
//
cmRecdPlayFrag* fp = p->rlist;
for(; fp!=NULL; fp=fp->rlink)
{
assert( fp->recdIdx <= fp->allocCnt);
unsigned n = cmMin(fp->allocCnt - fp->recdIdx,smpCnt);
unsigned i;
for(i=0; i<p->chCnt; ++i)
{
cmVOS_Copy(fp->chArray[i] + fp->recdIdx, n, iChs[i] );
fp->recdIdx += n;
}
}
//-------------------------------------------------------------------
// copy outgoing audio out of the active play buffers
//
fp = p->plist;
for(; fp!=NULL; fp=fp->rlink)
{
assert( fp->playIdx <= fp->recdIdx);
double gain = pow(10.0,((fp->fadeSmpIdx / p->srate) * fp->fadeDbPerSec)/20.0);
unsigned n = cmMin(fp->recdIdx - fp->playIdx,smpCnt);
unsigned i;
for(i=0; i<p->chCnt; ++i)
{
cmVOS_MultVVS(oChs[i],n,fp->chArray[i] + fp->playIdx,gain);
fp->playIdx += n;
}
// if a fade rate has been set then advance the fade phase
if(fp->fadeDbPerSec!=0.0)
fp->fadeSmpIdx += smpCnt;
}
return cmOkRC;
}

View File

@ -626,6 +626,55 @@ extern "C" {
cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx ); cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx );
cmRC_t cmScModulatorDump( cmScModulator* p ); cmRC_t cmScModulatorDump( cmScModulator* p );
//=======================================================================================================================
typedef struct cmRecdPlayFrag_str
{
unsigned labelSymId; // this fragments label
cmSample_t** chArray; // record buffer chArray[cmRecdPlay.chCnt][allocCnt]
unsigned allocCnt; // count of samples allocated to each channel
unsigned playIdx; // index of next sample to play
unsigned recdIdx; // index of next sample to receieve audio (count of full samples)
double fadeDbPerSec; // fade rate in dB per second
unsigned fadeSmpIdx;
struct cmRecdPlayFrag_str* rlink; // cmRecdPlay.rlist link
struct cmRecdPlayFrag_str* plink; // cmRecdPlay.plist link
} cmRecdPlayFrag;
typedef struct
{
cmObj obj;
cmRecdPlayFrag* frags; // frags[fragCnt] fragment array
unsigned fragCnt; // count of fragments
double srate; // system sample rate
unsigned chCnt; // count of input and output audio channels
double initFragSecs; // size initial memory allocated to each frag in seconds
unsigned maxLaSmpCnt; // samples allocated to each channel of the look-ahead buffers.
unsigned curLaSmpCnt; // current look-ahead time in samples (curLaSmpCnt<=maxLaSmpCnt)
cmSample_t** laChs; // laChs[chCnt][maxLaSmpCnt] - look-ahead buffers
int laSmpIdx; // next look-ahead buffer index to receive a sample
cmRecdPlayFrag* plist; // currently playing frags
cmRecdPlayFrag* rlist; // currently recording frags
} cmRecdPlay;
cmRecdPlay* cmRecdPlayAlloc( cmCtx* c, cmRecdPlay* p, double srate, unsigned fragCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs );
cmRC_t cmRecdPlayFree( cmRecdPlay** pp );
cmRC_t cmRecdPlayInit( cmRecdPlay* p, double srate, unsigned flagCnt, unsigned chCnt, double initFragSecs, double maxLaSecs, double curLaSecs );
cmRC_t cmRecdPlayFinal( cmRecdPlay* p );
cmRC_t cmRecdPlayRegisterFrag( cmRecdPlay* p, unsigned fragIdx, unsigned labelSymId );
cmRC_t cmRecdPlayRewind( cmRecdPlay* p );
cmRC_t cmRecdPlayBeginRecord( cmRecdPlay* p, unsigned labelSymId );
cmRC_t cmRecdPlayEndRecord( cmRecdPlay* p, unsigned labelSymId );
cmRC_t cmRecdPlayBeginPlay( cmRecdPlay* p, unsigned labelSymId );
cmRC_t cmRecdPlayEndPlay( cmRecdPlay* p, unsigned labelSymId );
cmRC_t cmRecdPlayBeginFade( cmRecdPlay* p, unsigned labelSymId, double fadeDbPerSec );
cmRC_t cmRecdPlayExec( cmRecdPlay* p, const cmSample_t** iChs, cmSample_t** oChs, unsigned chCnt, unsigned smpCnt );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -42,12 +42,15 @@ extern "C" {
const void* cmStackTop( cmStackH_t h ); const void* cmStackTop( cmStackH_t h );
// Set the value of 'dataEleCnt' elements on the stack. // Set the value of 'dataEleCnt' elements on the stack.
// The top element is at index cmStackCount() - 1.
cmStRC_t cmStackSet( cmStackH_t h, unsigned index, const void* data, unsigned dataEleCnt ); cmStRC_t cmStackSet( cmStackH_t h, unsigned index, const void* data, unsigned dataEleCnt );
// Copy 'dataEleCnt' elements into the buffer pointed to by 'data'. // Copy 'dataEleCnt' elements into the buffer pointed to by 'data'.
// The top element is at index cmStackCount() - 1.
cmStRC_t cmStackGetN( cmStackH_t h, unsigned index, void* data, unsigned dataEleCnt ); cmStRC_t cmStackGetN( cmStackH_t h, unsigned index, void* data, unsigned dataEleCnt );
// Return a pointer to a single element on the stack. // Return a pointer to a single element on the stack.
// The top element is at index cmStackCount() - 1.
const void* cmStackGet( cmStackH_t h, unsigned index ); const void* cmStackGet( cmStackH_t h, unsigned index );
// Convert the internal representation of the stack to a linear array and return // Convert the internal representation of the stack to a linear array and return

View File

@ -5418,6 +5418,7 @@ cmDspClassConsFunc_t _cmDspClassBuiltInArray[] =
cmActiveMeasClassCons, cmActiveMeasClassCons,
cmAmSyncClassCons, cmAmSyncClassCons,
cmNanoMapClassCons, cmNanoMapClassCons,
cmRecdPlayClassCons,
NULL, NULL,
}; };

View File

@ -572,7 +572,7 @@ cmDspRC_t _cmDspScoreReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t*
} }
if((tlFn = cmDspStrcz(inst, kFnScId )) != NULL ) if((tlFn = cmDspStrcz(inst, kFnScId )) != NULL )
if( cmScoreInitialize(ctx->cmCtx, &p->scH, tlFn, cmDspSampleRate(ctx), dynRefArray, dynRefCnt, _cmDspScoreCb, p, cmSymTblNullHandle ) != kOkTlRC ) if( cmScoreInitialize(ctx->cmCtx, &p->scH, tlFn, cmDspSampleRate(ctx), dynRefArray, dynRefCnt, _cmDspScoreCb, p, ctx->stH ) != kOkTlRC )
rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Score file open failed."); rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Score file open failed.");
errLabel: errLabel:
@ -2264,3 +2264,262 @@ struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx )
return &_cmNanoMapDC; return &_cmNanoMapDC;
} }
//==========================================================================================================================================
enum
{
kChCntPrId,
kFnPrId,
kSecsPrId,
kMaxLaSecsPrId,
kCurLaSecsPrId,
kFadeRatePrId,
kScLocIdxPrId,
kCmdPrId,
kInAudioBasePrId
};
cmDspClass_t _cmRecdPlayDC;
typedef struct
{
cmDspInst_t inst;
cmRecdPlay* rcdply;
cmScH_t scH;
unsigned onSymId;
unsigned offSymId;
unsigned audioOutBaseId;
unsigned chCnt;
unsigned scLocIdx;
} cmDspRecdPlay_t;
cmDspRC_t _cmDspRecdPlayOpenScore( cmDspCtx_t* ctx, cmDspInst_t* inst )
{
cmDspRC_t rc =kOkDspRC;
const cmChar_t* fn;
cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
p->scLocIdx = 0;
if((fn = cmDspStrcz(inst,kFnPrId)) == NULL || strlen(fn)==0 )
return cmErrMsg(&inst->classPtr->err, kInvalidArgDspRC, "No score file name supplied.");
if( cmScoreInitialize(ctx->cmCtx, &p->scH, fn, cmDspSampleRate(ctx), NULL, 0, NULL, NULL, ctx->stH ) != kOkScRC )
return cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to open the score '%s'.",fn);
if( cmScoreIsValid(p->scH) )
{
unsigned i;
unsigned markerCnt = cmScoreMarkerLabelCount(p->scH);
double initFragSecs = cmDspDouble(inst,kSecsPrId);
double maxLaSecs = cmDspDouble(inst,kMaxLaSecsPrId);
double curLaSecs = cmDspDouble(inst,kCurLaSecsPrId);
if((p->rcdply = cmRecdPlayAlloc(ctx->cmProcCtx, NULL, cmDspSampleRate(ctx), markerCnt, p->chCnt, initFragSecs, maxLaSecs, curLaSecs)) == NULL)
return cmErrMsg(&inst->classPtr->err,kSubSysFailDspRC,"Unable to create the internal recorder-player object.");
for(i=0; i<markerCnt; ++i)
cmRecdPlayRegisterFrag(p->rcdply,i, cmScoreMarkerLabelSymbolId(p->scH,i ));
}
return rc;
}
cmDspInst_t* _cmDspRecdPlayAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
{
if( va_cnt < 1 )
{
cmDspClassErr(ctx,classPtr,kVarArgParseFailDspRC,"The 'RecdPlay' constructor must have a count of input ports.");
return NULL;
}
va_list vl1;
va_copy(vl1,vl);
int chCnt = va_arg(vl,int);
unsigned audioOutBase = kInAudioBasePrId + chCnt;
cmDspRecdPlay_t* p = cmDspInstAllocV(cmDspRecdPlay_t,ctx,classPtr,instSymId,id,storeSymId,va_cnt,vl1,
1, "chs", kChCntPrId, 0,0, kUIntDsvFl | kReqArgDsvFl, "channel count.",
1, "fn", kFnPrId, 0,0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Score file." ,
1, "secs", kSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl | kReqArgDsvFl, "Initial fragment allocation in seconds.",
1, "maxla", kMaxLaSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl, "Maximum look-ahead buffer in seconds.",
1, "curla", kCurLaSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl, "Current look-head buffer in seconds.",
1, "frate", kFadeRatePrId, 0,0, kInDsvFl | kDoubleDsvFl, "Fade rate in dB per second.",
1, "index", kScLocIdxPrId, 0,0, kInDsvFl | kUIntDsvFl, "Score follower location index.",
1, "cmd", kCmdPrId, 0,0, kInDsvFl | kSymDsvFl, "on=reset off=stop.",
chCnt, "in", kInAudioBasePrId,0,1, kInDsvFl | kAudioBufDsvFl, "Audio input",
chCnt, "out", audioOutBase, 0,1, kOutDsvFl | kAudioBufDsvFl, "Audio output",
0 );
va_end(vl1);
p->onSymId = cmSymTblId(ctx->stH,"on");
p->offSymId = cmSymTblId(ctx->stH,"off");
p->audioOutBaseId = audioOutBase;
p->chCnt = chCnt;
p->scLocIdx = 0;
cmDspSetDefaultDouble(ctx,&p->inst, kSecsPrId, 0, 10.0 );
cmDspSetDefaultDouble(ctx,&p->inst, kMaxLaSecsPrId,0, 2.0);
cmDspSetDefaultDouble(ctx,&p->inst, kCurLaSecsPrId,0, 0.5);
cmDspSetDefaultDouble(ctx,&p->inst, kFadeRatePrId, 0, 1.0);
return &p->inst;
}
cmDspRC_t _cmDspRecdPlayFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspRC_t rc = kOkDspRC;
cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
cmRecdPlayFree(&p->rcdply);
cmScoreFinalize(&p->scH);
return rc;
}
cmDspRC_t _cmDspRecdPlayReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspApplyAllDefaults(ctx,inst);
return _cmDspRecdPlayOpenScore(ctx,inst);
}
cmDspRC_t _cmDspRecdPlayExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspRC_t rc = kOkDspRC;
cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
const cmSample_t* x[ p->chCnt ];
cmSample_t* y[ p->chCnt ];
unsigned n;
unsigned i;
unsigned actChCnt = 0;
for(i=0; i<p->chCnt; ++i)
{
if( i==0 )
n = cmDspAudioBufSmpCount(ctx,inst,kInAudioBasePrId+i,0);
else
{ assert( n == cmDspAudioBufSmpCount(ctx,inst,kInAudioBasePrId+i,0)); }
x[i] = cmDspAudioBuf(ctx,inst,kInAudioBasePrId+i,0);
if( x[i] != NULL )
{
y[i] = cmDspAudioBuf(ctx,inst,p->audioOutBaseId+i,0);
if( y[i] != NULL )
{
assert( n == cmDspAudioBufSmpCount(ctx,inst,p->audioOutBaseId+i,0));
cmVOS_Zero(y[i],n);
actChCnt += 1;
}
}
}
cmRecdPlayExec(p->rcdply,x,y,actChCnt,n);
return rc;
}
cmDspRC_t _cmDspRecdPlayRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
{
cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
cmDspSetEvent(ctx,inst,evt);
switch( evt->dstVarId )
{
case kCmdPrId:
if( cmDspSymbol(inst,kCmdPrId) == p->onSymId )
{
printf("rewind\n");
cmRecdPlayRewind(p->rcdply);
p->scLocIdx = 0;
}
else
if( cmDspSymbol(inst,kCmdPrId) == p->offSymId )
{
}
break;
case kCurLaSecsPrId:
break;
case kScLocIdxPrId:
{
unsigned endScLocIdx = cmDspUInt(inst,kScLocIdxPrId) ;
for(; p->scLocIdx<=endScLocIdx; p->scLocIdx+=1)
{
cmScoreLoc_t* loc = cmScoreLoc(p->scH, p->scLocIdx );
cmScoreMarker_t* mp = loc->markList;
for(; mp!=NULL; mp=mp->link)
switch( mp->markTypeId )
{
case kRecdBegScMId:
printf("recd-beg\n");
cmRecdPlayBeginRecord(p->rcdply, mp->labelSymId );
break;
case kRecdEndScMId:
printf("recd-end\n");
cmRecdPlayEndRecord(p->rcdply, mp->labelSymId );
break;
case kPlayBegScMId:
printf("play-beg\n");
cmRecdPlayBeginPlay(p->rcdply, mp->labelSymId );
break;
case kPlayEndScMId:
printf("play-end\n");
cmRecdPlayEndPlay(p->rcdply, mp->labelSymId );
break;
case kFadeScMId:
printf("fade-beg\n");
cmRecdPlayBeginFade(p->rcdply, mp->labelSymId, cmDspDouble(inst,kFadeRatePrId) );
break;
default:
break;
}
}
p->scLocIdx = endScLocIdx+1;
}
break;
}
return kOkDspRC;
}
struct cmDspClass_str* cmRecdPlayClassCons( cmDspCtx_t* ctx )
{
cmDspClassSetup(&_cmRecdPlayDC,ctx,"RecdPlay",
NULL,
_cmDspRecdPlayAlloc,
_cmDspRecdPlayFree,
_cmDspRecdPlayReset,
_cmDspRecdPlayExec,
_cmDspRecdPlayRecv,
NULL,
NULL,
"Score controlled live recorder/player");
return &_cmRecdPlayDC;
}

View File

@ -16,6 +16,7 @@ extern "C" {
struct cmDspClass_str* cmActiveMeasClassCons( cmDspCtx_t* ctx ); struct cmDspClass_str* cmActiveMeasClassCons( cmDspCtx_t* ctx );
struct cmDspClass_str* cmAmSyncClassCons( cmDspCtx_t* ctx ); struct cmDspClass_str* cmAmSyncClassCons( cmDspCtx_t* ctx );
struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx ); struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx );
struct cmDspClass_str* cmRecdPlayClassCons( cmDspCtx_t* ctx );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -97,7 +97,10 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
double cmpWndMaxMs = 1000.0; double cmpWndMaxMs = 1000.0;
double cmpWndMs = 200.0; double cmpWndMs = 200.0;
double recdPlayInitAllocSecs = 10.0;
double recdPlayMaxLaSecs = 2.0;
double recdPlayCurLaSecs = 0.1;
double recdPlayFadeRateDbPerSec = 4.0;
memset(&r,0,sizeof(r)); memset(&r,0,sizeof(r));
cmErrSetup(&err,&cmCtx->rpt,"Kr Timeline"); cmErrSetup(&err,&cmCtx->rpt,"Kr Timeline");
@ -122,6 +125,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspInst_t* mop = cmDspSysAllocInst(h,"MidiOut", NULL, 2, r.midiDevice,r.midiOutPort); cmDspInst_t* mop = cmDspSysAllocInst(h,"MidiOut", NULL, 2, r.midiDevice,r.midiOutPort);
cmDspInst_t* sfp = cmDspSysAllocInst(h,"ScFol", NULL, 1, r.scFn ); cmDspInst_t* sfp = cmDspSysAllocInst(h,"ScFol", NULL, 1, r.scFn );
cmDspInst_t* amp = cmDspSysAllocInst(h,"ActiveMeas", NULL, 1, 100 ); cmDspInst_t* amp = cmDspSysAllocInst(h,"ActiveMeas", NULL, 1, 100 );
cmDspInst_t* rpp = cmDspSysAllocInst(h,"RecdPlay", NULL, 4, 2, r.scFn, recdPlayInitAllocSecs, recdPlayMaxLaSecs, recdPlayCurLaSecs, recdPlayFadeRateDbPerSec );
cmDspInst_t* modp = cmDspSysAllocInst(h,"ScMod", NULL, 2, r.modFn, "m1" ); cmDspInst_t* modp = cmDspSysAllocInst(h,"ScMod", NULL, 2, r.modFn, "m1" );
cmDspInst_t* asp = cmDspSysAllocInst(h,"AmSync", NULL, 0 ); cmDspInst_t* asp = cmDspSysAllocInst(h,"AmSync", NULL, 0 );
@ -173,14 +177,14 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspInst_t* kr00 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact ); cmDspInst_t* kr00 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact );
cmDspInst_t* kr01 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact ); cmDspInst_t* kr01 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact );
cmDspInst_t* fad0 = cmDspSysAllocInst(h, "Xfader", NULL, 3, xfadeChCnt, xfadeMs, xfadeInitFl ); cmDspInst_t* fad0 = cmDspSysAllocInst(h, "Xfader", NULL, 3, xfadeChCnt, xfadeMs, xfadeInitFl );
cmDspInst_t* mix0 = cmDspSysAllocInst(h, "AMix", NULL, 3, xfadeChCnt, mixGain, mixGain ); cmDspInst_t* mix0 = cmDspSysAllocInst(h, "AMix", NULL, 4, xfadeChCnt+1, mixGain, mixGain, mixGain );
cmDspInst_t* cmp0 = cmDspSysAllocInst(h,"Compressor", NULL, 8, cmpBypassFl, cmpThreshDb, cmpRatio_num, cmpAtkMs, cmpRlsMs, cmpMakeup, cmpWndMs, cmpWndMaxMs ); cmDspInst_t* cmp0 = cmDspSysAllocInst(h,"Compressor", NULL, 8, cmpBypassFl, cmpThreshDb, cmpRatio_num, cmpAtkMs, cmpRlsMs, cmpMakeup, cmpWndMs, cmpWndMaxMs );
cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 0 ); cmDspInst_t* ao0p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 0 );
cmDspInst_t* kr10 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact ); cmDspInst_t* kr10 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact );
cmDspInst_t* kr11 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact ); cmDspInst_t* kr11 = cmDspSysAllocInst(h, "Kr", NULL, 2, krWndSmpCnt, krHopFact );
cmDspInst_t* fad1 = cmDspSysAllocInst(h, "Xfader", NULL, 3, xfadeChCnt, xfadeMs, xfadeInitFl ); cmDspInst_t* fad1 = cmDspSysAllocInst(h, "Xfader", NULL, 3, xfadeChCnt, xfadeMs, xfadeInitFl );
cmDspInst_t* mix1 = cmDspSysAllocInst(h, "AMix", NULL, 3, xfadeChCnt, mixGain, mixGain ); cmDspInst_t* mix1 = cmDspSysAllocInst(h, "AMix", NULL, 4, xfadeChCnt+1, mixGain, mixGain, mixGain );
cmDspInst_t* cmp1 = cmDspSysAllocInst(h,"Compressor", NULL, 8, cmpBypassFl, cmpThreshDb, cmpRatio_num, cmpAtkMs, cmpRlsMs, cmpMakeup, cmpWndMs, cmpWndMaxMs ); cmDspInst_t* cmp1 = cmDspSysAllocInst(h,"Compressor", NULL, 8, cmpBypassFl, cmpThreshDb, cmpRatio_num, cmpAtkMs, cmpRlsMs, cmpMakeup, cmpWndMs, cmpWndMaxMs );
cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 1 ); cmDspInst_t* ao1p = cmDspSysAllocInst(h,"AudioOut", NULL, 1, 1 );
@ -378,12 +382,14 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspSysConnectAudio(h, wtp, "out", au0Sw, "a-in-0" ); // wt -> sw cmDspSysConnectAudio(h, wtp, "out", au0Sw, "a-in-0" ); // wt -> sw
cmDspSysConnectAudio(h, ai0p, "out", au0Sw, "a-in-1" ); // ain -> sw cmDspSysConnectAudio(h, ai0p, "out", au0Sw, "a-in-1" ); // ain -> sw
cmDspSysConnectAudio(h, ai0p, "out", mi0p, "in" ); cmDspSysConnectAudio(h, ai0p, "out", mi0p, "in" );
cmDspSysConnectAudio(h, au0Sw,"a-out", rpp, "in-0"); // sw -> rcdply
cmDspSysConnectAudio(h, au0Sw,"a-out", kr00, "in" ); // sw -> kr cmDspSysConnectAudio(h, au0Sw,"a-out", kr00, "in" ); // sw -> kr
cmDspSysConnectAudio(h, kr00, "out", fad0, "in-0"); // kr -> fad cmDspSysConnectAudio(h, kr00, "out", fad0, "in-0"); // kr -> fad
cmDspSysConnectAudio(h, fad0, "out-0", mix0, "in-0"); // fad -> mix cmDspSysConnectAudio(h, fad0, "out-0", mix0, "in-0"); // fad -> mix
cmDspSysConnectAudio(h, au0Sw,"a-out", kr01, "in" ); // sw -> kr cmDspSysConnectAudio(h, au0Sw,"a-out", kr01, "in" ); // sw -> kr
cmDspSysConnectAudio(h, kr01, "out", fad0, "in-1"); // kr -> fad cmDspSysConnectAudio(h, kr01, "out", fad0, "in-1"); // kr -> fad
cmDspSysConnectAudio(h, fad0, "out-1", mix0, "in-1"); // fad -> mix cmDspSysConnectAudio(h, fad0, "out-1", mix0, "in-1"); // fad -> mix
cmDspSysConnectAudio(h, rpp, "out-0", mix0, "in-2");
cmDspSysConnectAudio(h, mix0, "out", cmp0, "in"); // mix -> cmp cmDspSysConnectAudio(h, mix0, "out", cmp0, "in"); // mix -> cmp
cmDspSysConnectAudio(h, cmp0, "out", ao0p, "in" ); // cmp -> aout cmDspSysConnectAudio(h, cmp0, "out", ao0p, "in" ); // cmp -> aout
@ -391,12 +397,14 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspSysConnectAudio(h, wtp, "out", au1Sw, "a-in-0" ); // wt -> kr cmDspSysConnectAudio(h, wtp, "out", au1Sw, "a-in-0" ); // wt -> kr
cmDspSysConnectAudio(h, ai1p, "out", au1Sw, "a-in-1" ); cmDspSysConnectAudio(h, ai1p, "out", au1Sw, "a-in-1" );
cmDspSysConnectAudio(h, ai1p, "out", mi1p, "in" ); cmDspSysConnectAudio(h, ai1p, "out", mi1p, "in" );
cmDspSysConnectAudio(h, au1Sw,"a-out", rpp, "in-1"); // sw -> rcdply
cmDspSysConnectAudio(h, au1Sw,"a-out", kr10, "in" ); cmDspSysConnectAudio(h, au1Sw,"a-out", kr10, "in" );
cmDspSysConnectAudio(h, kr10, "out", fad1, "in-0"); cmDspSysConnectAudio(h, kr10, "out", fad1, "in-0");
cmDspSysConnectAudio(h, fad1, "out-0", mix1, "in-0"); cmDspSysConnectAudio(h, fad1, "out-0", mix1, "in-0");
cmDspSysConnectAudio(h, au1Sw,"a-out", kr11, "in" ); // wt -> kr cmDspSysConnectAudio(h, au1Sw,"a-out", kr11, "in" ); // wt -> kr
cmDspSysConnectAudio(h, kr11, "out", fad1, "in-1"); cmDspSysConnectAudio(h, kr11, "out", fad1, "in-1");
cmDspSysConnectAudio(h, fad1, "out-1", mix1, "in-1"); cmDspSysConnectAudio(h, fad1, "out-1", mix1, "in-1");
cmDspSysConnectAudio(h, rpp, "out-0", mix1, "in-2");
cmDspSysConnectAudio(h, mix1, "out", cmp1, "in"); cmDspSysConnectAudio(h, mix1, "out", cmp1, "in");
cmDspSysConnectAudio(h, cmp1, "out", ao1p, "in" ); // comp -> aout cmDspSysConnectAudio(h, cmp1, "out", ao1p, "in" ); // comp -> aout
@ -437,6 +445,7 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspSysInstallCb(h, pts, "on", wtRt, "s-in", NULL ); cmDspSysInstallCb(h, pts, "on", wtRt, "s-in", NULL );
cmDspSysInstallCb(h, wtRt,"s-out-0", wtp, "cmd", NULL ); cmDspSysInstallCb(h, wtRt,"s-out-0", wtp, "cmd", NULL );
cmDspSysInstallCb(h, pts, "on", modp, "cmd", NULL ); cmDspSysInstallCb(h, pts, "on", modp, "cmd", NULL );
cmDspSysInstallCb(h, pts, "on", rpp, "cmd", NULL );
cmDspSysInstallCb(h, onb, "sym", amCmd, "rewind",NULL ); cmDspSysInstallCb(h, onb, "sym", amCmd, "rewind",NULL );
cmDspSysInstallCb(h, onb, "out", achan0,"reset", NULL ); cmDspSysInstallCb(h, onb, "out", achan0,"reset", NULL );
cmDspSysInstallCb(h, onb, "out", achan1,"reset", NULL ); cmDspSysInstallCb(h, onb, "out", achan1,"reset", NULL );
@ -493,7 +502,8 @@ cmDspRC_t _cmDspSysPgm_TimeLine(cmDspSysH_t h, void** userPtrPtr )
cmDspSysInstallCb(h, mip, "d0", sfp, "d0", NULL ); cmDspSysInstallCb(h, mip, "d0", sfp, "d0", NULL );
cmDspSysInstallCb(h, mip, "status", sfp, "status", NULL ); cmDspSysInstallCb(h, mip, "status", sfp, "status", NULL );
// score follower to modulator and printers // score follower to recd_play,modulator and printers
cmDspSysInstallCb(h, sfp, "out", rpp, "index", NULL );
cmDspSysInstallCb(h, sfp, "out", modp, "index", NULL ); cmDspSysInstallCb(h, sfp, "out", modp, "index", NULL );
cmDspSysInstallCb(h, sfp, "recent", prp, "in", NULL ); // report 'recent' but only act on 'max' loc index cmDspSysInstallCb(h, sfp, "recent", prp, "in", NULL ); // report 'recent' but only act on 'max' loc index