cmProc4.h/c : Added the 'exec' entry type to cmScModulator.

This commit is contained in:
kevin 2016-07-06 18:55:36 -04:00
parent 7e3a3ff0ab
commit a607108e48
2 changed files with 267 additions and 20 deletions

264
cmProc4.c
View File

@ -2687,6 +2687,7 @@ cmRC_t cmScModulatorFree( cmScModulator** pp )
return rc; return rc;
cmMemFree(p->earray); cmMemFree(p->earray);
cmMemFree(p->xlist);
cmObjFree(pp); cmObjFree(pp);
return rc; return rc;
} }
@ -2700,11 +2701,12 @@ typedef struct
_cmScModTypeMap_t _cmScModTypeArray[] = _cmScModTypeMap_t _cmScModTypeArray[] =
{ {
{ kDeclModTId, 0, "decl" }, { kDeclModTId, 0, "decl" },
{ kSetModTId, 1, "set" }, { kSetModTId, 1, "set" },
{ kLineModTId, 2, "line" }, { kLineModTId, 2, "line" },
{ kSetLineModTId, 3, "sline" }, { kSetLineModTId, 3, "sline" },
{ kPostModTId, 4, "post" }, { kPostModTId, 4, "post" },
{ kExecModTId, 5, "exec" },
{ kInvalidModTId, 0, "<invalid>"} { kInvalidModTId, 0, "<invalid>"}
}; };
@ -2718,6 +2720,16 @@ const _cmScModTypeMap_t* _cmScModTypeLabelToMap( const cmChar_t* label )
return NULL; return NULL;
} }
const _cmScModTypeMap_t* _cmScModTypeIdToMap( unsigned typeId )
{
unsigned i;
for(i=0; _cmScModTypeArray[i].typeId!=kInvalidModTId; ++i)
if( _cmScModTypeArray[i].typeId == typeId )
return _cmScModTypeArray + i;
return NULL;
}
cmScModVar_t* _cmScModSymToVar( cmScModulator* p, unsigned varSymId ) cmScModVar_t* _cmScModSymToVar( cmScModulator* p, unsigned varSymId )
{ {
cmScModVar_t* vp = p->vlist; cmScModVar_t* vp = p->vlist;
@ -2752,14 +2764,14 @@ cmScModVar_t* _cmScModulatorInsertVar( cmScModulator* p, unsigned varSymId, unsi
return vp; return vp;
} }
cmScModEntry_t* _cmScModulatorInsertEntry(cmScModulator* p, unsigned idx, unsigned scLocIdx, unsigned modSymId, unsigned varSymId, unsigned typeId, unsigned paramCnt ) cmScModEntry_t* _cmScModulatorInsertEntry(cmScModulator* p, unsigned idx, unsigned scLocIdx, unsigned modSymId, unsigned varSymId, unsigned typeId, unsigned entryFlags, unsigned paramCnt )
{ {
assert( idx < p->en ); assert( idx < p->en );
p->earray[idx].scLocIdx = scLocIdx; p->earray[idx].scLocIdx = scLocIdx;
p->earray[idx].typeId = typeId; p->earray[idx].typeId = typeId;
p->earray[idx].varPtr = _cmScModulatorInsertVar(p,varSymId,0); p->earray[idx].varPtr = _cmScModulatorInsertVar(p,varSymId,0);
p->earray[idx].flags = entryFlags;
if( p->earray[idx].varPtr->outVarId == cmInvalidIdx ) if( p->earray[idx].varPtr->outVarId == cmInvalidIdx )
p->earray[idx].varPtr->outVarId = p->outVarCnt++; p->earray[idx].varPtr->outVarId = p->outVarCnt++;
@ -2821,6 +2833,86 @@ cmScModEntry_t* _cmScModulatorInsertEntry(cmScModulator* p, unsigned idx, unsign
} }
void _cmScProcessEntryGroups( cmScModulator* p )
{
unsigned i=0;
cmScModEntryGroup_t* g0 = NULL;
cmScModEntryGroup_t* g1 = p->glist;
while( i<p->en )
{
// if this is the first entry in a group
if( cmIsFlag(p->earray[i].flags , kLocLabelEntryFl ) )
{
// if no group record is avaiable ...
if( g1 == NULL )
{
// ... then allocate one and ...
g1 = cmMemAllocZ(cmScModEntryGroup_t,1);
// ... link it to the end of the group list
if( g0 == NULL )
p->glist = g1;
else
g0->link = g1;
}
unsigned j;
g1->n = 0;
// get a count of the entries in this group
while( i<p->en && p->earray[i+g1->n].scLocIdx == p->earray[i].scLocIdx )
g1->n += 1;
// allocate an array to hold the group
g1->base = cmMemResizeZ(cmScModEntry_t*,g1->base,g1->n);
for(j=0; j<g1->n; ++j)
g1->base[j] = p->earray + i + j;
i += g1->n;
// make the next group record available
g0 = g1;
g1 = g1->link;
}
else
{
i += 1;
}
}
// set successive records as invalid
for(; g1 != NULL; g1=g1->link)
g1->base = NULL;
}
void _cmScProcessExecList( cmScModulator* p )
{
unsigned i,j;
unsigned n = 0;
for(i=0; i<p->en; ++i)
if( cmIsNotFlag(p->earray[i].flags,kLocLabelEntryFl) )
n += 1;
p->xlist = cmMemResizeZ(cmScModEntry_t*,p->xlist,n);
p->xn = n;
for(i=0,j=0; i<p->en; ++i)
if( cmIsNotFlag(p->earray[i].flags,kLocLabelEntryFl) )
p->xlist[j++] = p->earray + i;
assert( j == p->xn );
}
cmRC_t _cmScModulatorParse( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, const cmChar_t* fn ) cmRC_t _cmScModulatorParse( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, const cmChar_t* fn )
{ {
cmRC_t rc = cmOkRC; cmRC_t rc = cmOkRC;
@ -2847,13 +2939,15 @@ cmRC_t _cmScModulatorParse( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, con
p->earray = cmMemResizeZ(cmScModEntry_t,p->earray,entryCnt); p->earray = cmMemResizeZ(cmScModEntry_t,p->earray,entryCnt);
p->en = entryCnt; p->en = entryCnt;
unsigned prvScLocIdx = cmInvalidIdx; unsigned prvScLocIdx = cmInvalidIdx;
const cmChar_t* prvModLabel = NULL; const cmChar_t* prvModLabel = NULL;
const cmChar_t* prvVarLabel = NULL; const cmChar_t* prvVarLabel = NULL;
const cmChar_t* prvTypeLabel = NULL; const cmChar_t* prvTypeLabel = NULL;
unsigned prvEntryFlags = 0;
for(i=0; i<entryCnt; ++i) for(i=0; i<entryCnt; ++i)
{ {
cmJsRC_t jsRC; cmJsRC_t jsRC = kOkJsRC;
const char* errLabelPtr = NULL; const char* errLabelPtr = NULL;
unsigned scLocIdx = cmInvalidIdx; unsigned scLocIdx = cmInvalidIdx;
const cmChar_t* modLabel = NULL; const cmChar_t* modLabel = NULL;
@ -2862,9 +2956,43 @@ cmRC_t _cmScModulatorParse( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, con
cmJsonNode_t* onp = cmJsonArrayElement(jnp,i); cmJsonNode_t* onp = cmJsonArrayElement(jnp,i);
cmJsonNode_t* dnp = NULL; cmJsonNode_t* dnp = NULL;
const _cmScModTypeMap_t* map = NULL; const _cmScModTypeMap_t* map = NULL;
unsigned locTypeId = kIntTId;
unsigned entryFlags = cmInvalidId;
// if a 'loc' field was specified for this label
if( cmJsonFindPair( onp, "loc" ) != NULL )
{
const cmChar_t* locLabel = NULL;
// get the type of the 'loc' value field
if( cmJsonMemberType(onp, "loc", &locTypeId) == kOkJsRC )
{
// read the 'loc' value field
if( locTypeId == kStringTId )
rc = cmJsonStringMember( onp, "loc", &locLabel );
else
rc = cmJsonUIntMember( onp, "loc", &scLocIdx);
}
// check for parsing errors
if( rc != kOkJsRC )
{
rc = cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Error:Reading 'loc' field on record at index %i in file:%s",i,cmStringNullGuard(fn) );
goto errLabel;
}
// if a label was given then convert it to a symbol id
if( locLabel != NULL )
{
scLocIdx = cmSymTblRegisterSymbol(stH,locLabel);
entryFlags = kLocLabelEntryFl;
}
}
if((jsRC = cmJsonMemberValues( onp, &errLabelPtr, if((jsRC = cmJsonMemberValues( onp, &errLabelPtr,
"loc", kIntTId | kOptArgJsFl, &scLocIdx,
"mod", kStringTId | kOptArgJsFl, &modLabel, "mod", kStringTId | kOptArgJsFl, &modLabel,
"var", kStringTId | kOptArgJsFl, &varLabel, "var", kStringTId | kOptArgJsFl, &varLabel,
"type",kStringTId | kOptArgJsFl, &typeLabel, "type",kStringTId | kOptArgJsFl, &typeLabel,
@ -2883,6 +3011,12 @@ cmRC_t _cmScModulatorParse( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, con
else else
prvScLocIdx = scLocIdx; prvScLocIdx = scLocIdx;
// if the flags field was not specified
if( entryFlags == cmInvalidId )
entryFlags = prvEntryFlags;
else
prvEntryFlags = entryFlags;
// if the mod label was not given use the previous one // if the mod label was not given use the previous one
if( modLabel == NULL ) if( modLabel == NULL )
modLabel = prvModLabel; modLabel = prvModLabel;
@ -2940,7 +3074,7 @@ cmRC_t _cmScModulatorParse( cmScModulator* p, cmCtx_t* ctx, cmSymTblH_t stH, con
unsigned paramCnt = cmJsonChildCount(onp); unsigned paramCnt = cmJsonChildCount(onp);
// fill the entry record and find or create the target var // fill the entry record and find or create the target var
cmScModEntry_t* ep = _cmScModulatorInsertEntry(p,i,scLocIdx,modSymId,varSymId,map->typeId,paramCnt); cmScModEntry_t* ep = _cmScModulatorInsertEntry(p,i,scLocIdx,modSymId,varSymId,map->typeId,entryFlags,paramCnt);
typedef struct typedef struct
{ {
@ -2994,6 +3128,10 @@ cmRC_t _cmScModulatorReset( cmScModulator* p, cmCtx_t* ctx, unsigned scLocIdx )
if((rc = _cmScModulatorParse(p,ctx,p->stH,p->fn)) != cmOkRC ) if((rc = _cmScModulatorParse(p,ctx,p->stH,p->fn)) != cmOkRC )
goto errLabel; goto errLabel;
_cmScProcessEntryGroups(p); // fill p->glist
_cmScProcessExecList(p); // fill p->xlist
// clear the active flag on all variables // clear the active flag on all variables
cmScModVar_t* vp = p->vlist; cmScModVar_t* vp = p->vlist;
@ -3044,6 +3182,17 @@ cmRC_t cmScModulatorFinal( cmScModulator* p )
vp=np; vp=np;
} }
// release each group record
cmScModEntryGroup_t* g = p->glist;
while( g != NULL )
{
cmScModEntryGroup_t* g0 = g->link;
cmMemFree(g->base);
cmMemFree(g);
g = g0;
}
p->glist = NULL;
return cmOkRC; return cmOkRC;
} }
@ -3149,6 +3298,22 @@ cmRC_t _cmScModGetParam( cmScModulator* p, const cmScModParam_t* pp, double* va
return rc; return rc;
} }
cmRC_t _cmScModExecEntries( cmScModulator* p, cmScModEntry_t** xparray, unsigned* idxRef, unsigned cnt, unsigned scLocIdx );
cmRC_t _cmScModExecGroup( cmScModulator* p, cmScModEntry_t* ep )
{
cmScModEntryGroup_t* g = p->glist;
for(; g!=NULL; g=g->link)
if( g->base != NULL && g->base[0]->scLocIdx == ep->beg.symId )
{
unsigned idx = 0;
return _cmScModExecEntries( p, g->base, &idx, g->n, ep->beg.symId );
}
return cmCtxRtCondition( &p->obj, cmInvalidArgRC, "Entry group '%s' not found.",cmSymTblLabel(p->stH,ep->beg.symId));
}
// Type specific variable activation - // Type specific variable activation -
cmRC_t _cmScModActivate(cmScModulator* p, cmScModEntry_t* ep ) cmRC_t _cmScModActivate(cmScModulator* p, cmScModEntry_t* ep )
{ {
@ -3191,6 +3356,10 @@ cmRC_t _cmScModActivate(cmScModulator* p, cmScModEntry_t* ep )
p->postFl = vp->value; p->postFl = vp->value;
break; break;
case kExecModTId:
rc = _cmScModExecGroup(p,ep);
break;
default: default:
{ assert(0); } { assert(0); }
} }
@ -3270,6 +3439,10 @@ bool _cmScModExec( cmScModulator* p, cmScModVar_t* vp )
sendFl = false; sendFl = false;
break; break;
case kExecModTId:
sendFl = false;
break;
default: default:
{ assert(0); } { assert(0); }
} }
@ -3290,16 +3463,21 @@ bool _cmScModExec( cmScModulator* p, cmScModVar_t* vp )
return fl; return fl;
} }
// Execute the entries in xparray[] begining with entry xparray[idx] and continuing until:
cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx ) // 1) cnt - idx entries have been executed
// 2) an entry is located whose scLocIdx != scLocIdx and also not -1
cmRC_t _cmScModExecEntries( cmScModulator* p, cmScModEntry_t** xparray, unsigned* idxRef, unsigned cnt, unsigned scLocIdx )
{ {
assert( idxRef != NULL );
cmRC_t trc; cmRC_t trc;
cmRC_t rc = cmOkRC; cmRC_t rc = cmOkRC;
unsigned idx = *idxRef;
// trigger entries that have expired since the last call to this function // trigger entries that have expired since the last call to this function
for(; p->nei<p->en && (p->earray[p->nei].scLocIdx==-1 || p->earray[p->nei].scLocIdx<=scLocIdx); ++p->nei) for(; idx<cnt && (xparray[idx]->scLocIdx==-1 || xparray[idx]->scLocIdx<=scLocIdx); ++idx)
{ {
cmScModEntry_t* ep = p->earray + p->nei; cmScModEntry_t* ep = xparray[idx];
// if the variable assoc'd with this entry is not on the active list ... // if the variable assoc'd with this entry is not on the active list ...
if( cmIsFlag(ep->varPtr->flags,kActiveModFl) == false ) if( cmIsFlag(ep->varPtr->flags,kActiveModFl) == false )
@ -3329,6 +3507,53 @@ cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx )
} }
*idxRef = idx;
return rc;
}
cmRC_t cmScModulatorExec( cmScModulator* p, unsigned scLocIdx )
{
cmRC_t rc = cmOkRC;
/*
cmRC_t trc;
// trigger entries that have expired since the last call to this function
for(; p->nei<p->xn && (p->xlist[p->nei]->scLocIdx==-1 || p->xlist[p->nei]->scLocIdx<=scLocIdx); ++p->nei)
{
cmScModEntry_t* ep = p->xlist[p->nei];
// if the variable assoc'd with this entry is not on the active list ...
if( cmIsFlag(ep->varPtr->flags,kActiveModFl) == false )
{
// ... then append it to the end of the active list ...
ep->varPtr->flags |= kActiveModFl;
if( p->elist == NULL )
p->elist = ep->varPtr;
else
{
p->elist->alink = ep->varPtr;
p->elist = ep->varPtr;
}
p->elist->alink = NULL;
if( p->alist == NULL )
p->alist = ep->varPtr;
}
// do type specific activation
if((trc = _cmScModActivate(p,ep)) != cmOkRC )
rc = trc;
ep->varPtr->entry = ep;
}
*/
rc = _cmScModExecEntries(p, p->xlist, &p->nei, p->xn, scLocIdx );
// Update the active variables // Update the active variables
cmScModVar_t* pp = NULL; cmScModVar_t* pp = NULL;
@ -3403,7 +3628,16 @@ cmRC_t cmScModulatorDump( cmScModulator* p )
for(i=0; i<p->en; ++i) for(i=0; i<p->en; ++i)
{ {
cmScModEntry_t* ep = p->earray + i; cmScModEntry_t* ep = p->earray + i;
printf("%3i %4i %2i %7s ", i, ep->scLocIdx, ep->typeId, cmSymTblLabel(p->stH,ep->varPtr->varSymId)); const _cmScModTypeMap_t* tm = _cmScModTypeIdToMap( ep->typeId );
printf("%3i ",i);
if( cmIsFlag(ep->flags,kLocLabelEntryFl) )
printf("%10s ",cmSymTblLabel(p->stH,ep->scLocIdx));
else
printf("%10i ",ep->scLocIdx);
printf("%5s %7s", tm==NULL ? "invld" : tm->label, cmSymTblLabel(p->stH,ep->varPtr->varSymId));
_cmScModDumpParam(p," beg", &ep->beg); _cmScModDumpParam(p," beg", &ep->beg);
_cmScModDumpParam(p," end", &ep->end); _cmScModDumpParam(p," end", &ep->end);
_cmScModDumpParam(p," min", &ep->min); _cmScModDumpParam(p," min", &ep->min);

View File

@ -425,6 +425,7 @@ extern "C" {
line = ramp from its current value to <val> over <dur> seconds line = ramp from its current value to <val> over <dur> seconds
sline = set <var> to <val> and ramp to <end> over <dur> seconds sline = set <var> to <val> and ramp to <end> over <dur> seconds
post = send a 'post' msg after each transmission (can be used to change the cross-fader after each msg) post = send a 'post' msg after each transmission (can be used to change the cross-fader after each msg)
exec = execute the entry group <val>
*/ */
enum enum
@ -435,6 +436,7 @@ extern "C" {
kLineModTId, // linear ramp variable to parray[0] over parray[1] seconds kLineModTId, // linear ramp variable to parray[0] over parray[1] seconds
kSetLineModTId, // set variable to parray[0] and ramp to parray[1] over parray[2] seconds kSetLineModTId, // set variable to parray[0] and ramp to parray[1] over parray[2] seconds
kPostModTId, // kPostModTId, //
kExecModTId // execute an entry group
}; };
enum enum
@ -475,12 +477,13 @@ extern "C" {
struct cmScModVar_str* alink; // p->alist link struct cmScModVar_str* alink; // p->alist link
} cmScModVar_t; } cmScModVar_t;
enum { kLocLabelEntryFl = 0x01 };
// Each entry gives a time tagged location and some parameters // Each entry gives a time tagged location and some parameters
// for an algorthm which is used to set/modulate a value. // for an algorthm which is used to set/modulate a value.
typedef struct cmScModEntry_str typedef struct cmScModEntry_str
{ {
unsigned flags; // { kLocLabelEntryFl }
unsigned scLocIdx; // entry start time unsigned scLocIdx; // entry start time
unsigned typeId; // variable type unsigned typeId; // variable type
cmScModParam_t beg; // parameter values cmScModParam_t beg; // parameter values
@ -492,6 +495,13 @@ extern "C" {
cmScModVar_t* varPtr; // target variable cmScModVar_t* varPtr; // target variable
} cmScModEntry_t; } cmScModEntry_t;
typedef struct cmScModEntryGroup_str
{
cmScModEntry_t** base;
unsigned n;
struct cmScModEntryGroup_str* link;
} cmScModEntryGroup_t;
typedef void (*cmScModCb_t)( void* cbArg, unsigned varSymId, double value, bool postFl ); typedef void (*cmScModCb_t)( void* cbArg, unsigned varSymId, double value, bool postFl );
typedef struct typedef struct
@ -512,6 +522,9 @@ extern "C" {
unsigned nei; // next entry index unsigned nei; // next entry index
unsigned outVarCnt; // count of unique vars that are targets of entry recds unsigned outVarCnt; // count of unique vars that are targets of entry recds
bool postFl; // send a 'post' msg after each transmission bool postFl; // send a 'post' msg after each transmission
cmScModEntry_t** xlist;
unsigned xn;
cmScModEntryGroup_t* glist;
} cmScModulator; } cmScModulator;